この記事の内容
ブラウザで Deep Learning が 試せるサービス「Colaboratory」で
ディープラーニングを試す方法を紹介します。
題材はディープラーニング界の"Hello World"、「MNIST」です。
なお、このチュートリアルで必要なディープラーニングの最低限必要な知識については「ディープラーニング入門への最小知識」で解説しています
MNISTとは
- ディープラーニングのチュートリアル用の画像データ集です
- この画像から書かれている数字を判定するAIを作ってみます
Colaboratoryとは
- ブラウザで Deep Learning が試せるサービスです
- Googleのサービスです
- 無料です
- GPUが12時間無料で使えます。(K80という古いものです)
-
pip install
が出来るのでどんなフレームワーク(AI作成ライブラリ)でも試せます- 今回は
PyTorch
を使います
- 今回は
Colaboratoryの学習環境セットアップ
Colaboratoryの使い方
Colaboratoryの挙動がおかしくなったら
AI作成してみよう
以下に出てくるコードを適宜Colaboratory上にコピペ・実行してください
フレームワークインストール
- フレームワークにはPyTorchを使ってみます。次のコマンドでColaboratoryにインストールしてください
!pip3 install torch torchvision
データの読み込み
-
PyTorchにはMNISTデータを読み込むライブラリが存在します。これでMNISTデータのダウンロードと読み込みをします。
import torchvision.transforms as transforms from torch.utils.data import DataLoader from torchvision.datasets import MNIST # 訓練データとテストデータを用意 train_data = MNIST('~/tmp/mnist', train=True, download=True, transform=transforms.ToTensor()) train_loader = DataLoader(train_data, shuffle=True) test_data = MNIST('~/tmp/mnist', train=False, download=True, transform=transforms.ToTensor()) test_loader = DataLoader(test_data, shuffle=False)
- コードについて
-
train=True
: MNISTの中で学習用、テスト用に既にデータが分かれています。読み込み時に学習用かテスト用か指定します -
transform=transforms.ToTensor()
: 読み込み後に画像データを行列に変換します。この時点では(28,28)の2次元配列です
-
- コードについて
モデルを定義
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super().__init__()
self.l1 = nn.Linear(28 * 28, 50) # 入力層から隠れ層へ
self.l2 = nn.Linear(50, 10) # 隠れ層から出力層へ
def forward(self, inputs):
o0 = inputs.view(1, 28 * 28) # テンソルのリサイズ
o1 = self.l1(o0)
o2 = self.l2(o1)
return o2
net = Net()
- コードについて
-
class Net(nn.Module):
: PyTorchのニューラルネットクラスを継承してニューラルネットを定義します。 -
def forward(self, inputs):
: 入力を与えたときの計算方法を指定しています-
inputs.view(1, 28 * 28)
: 入力が2次元配列なので、ニューラルネットに入れるために28*28=784の1次元配列に変換しています
-
-
このニューラルネットの出力は要素数10の配列です。配列内で最も大きい数値をもつインデックスが判定結果です。
- 例えば、
output = [1,-2,3,7,100,4,6,7,3,2]
の場合はoutput[5]
が最も大きいので5
が判定結果です
- 例えば、
-
学習方法の指定
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01)
- 損失関数(criterion)には「クロスエントロピー」を用います
- 重み更新には
SGD
を使用します- 学習率
lr
は0.01にしています
- 学習率
学習実行
for i, data in enumerate(train_loader):
inputs, labels = data
# 勾配情報をリセット
optimizer.zero_grad()
# 入力を与える
outputs = net(inputs)
# 損失関数を使って損失を計算する
loss = criterion(outputs, labels)
# 勾配計算
loss.backward()
# 重みの更新
optimizer.step()
print('Finished Training')
-
enumerate(train_loader)
: 学習用画像を一枚ずつ取り出してループを回します- 取り出したデータから
inputs, labels = data
として画像とラベルを取り出しています
- 取り出したデータから
- 実行すると1分ほどで
'Finished Training'
が出力されます
テストする
import torch
correct = 0
total = 0
for data in test_loader:
inputs, labels = data
outputs = net(inputs)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum()
print('Accuracy %d / %d = %f' % (correct, total, float(correct) / total))
- 実行するとテストデータで判定した結果の精度が見れます
テストデータ画像と判定結果のペアを表示
import matplotlib.pyplot as plt
test_iter = iter(test_loader)
inputs, labels = test_iter.next()
outputs = net(inputs)
_, predicted = torch.max(outputs.data, 1)
plt.imshow(inputs[0].numpy().reshape(28, 28), cmap='gray')
print('判定結果', predicted[0])
ちゃんと7の画像を7と判定できたようです
備考
-
普通のAI開発でやるであろうことを大量に割愛しています。
- バッチ
- エポック
- 画像の正規化
- エポック内で学習後にテストを行う。ステップごとに精度を計る
- 等...
-
MNISTの参考モデルはBasic MNIST Exampleにあります
参考にしたサイト
https://www.madopro.net/entry/pytorch_mnist
https://stackoverflow.com/questions/41990250/what-is-cross-entropy
http://nkdkccmbr.hateblo.jp/entry/2016/10/06/222245
http://cookie-box.hatenablog.com/entry/2017/05/07/121607