モデルの訓練の様子が視覚化できるみたいですね。
今まではmatplotlibでやっていたけれど、TensorBoardに書き込むともっと詳しい情報が見られるみたい。
ローカル環境にて実行することで、TensorBoardも順調に動いています。利用方法もだいぶ慣れてきました。引き続きチュートリアルを行っていきます。
今回は、「5. Tracking model training with TensorBoard」の項目から進めていきます。チュートリアルでは、CPUでのみ実行しているようでしたので、GPUでの実行もチャレンジしてみました。チュートリアルのプログラムそのままではないですが、PyTorchのGPUで実行するときのコツを掴めた気がします。
こんな人の役に立つかも
・機械学習プログラミングを勉強している人
・PyTorchのチュートリアルをしている人
・PyTorchでTensorBoardを利用したい人
5.訓練のトラッキングをする
チュートリアルのプログラム
ヘルパー関数として次のプログラムを実行しておきます。このヘルパー関数は、TensorBoardに、1000ミニバッチ毎に1ミニバッチ分の画像とモデルの正答率を書き出すために利用されます。「images_to_probs」は「plot_classes_preds」に呼ばれるので、このブロックで一つの書き出しの機能を実現しています。
次の図ように、チェックポイント毎のミニバッチ画像の正解率と画像を表示するようにできます。
#ヘルパー関数
def images_to_probs(net, images):
'''
ニューラルネットに画像を入れて、予測を行い、出力である確率を取得します。
'''
output = net(images)
#ニューラルネットの出力で最大の値の確率値を取得
_, preds_tensor = torch.max(output, 1)
preds = np.squeeze(preds_tensor.numpy())#tensorからnumpyに
return preds, [F.softmax(el, dim=0)[i].item() for i, el in zip(preds, output)]
def plot_classes_preds(net, images, labels):
'''
「images_to_probs」関数の予測値に、matplotlibの図を生成し加えます。
'''
preds, probs = images_to_probs(net, images)
#予測と正解を一緒にしてミニバッチのデータをプロットします。
fig = plt.figure(figsize=(12, 48))
for idx in np.arange(4):
ax = fig.add_subplot(1, 4, idx+1, xticks=[], yticks=[])
matplotlib_imshow(images[idx], one_channel=True)
ax.set_title("{0}, {1:.1f}%\n(label: {2})".format(
classes[preds[idx]],
probs[idx] * 100.0,
classes[labels[idx]]),
color=("green" if preds[idx]==labels[idx].item() else "red"))
return fig
チュートリアルでは、CPU実行でしたので、GPUで実行するときもチャレンジしてみました。
PCにNVIDIAのCUDAが利用できるGPUが搭載されている場合、GPUを利用することもできます。GPUで実行する場合、以下の【GPU】の部分以下のプログラムのコメントアウトを外し、【CPU】のプログラムをコメントアウトします。
#【GPU】
#device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
#net.to(device)
#【CPU】
net.cpu()
GPUで実行する場合、再度以下のプログラムを実行しておきます。(コメントアウトは外します。)
#GPUで実行する場合、再度実行
#criterion = nn.CrossEntropyLoss()
#optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
最後に、前のチュートリアルと同じモデルトレーニングコードを使用してモデルをトレーニングを行います。
コンソールに出力するのではなく、1000バッチごとに結果をTensorBoardに書き込みます。これは、add_scalar関数を使用して行われます。
さらに、トレーニング中に、モデルの予測と、そのバッチに含まれる4つの画像の実際の結果を示す画像を生成します。(一番最初のヘルパー関数を利用)
running_loss = 0.0
#訓練ループ
for epoch in range(1):
#ミニバッチループ
for i, data in enumerate(trainloader, 0):
#入力データ。「data」は [inputs, labels]のリスト。
#【GPU】
#inputs, labels = data[0].to(device) , data[1].to(device)
#【CPU】
inputs, labels = data#CPU
#勾配の初期化
optimizer.zero_grad()
#順伝播、誤差計算、逆伝播、最適化を行います。
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
#損失の計算を行い、変数「runnning_loss」に累積
running_loss += loss.item()
if i % 1000 == 999: #1000ミニバッチ毎に処理(画像4000枚ごと)
#TensorBoardに1000ミニバッチの損失平均を書き込みます
#add_scalarには、「データ名」「Y軸データの値」「X軸データ」で与えています。
#X軸のデータとして、ミニバッチ数を計算しています。
writer.add_scalar('training loss',
running_loss / 1000,
epoch * len(trainloader) + i)
#「predictions vs. actuals」を作成します。
#1000ミニバッチ毎にひとつのミニバッチの正解を視覚的に表示します。
writer.add_figure('predictions vs. actuals',
#【GPU】
#plot_classes_preds(net.cpu(), inputs.cpu(), labels.cpu()),#GPU利用時ここではCPUで処理
#【CPU】
plot_classes_preds(net, inputs, labels),
global_step=epoch * len(trainloader) + i)
#【GPU】
#net.cuda(), inputs.cuda(), labels.cuda()
print("チェックポイント")
#「running_loss」変数の初期化
running_loss = 0.0
print('Finished Training')
TensorBoardでの確認
訓練を行なった後、ブラウザで表示されているTensorBoardをリロードします。すると、「SCALARS」というタブに、訓練の損失が視覚化されるようになります。
また、「images」タブを開くと、「predictions vs. actuals」という項目に、一番最初に図としてみたチェックポイント毎のミニバッチ画像に対する正解または不正解が表示されています。(画像自体は結構下にスクロールしないと出てこないです。)
1000ミニバッチ毎に処理を行なっているはずなのですが、上のスライダーは適度に飛ばされていて、1000ミニバッチ毎ではない感じです。この「step」何ですが、「add_figure」関数の「global_step」というパラメータに渡す値で、受け取る値はint型となります。intにキャストして実行してみましたが、適度に飛ばされます(表示されるstep数は変わりました。)。全体として8回のポイントで見ることができるようになります。(詳細にどのように動作しているかはよくわかりませんでした。)
GitHubに、チュートリアルの最初から実行できるプログラムを配置しています。実行時にご参考ください。本記事のチュートリアルは「5.」が該当します。
続きの記事はこちらになります。