著者:飯尾 淳
本連載では「Pythonを昔から使っているものの、それほど使いこなしてはいない」という筆者が、いろいろな日常業務をPythonで処理することで、立派な「蛇使い」に育つことを目指します。その過程を温
かく見守ってください。皆さんと共に勉強していきましょう。第13回では、PyTorchという機械学習ライブラリを使って、手書きの数字を画像認識によって分類してみます。実際に作業することで、機械学習の効果を感じてください。
シェルスクリプトマガジン Vol.83は以下のリンク先でご購入できます。
図1 MNISTデータセットをダウンロードするためのコード
1 2 3 4 5 6 7 8 9 |
data_folder = '~/data' BATCH_SIZE = 8 mnist_data = MNIST(data_folder, train=True, download=True, transform=transforms.ToTensor()) data_loader = DataLoader(mnist_data, batch_size=BATCH_SIZE, shuffle=False) |
図4 MNISTデータセットのデータを1セット表示するコード
1 2 3 4 5 6 7 8 9 10 |
data_iterator = iter(data_loader) images, labels = next(data_iterator) # 最初の画像を表示 location = 0 # 画像データを28×28画素のデータに変換して表示 data = images[location].numpy() reshaped_data = data.reshape(28, 28) plt.imshow(reshaped_data, cmap='inferno', interpolation='bicubic') plt.show() print('ラベル:', labels[location]) |
図6 学習データと検証データを用意するコード
1 2 3 4 5 6 7 8 9 10 |
# 学習データ train_data_loader = DataLoader( MNIST(data_folder, train=True, download=True, transform=transforms.ToTensor()), batch_size=BATCH_SIZE, shuffle=True) # 検証データ test_data_loader = DataLoader( MNIST(data_folder, train=False, download=True, transform=transforms.ToTensor()), batch_size=BATCH_SIZE, shuffle=True) |
図9 ニューラルネットワークモデルを定義するコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
from torch.autograd import Variable import torch.nn as nn # 親クラスのnn.Moduleを継承してモデルを作成 class MLP(nn.Module): def __init__(self): super().__init__() self.layer1 = nn.Linear(28 * 28, 100) self.layer2 = nn.Linear(100, 50) self.layer3 = nn.Linear(50, 10) def forward(self, input_data): input_data = input_data.view(-1, 28 * 28) input_data = self.layer1(input_data) input_data = self.layer2(input_data) input_data = self.layer3(input_data) return input_data |
図11 学習前の準備をするコード
1 2 3 4 5 6 7 |
import torch.optim as optimizer # モデルの作成 model = MLP() # 評価器(誤差項)と最適化器の作成 lossResult = nn.CrossEntropyLoss() optimizer = optimizer.SGD(model.parameters(), lr=0.01) |
図12 画像認識の精度を検証するコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import torch # 検証した数と正解の数 total = 0 count_when_correct = 0 for data in test_data_loader: test_data, teacher_labels = data results = model(Variable(test_data)) _, predicted = torch.max(results.data, 1) total += teacher_labels.size(0) count_when_correct += (predicted == teacher_labels).sum() rate = int(count_when_correct) / int(total) print(f'count_when_correct:{count_when_correct}') print(f'total:{total}') print(f'正解率:{count_when_correct} / {total} = {rate}') |
図13 モデルを学習させるコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# 最大学習回数 MAX_EPOCH = 4 for epoch in range(MAX_EPOCH): total_loss = 0.0 for i, data in enumerate(train_data_loader): train_data, teacher_labels = data train_data, teacher_labels = \ Variable(train_data), Variable(teacher_labels) # 勾配情報をリセット optimizer.zero_grad() outputs = model(train_data) loss = lossResult(outputs, teacher_labels) loss.backward() # 勾配を更新 optimizer.step() # 誤差を積み上げる total_loss += loss.data if i % 2000 == 1999: print(f'学習進捗:[{epoch+1}, {i+1}]', end='') print(f'学習誤差(loss): {total_loss / 2000:.3f}') total_loss = 0.0 print('学習終了') |
図15 個別の判定結果を確認するコード
1 2 3 4 5 6 7 8 9 10 |
# データの取得と検証 test_iterator = iter(test_data_loader) test_data, teacher_labels = next(test_iterator) results = model(Variable(test_data)) _, predicted_label = torch.max(results.data, 1) # 最初のデータを検証して画像を表示 location = 0 plt.imshow(test_data[location].numpy().reshape(28, 28), cmap='inferno', interpolation='bicubic') print('ラベル:', predicted_label[location]) |