PyTorch 1.5 : PyTorch の学習 : TensorBoard でモデル、データと訓練を可視化する (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 05/07/2020 (1.5.0)
* 本ページは、PyTorch 1.5 Tutorials の以下のページを翻訳した上で適宜、補足説明したものです:
- Learning PyTorch : Visualizing Models, Data, and Training with TensorBoard
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
- Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション |
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/ |
Facebook: https://www.facebook.com/ClassCatJP/ |
PyTorch の学習 : TensorBoard でモデル、データと訓練を可視化する
60 Minute Blitz では、どのようにデータを読み込み、それを nn.Module のサブクラスとして定義するモデルを通してそれを供給し、訓練データ上でこのモデルを訓練し、そしてそれをテストデータ上でテストするかを貴方に示しました。何が起きているか見るため、訓練が進んでいるかのための感覚を得るためモデルが訓練されるとき幾つかの統計情報をプリントアウトしました。けれども、それよりも遥かに上手くやることができます : PyTorch は TensorBoard と統合しています、ニューラルネットワーク訓練実行の結果を可視化するために設計されたツールです。このチュートリアルは Fashion-MNIST データセット を利用してその機能の幾つかを示します、これは torchvision.datasets を使用して PyTorch に読み込めます。
このチュートリアルでは、以下をどのように行なうかを学習します :
- データを読みそして適切な変換を伴う (前のチュートリアルに近いです)。
- TensorBoard をセットアップする。
- TensorBoard に書く。
- TensorBoard を使用してモデル・アーキテクチャを調べる。
- より少ないコードで、最後のチュートリアルで作成した可視化の対話的バージョンを作成するために TensorBoard を使用します。
特に、ポイント #5 で、以下を見ます :
- 訓練データを調べるための 2, 3 の方法
- モデルのそれが訓練されるときのパフォーマンスをどのように追跡するか
- モデルのパフォーマンスをそれがひとたび訓練されればどのように評価するか。
CIFAR-10 チュートリアル 内のものと類似のボイラープレートから始めます :
# imports import matplotlib.pyplot as plt import numpy as np import torch import torchvision import torchvision.transforms as transforms import torch.nn as nn import torch.nn.functional as F import torch.optim as optim # transforms transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))]) # datasets trainset = torchvision.datasets.FashionMNIST('./data', download=True, train=True, transform=transform) testset = torchvision.datasets.FashionMNIST('./data', download=True, train=False, transform=transform) # dataloaders trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2) testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2) # constant for classes classes = ('T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle Boot') # helper function to show an image # (used in the `plot_classes_preds` function below) def matplotlib_imshow(img, one_channel=False): if one_channel: img = img.mean(dim=0) img = img / 2 + 0.5 # unnormalize npimg = img.numpy() if one_channel: plt.imshow(npimg, cmap="Greys") else: plt.imshow(np.transpose(npimg, (1, 2, 0)))
そのチュートリアルから類似のモデル・アーキテクチャを定義し、今では画像が 3 の代わりに 1 チャネルで 32×32 の代わりに 28×28 である事実を説明するために小さい変更だけを行ないます :
class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 6, 5) self.pool = nn.MaxPool2d(2, 2) self.conv2 = nn.Conv2d(6, 16, 5) self.fc1 = nn.Linear(16 * 4 * 4, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) def forward(self, x): x = self.pool(F.relu(self.conv1(x))) x = self.pool(F.relu(self.conv2(x))) x = x.view(-1, 16 * 4 * 4) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x net = Net()
前のと同じ optimizer と criterion (基準) を定義します :
criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
1. TensorBoard セットアップ
今は TensorBoard をセットアップし、torch.utils から tensorboard をインポートして SummaryWriter を定義します、情報を TensorBoard に書くためのキーオブジェクトです。
from torch.utils.tensorboard import SummaryWriter # default `log_dir` is "runs" - we'll be more specific here writer = SummaryWriter('runs/fashion_mnist_experiment_1')
この行は単独で runs/fashion_mnist_experiment_1 フォルダを作成することに注意してください。
2. TensorBoard に書く
今は画像を TensorBord に書きましょう – 特に、グリッド – make_grid を使用して。
# get some random training images dataiter = iter(trainloader) images, labels = dataiter.next() # create grid of images img_grid = torchvision.utils.make_grid(images) # show images matplotlib_imshow(img_grid, one_channel=True) # write to tensorboard writer.add_image('four_fashion_mnist_images', img_grid)
今は次をコマンドラインから実行して :
tensorboard --logdir=runs
そして https://localhost:6006 にナビゲートすると以下を表示します :
今では貴方はどのように TensorBoard を利用するか知りました!けれども、この例は Jupyter ノートブックで成されるでしょう – そこでは TensorBoard は対話的可視化を作成するという点で優れています。次にそれらの一つを、そしてチュートリアルの終わりまでには幾つかをカバーします。
3. TensorBoard を使用してモデルを調べる
TensorBoard の強みの一つは複雑なモデル構造を可視化する能力です。
構築したモデルを可視化しましょう。
writer.add_graph(net, images) writer.close()
TensorBoard をリフレッシュした今、このように見える “Graphs” タブを見るはずです :
続けてそれを展開するために “Net” 上をダブルクリックすると、モデルを作り上げる個々の演算の詳細なビューを見ます。
TensoBoard はより低位の次元空間で画像データのような高位次元データを可視化するための非常に手軽な特徴を持ちます ; これを次にカバーします。
“Projector” を TensorBoard に追加する
add_embedding メソッドを通して高位次元データの低位次元表現を可視化できます。
# helper function def select_n_random(data, labels, n=100): ''' Selects n random datapoints and their corresponding labels from a dataset ''' assert len(data) == len(labels) perm = torch.randperm(len(data)) return data[perm][:n], labels[perm][:n] # select random images and their target indices images, labels = select_n_random(trainset.data, trainset.targets) # get the class labels for each image class_labels = [classes[lab] for lab in labels] # log embeddings features = images.view(-1, 28 * 28) writer.add_embedding(features, metadata=class_labels, label_img=images.unsqueeze(1)) writer.close()
今では TensorBoard の “Projector” タブでは、これらの 100 画像を見ることができて – それらの各々は 784 次元です – 3 次元空間に低位に射影されています。更に、これらは対話的です : 3 次元射影を回転するためにクリックしてドラッグできます。最後に、可視化を容易に見るための 2 つの tips を: 左上の “color: label” を選択し、”night mode” を有効にします、これは画像を見やすくします、何故ならば背景が白色だからです :
今ではデータを徹底的に調べました、TensorBoard がモデル訓練と評価の追跡をどのように明瞭にできるかを示します、訓練から始めます。
5. モデル訓練を TensorBoard で追跡する
前の例では、モデルの実行損失を単純に 2000 反復毎にプリントしました。今は、代わりに実行損失を TensorBoard にログ記録します、plot_classes_preds 関数を通してモデルが作成する予測へのビューと一緒に。
# helper functions def images_to_probs(net, images): ''' Generates predictions and corresponding probabilities from a trained network and a list of images ''' output = net(images) # convert output probabilities to predicted class _, preds_tensor = torch.max(output, 1) preds = np.squeeze(preds_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): ''' Generates matplotlib Figure using a trained network, along with images and labels from a batch, that shows the network's top prediction along with its probability, alongside the actual label, coloring this information based on whether the prediction was correct or not. Uses the "images_to_probs" function. ''' preds, probs = images_to_probs(net, images) # plot the images in the batch, along with predicted and true labels 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
最後に、前のチュートリアルからのものと同じモデル訓練コードを仕様してモデルを訓練しましょう、しかしコンソールにプリントする代わりに 100 バッチ毎に TensorBoard に結果を書きます ; これは add_scalar 関数を使用して成されます。
更に、訓練するとき、そのバッチに含まれる 4 つの画像上でモデルの予測 vs. 実際の結果を示す画像を生成します。
running_loss = 0.0 for epoch in range(1): # loop over the dataset multiple times for i, data in enumerate(trainloader, 0): # get the inputs; data is a list of [inputs, labels] inputs, labels = data # zero the parameter gradients optimizer.zero_grad() # forward + backward + optimize outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() if i % 1000 == 999: # every 1000 mini-batches... # ...log the running loss writer.add_scalar('training loss', running_loss / 1000, epoch * len(trainloader) + i) # ...log a Matplotlib Figure showing the model's predictions on a # random mini-batch writer.add_figure('predictions vs. actuals', plot_classes_preds(net, inputs, labels), global_step=epoch * len(trainloader) + i) running_loss = 0.0 print('Finished Training')
今では訓練の 15,000 反復に渡りプロットされた実行損失を見るために scalars タブを見ることができます :
更に、学習を通して任意のバッチ上でモデルが作成した予測を見ることができます。これを見るために “Images” タブを見て “predictions vs. actuals” 可視化の下をスクロールダウンします ; これは私達に、例えば、3000 訓練反復後、モデルは既にシャツ、スニーカーとコートのような視覚的に明白なクラスの間を識別できていることを示します、それはそれが訓練で後でなるほどには確信できませんが :
前のチュートリアルでは、ひとたびモデルが訓練されたあと、クラス毎の精度を見ました ; ここでは、各クラスのための precision-recall カーブ (良い説明は ここ です) をプロットするために TensorBoard を使用します。
6. 訓練モデルを TensorBoard で評価する
# 1. gets the probability predictions in a test_size x num_classes Tensor # 2. gets the preds in a test_size Tensor # takes ~10 seconds to run class_probs = [] class_preds = [] with torch.no_grad(): for data in testloader: images, labels = data output = net(images) class_probs_batch = [F.softmax(el, dim=0) for el in output] _, class_preds_batch = torch.max(output, 1) class_probs.append(class_probs_batch) class_preds.append(class_preds_batch) test_probs = torch.cat([torch.stack(batch) for batch in class_probs]) test_preds = torch.cat(class_preds) # helper function def add_pr_curve_tensorboard(class_index, test_probs, test_preds, global_step=0): ''' Takes in a "class_index" from 0 to 9 and plots the corresponding precision-recall curve ''' tensorboard_preds = test_preds == class_index tensorboard_probs = test_probs[:, class_index] writer.add_pr_curve(classes[class_index], tensorboard_preds, tensorboard_probs, global_step=global_step) writer.close() # plot all the pr curves for i in range(len(classes)): add_pr_curve_tensorboard(i, test_probs, test_preds)
今では “PR Curves” タブを見ます、これは各クラスのための precision-recall カーブを含みます。続けてその辺りを調べてください ; 幾つかのクラスではモデルは 100% 近い “area under the curve” を持ちます、その一方で他ではこの領域がより低いです :
そしてそれは TensorBoard へのイントロでそして PyTorch はそれとの統合を持ちます。もちろん、TensorBoard が行なうこと総ては Jupyter ノートブックで行えるでしょう、しかし TensorBoard では、デフォルトで対話的であるビジュアルを得ます。
以上