著者:飯尾 淳
本連載では「Pythonを昔から使っているものの、それほど使いこなしてはいない」という筆者が、いろいろな日常業務をPythonで処理することで、立派な「蛇使い」に育つことを目指します。その過程を温
かく見守ってください。皆さんと共に勉強していきましょう。第13回では、PyTorchという機械学習ライブラリを使って、手書きの数字を画像認識によって分類してみます。実際に作業することで、機械学習の効果を感じてください。
シェルスクリプトマガジン Vol.83は以下のリンク先でご購入できます。![]()
![]()
図1 MNISTデータセットをダウンロードするためのコード
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セット表示するコード
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 学習データと検証データを用意するコード
# 学習データ
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 ニューラルネットワークモデルを定義するコード
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 学習前の準備をするコード
import torch.optim as optimizer
# モデルの作成
model = MLP()
# 評価器(誤差項)と最適化器の作成
lossResult = nn.CrossEntropyLoss()
optimizer = optimizer.SGD(model.parameters(), lr=0.01)
図12 画像認識の精度を検証するコード
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 モデルを学習させるコード
# 最大学習回数
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 個別の判定結果を確認するコード
# データの取得と検証
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])