AWS GPUを搭載したEC2インスタンスを用いた行列計算と深層学習(2/2)


 
前回の行列計算に続いて今回は手書きの数字を識別する深層学習を行いました。
 
スタックのデプロイやJupyter Notebookの起動などは前回の続きから行うので詳しい準備内容は下記の記事にまとめています。
 
nissin-geppox.hatenablog.com




 

テストデータのダウンロード

 
まず、今回コードを書いていく新しいノートブックと使用するファイルをアップロードしました。
 
新しいノートブックは"conda_pytorch_p36"で作成し、アップロードするファイルはhandon/mnist/pytorch/ディレクトリ内にある"simple_mnist.py"をアップロードしました。

 
次に起動したノートブックに必要なライブラリをインポートしました。

入力

import torch
import torch.optim as optim
import torchvision
from torchvision import datasets, transforms
from matplotlib import pyplot as plt

# custom functions and classes
from simple_mnist import Model, train, evaluate

 
次にテストデータをダウンロードしました。また、画像データの輝度の正規化も行いました。
入力

transf = transforms.Compose([transforms.ToTensor(),
                            transforms.Normalize((0.1307,), (0.3081,))])
trainset = datasets.MNIST(root='./data', train=True, download=True, transform=transf)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)

testset = datasets.MNIST(root='./data', train=False, download=True, transform=transf)
testloader = torch.utils.data.DataLoader(testset, batch_size=1000, shuffle=True)

 
最後に、ダウンロードした正方形の画像データをいくつか出力しました。

入力

examples = iter(testloader)
example_data, example_targets = examples.next()

print("Example data size:", example_data.shape)

fig = plt.figure(figsize=(10,4))
for i in range(10):
    plt.subplot(2,5,i+1)
    plt.tight_layout()
    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    plt.title("Ground Truth: {}".format(example_targets[i]))
    plt.xticks([])
    plt.yticks([])
plt.show()

出力

この画像より、画像データが正常にダウンロードされたことを確認することができました。




 

画像の識別

 
ダウンロードした画像データの数字をCNNを用いて識別しました。

 
まず、CNNのモデルを定義しました。

入力

model = Model()
model.to("cuda") # load to GPU


次にCNNのパラメータを更新する最適化するアルドリズムを定義しました。

入力

optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)


次にCNNの学習ループを行いました。

入力

train_losses = []
for epoch in range(5):
    losses = train(model, trainloader, optimizer, epoch)
    train_losses = train_losses + losses
    test_loss, test_accuracy = evaluate(model, testloader)
    print(f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {test_accuracy:.1f}%\n")

plt.figure(figsize=(7,5))
plt.plot(train_losses)
plt.xlabel("Iterations")
plt.ylabel("Train loss")
plt.show()

出力

この画像のグラフは損失関数の値の推移を表しています。学習が進むにつれて値は減少していき、最終的な精度は98.6%になることが確認できます。
 
最後に学習結果を出力しました。

入力

model.eval()

with torch.no_grad():
    output = model(example_data.to("cuda"))

fig = plt.figure(figsize=(10,4))
for i in range(10):
    plt.subplot(2,5,i+1)
    plt.tight_layout()
    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    plt.xticks([])
    plt.yticks([])
plt.show()

出力

この画像より、出力されたすべての画像が正しく識別されているこを確認することができました。

 
また、今回学習したニューラルネットワークのパラメータを保存することができます。

入力

torch.save(model.state_dict(), "mnist_cnn.pt")


 

スタックの削除

 
スタックの削除は以下のコマンドより行うことができます。

$ cdk destroy