Digit Recognizerに挑戦
KaggleのDigit Recognizerに挑戦します。
使用言語は、Pythonです。
学習のモデルは”CNN”を使うので、ニューラルネットワークのライブラリ”PyTorch”を使っていきます。
※私的に、Kerasが一番簡単にモデルを構築できると思います。
プログラムの解説
ここでは、次の順でソースコードを分けて紹介します。
- インポートするリスト
- 訓練データの読み込み
- 訓練データの前処理
- ネットワークの構築
- 学習
- 学習結果
- テストデータの読み込み
- ラベルの推測
- 提出ファイル作成
インポートするもの
import time import numpy as np import pandas as pd import torch from torch import nn, optim from torch.utils.data import Dataset, DataLoader,TensorDataset from sklearn.model_selection import train_test_split import matplotlib.pyplot as plt %matplotlib inline
訓練データの読み込み&前処理
train = pd.read_csv('train.csv') X = train.drop('label', axis=1).values y = train.label.values X = X.reshape(-1, 1, 28, 28) X = X/255 train_X, val_X, train_y, val_y = train_test_split(X, y, test_size=0.2, random_state=0) train_X = torch.tensor(train_X, dtype=torch.float32) train_y = torch.tensor(train_y, dtype=torch.int64) val_X= torch.tensor(val_X, dtype=torch.float32) val_y = torch.tensor(val_y, dtype=torch.int64) train_set = torch.utils.data.TensorDataset(train_X,train_y) test_set = torch.utils.data.TensorDataset(val_X, val_y) batch_sizes = 128 train_loader = torch.utils.data.DataLoader(train_set, batch_size = batch_sizes, shuffle = False) test_loader = torch.utils.data.DataLoader(test_set, batch_size = batch_sizes, shuffle = False)
ネットワークの構築
class net(nn.Module): def __init__(self): super(net,self).__init__() #畳み込み層 self.conv_layers = nn.Sequential( nn.Conv2d(in_channels = 1, out_channels = 32, kernel_size = 5, stride=1, padding=0), nn.ReLU(), nn.Conv2d(in_channels = 32, out_channels = 32, kernel_size = 5, stride=1, padding=0), nn.ReLU(), nn.MaxPool2d(kernel_size = 2, stride=2), nn.Dropout(p=0.25), nn.Conv2d(in_channels = 32, out_channels = 64, kernel_size = 3, stride=1, padding=0), nn.ReLU(), nn.Conv2d(in_channels = 64, out_channels = 64, kernel_size = 3, stride=1, padding=0), nn.ReLU(), nn.MaxPool2d(kernel_size = 2, stride=2), nn.Dropout(p=0.25) ) #全結合層 self.dence = nn.Sequential( nn.Linear(64 * 3 *3, 256), nn.Dropout(p=0.5), #nn.Linear(256, 128), #nn.Dropout(p=0.25), nn.Linear(256, 10) ) #順伝播 def forward(self,x): out = self.conv_layers(x) #Flatten out = out.view(out.size(0), -1) #全結合層 out = self.dence(out) return out #畳み込み層の出力サイズのチェック def check_cnn_size(self, size_check): out = self.conv_layers(size_check) return out
デバイスチェック
device = 'cuda' if torch.cuda.is_available() else 'cpu' net = net().to(device)
畳み込み層の出力サイズチェック
size_check = torch.FloatTensor(10, 1, 28, 28) size_check = size_check.to(device) print(net.check_cnn_size(size_check).size())
損失関数と最適化
#損失関数 criterion = nn.CrossEntropyLoss() #最適化 optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9, weight_decay=5e-4)
学習
num_epochs =30 train_loss_list = [] train_acc_list = [] val_loss_list = [] val_acc_list = [] start = time.time() for epoch in range(num_epochs): train_loss = 0 train_acc = 0 val_loss = 0 val_acc = 0 #train net.train() for i, (images, labels) in enumerate(train_loader): images, labels = images.to(device), labels.to(device) optimizer.zero_grad() outputs = net.forward(images) loss = criterion(outputs, labels) train_loss += loss.item() train_acc += (outputs.max(1)[1] == labels).sum().item() loss.backward() optimizer.step() avg_train_loss = train_loss / len(train_loader.dataset) avg_train_acc = train_acc / len(train_loader.dataset) #val net.eval() with torch.no_grad(): for images, labels in test_loader: images = images.to(device) labels = labels.to(device) outputs = net.forward(images) loss = criterion(outputs, labels) val_loss += loss.item() val_acc += (outputs.max(1)[1] == labels).sum().item() avg_val_loss = val_loss / len(test_loader.dataset) avg_val_acc = val_acc / len(test_loader.dataset) print ('Epoch [{}/{}], Loss: {loss:.4f}, val_loss: {val_loss:.4f}, val_acc: {val_acc:.4f}' .format(epoch+1, num_epochs, i+1, loss=avg_train_loss, val_loss=avg_val_loss, val_acc=avg_val_acc)) train_loss_list.append(avg_train_loss) train_acc_list.append(avg_train_acc) val_loss_list.append(avg_val_loss) val_acc_list.append(avg_val_acc) print(time.time() - start)
学習結果
plt.plot(train_acc_list, label='Training loss') plt.plot(val_acc_list, label='Validation loss') plt.legend();
テストデータの読み込みと前処理
test = pd.read_csv('test.csv') test = test.values test = test.reshape(-1, 1, 28, 28) test = test/255 batch_sizes = 1 test = torch.tensor(test, dtype=torch.float32) test_sets = torch.utils.data.TensorDataset(test) new_test_loader = torch.utils.data.DataLoader(test, batch_size = batch_sizes, shuffle = False)
ラベルの推測
pred_list = [] start = time.time() with torch.no_grad(): net.eval() c = 0 for images in new_test_loader: images = images.to(device) output = net.forward(images) _, pred = torch.max(output.data, 1) pred_list.append(pred.item()) print(time.time() - start)
提出用ファイルの作成
pred_list = np.array(pred_list) ID_lists= np.arange(1, pred_list.shape[0]+1) submissions=pd.DataFrame({"ImageId": ID_lists, "Label": pred_list}) submissions.to_csv("submissions.csv", index=False, header=True)
Kaggleのテスト結果
Kaggleでの、本番のテスト結果は、
0.98428
でした。
最高スコアが、1.00になっています。。。
全問正解、つまり、acc=100%
過学習なしのこの結果って。。。
Kernel見て、勉強します。。。