<jupyter_start><jupyter_text>Anaconda環境、JupyterNotebook実行用<jupyter_code># imports
import matplotlib.pyplot as plt
import numpy as np

import torch
import torchvision
import torchvision.transforms as transforms

#functionalはas F とするのが一般的
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

#データを-1~1の範囲にノーマライズ（MNISTのため１チャンネル画像）
transform = transforms.Compose(
    [transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))])

#FashionMNISTデータセット
trainset = torchvision.datasets.FashionMNIST('./data',
    download=True,
    train=True,
    transform=transform)
testset = torchvision.datasets.FashionMNIST('./data',
    download=True,
    train=False,
    transform=transform)

#データローダー、バッチサイズは４とする。
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)

#答え（ラベル）の定義
classes = ('T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
        'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle Boot')
# FashionMNISTの画像確認用関数
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)))

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)
        #全結合層の入力時には、画像が16チャンネルの4×4画像となっているので「4×4」に変更しています。
        #（画像サイズはforwardメソッドに記載）
        self.fc1 = nn.Linear(16 * 4 * 4, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        #Conv①：6チャンネルの24×24画像→MaxPool：12×12画像
        x = self.pool(F.relu(self.conv1(x)))
        #Conv②：16チャンネルの8×8画像に→MaxPool：4×4画像
        x = self.pool(F.relu(self.conv2(x)))
        #全結合層に入力するためには、１画像のデータを全て横並びにする。
        #行が画像枚数、列が4×4の16チャンネルの画像ピクセルデータが横並びになったデータ
        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()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)<jupyter_output><empty_output><jupyter_text>１．TensorBoardのセットアップ<jupyter_code>from torch.utils.tensorboard import SummaryWriter

# default `log_dir` is "runs" - we'll be more specific here
writer = SummaryWriter('runs/fashion_mnist_experiment_1')<jupyter_output><jupyter_text>２．TensorBoardへの書き込み<jupyter_code>#trainloaderのイテレータを取得
dataiter = iter(trainloader)
#イテレータでミニバッチ（画像４枚）を取得
images, labels = dataiter.next()

#make_grid関数で画像を書き込み、並べて表示できる
img_grid = torchvision.utils.make_grid(images)

#matplotlibで先ほどmake_gridで並べた画像を表示する。
matplotlib_imshow(img_grid, one_channel=True)

#tensorboardに並べた４枚の画像を書き込む。
writer.add_image('four_fashion_mnist_images', img_grid)<jupyter_output><empty_output><jupyter_text>３．TensorBoardを使用してモデルを検査する<jupyter_code>writer.add_graph(net, images)
writer.close()<jupyter_output><empty_output><jupyter_text>４．「Projector」を追加する<jupyter_code>#①追加のプログラム=============================
#TensorFlowパッケージが存在してしまっている場合は
#以下プログラムで一時しのぎが可能
#import tensorflow as tf
#import tensorboard as tb
#tf.io.gfile = tb.compat.tensorflow_stub.io.gfile
#===============================================

#ヘルパー関数
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()<jupyter_output><empty_output><jupyter_text>ここで出るエラーについては以下を参考にしました。https://github.com/pytorch/pytorch/issues/30966 macでの階層指定ターミナルでtensorboardを起動します。私のmac環境では、「/Python」の階層にJupyterノートを配置しています。そのため、コマンドのlogdirを次のように指定したらうまく動作しました。tensorboard --logdir=/Python/runswindowsでの階層指定AnacondaPromptでTensorBoardを起動します。私のwindows環境では、「C:\Users\ユーザー名（任意）\Python」階層にJupyterノートブックのPythonプログラムを保存しています。そのため、以下のようにlogdirを指定するとうまくいきました。tensorboard --logdir=C:\Users\ユーザー名（任意）\Python\runsTensorBoardへのアクセスブラウザにて、http://localhost:6006/を入力してTensorBoardにアクセス。 ５. 訓練のトラッキングをする<jupyter_code>#ヘルパー関数
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
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net.to(device)
#net.cpu()#CPU利用

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)<jupyter_output><empty_output><jupyter_text>最後に、前のチュートリアルと同じモデルトレーニングコードを使用してモデルをトレーニングしますが、コンソールに出力するのではなく、1000バッチごとに結果をTensorBoardに書き込みます。これは、add_scalar関数を使用して行われます。さらに、トレーニング中に、モデルの予測と、そのバッチに含まれる4つの画像の実際の結果を示す画像を生成します。<jupyter_code>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')<jupyter_output><empty_output><jupyter_text>これで、スカラータブを見て、トレーニングの15,000回の反復にわたってプロットされたランニングロスを確認できます。さらに、学習を通じてモデルが任意のバッチで行った予測を確認できます。これを確認するには、「画像」タブを表示し、「予測vs実績」ビジュアライゼーションの下にスクロールしてください。これは、たとえば、わずか3000回のトレーニングを繰り返しただけで、モデルはシャツ、スニーカー、コートなどの視覚的に区別できるクラスをすでに区別できたことを示していますが、トレーニングの後半ほどは確信が持てません。前のチュートリアルでは、モデルがトレーニングされた後、クラスごとの精度を調べました。ここでは、TensorBoardを使用して、各クラスの精度-再現率曲線（ここで適切な説明）をプロットします。 ６．TensorBoardでモデルを評価する softmaxの挙動の確認<jupyter_code>#Softmaxを行う(2階のテンソル、行列の場合、dim1で行の方向に処理を行う設定)
m = nn.Softmax(dim=1)
print(m)
#2行3列のテンソルをランダムな値で初期化
input = torch.randn(2, 3)
print(input)
#テンソルにSoftMaxの処理を行う
output = m(input)
print(output)
#行方向にテンソルを合計する
print(torch.sum(output, dim=1))<jupyter_output>tensor([1.0000, 1.0000])<jupyter_text>PyTorchのsoftmax関数https://pytorch.org/docs/master/generated/torch.nn.Softmax.html torch.catとstackの挙動<jupyter_code>x = torch.randn(2, 3)
x
#リストを作成します。
x_list = []
x_list.append(x)
x_list.append(x)
x_list.append(x)
print(torch.stack(x_list))
torch.stack(x_list).size()<jupyter_output>tensor([[[ 1.2377,  0.0331,  1.4176],
         [ 0.6362, -0.5774,  1.7173]],

        [[ 1.2377,  0.0331,  1.4176],
         [ 0.6362, -0.5774,  1.7173]],

        [[ 1.2377,  0.0331,  1.4176],
         [ 0.6362, -0.5774,  1.7173]]])<jupyter_text>torch.stackhttps://pytorch.org/docs/master/generated/torch.stack.html<jupyter_code>print(torch.cat(x_list))
torch.cat(x_list).size()<jupyter_output>tensor([[ 1.2377,  0.0331,  1.4176],
        [ 0.6362, -0.5774,  1.7173],
        [ 1.2377,  0.0331,  1.4176],
        [ 0.6362, -0.5774,  1.7173],
        [ 1.2377,  0.0331,  1.4176],
        [ 0.6362, -0.5774,  1.7173]])<jupyter_text>catにリストを与えることで、行方向に結合ができる。torch.cathttps://pytorch.org/docs/master/generated/torch.cat.html?highlight=torch%20cattorch.cat<jupyter_code>#1. テストデータの「probability」の値を求めます(モデルが出力する確率の値です)
#2. テストデータのモデルの予測値を求めます。
#この処理には10秒程度かかります。
class_probs = []
class_preds = []
with torch.no_grad():
    for data in testloader:
        #【GPU】
        #images, labels = data[0].to(device) , data[1].to(device)
        #【CPU】
        images, labels = data

        output = net(images)
        #テンソルの行(画像１枚当たりの出力)をソフトマックス関数に通す
        #class_probs_batchはリスト。
        class_probs_batch = [F.softmax(el, dim=0) for el in output]
        #一番値が大きいクラスをMax関数で選択して予測回答とする(第二引数が1で行の中の最大値を取る)
        _, class_preds_batch = torch.max(output, 1)

　　　　#Pythonのリストに「probability」と「予測回答」を追加していきます
        #class_probsはリスト。
        class_probs.append(class_probs_batch)
        class_preds.append(class_preds_batch)

#[torch.stack(batch) for batch in class_probs]
#テンソルを要素に持つリストをテンソルに変換
test_probs = torch.cat([torch.stack(batch) for batch in class_probs])
#print(test_probs.size())#ここで、[10000,10]の行列となる。
test_preds = torch.cat(class_preds)
#print(test_preds.size())#ここで、[10000]のベクトルとなる。

# ヘルパー関数
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
    '''
    #ラベル(class_index)と等しいtest_predsの値がtensorboard_predsとなる。
    tensorboard_preds = test_preds == class_index
    #ラベルの列のみを取得してtensorboard_probsとする。
    tensorboard_probs = test_probs[:, class_index]

    writer.add_pr_curve(classes[class_index],
                        tensorboard_preds,
                        tensorboard_probs,
                        global_step=global_step)
    writer.close()

# PRカーブを作成する。0~9までのラベルで作成するのでループする。
for i in range(len(classes)):
    add_pr_curve_tensorboard(i, test_probs, test_preds)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1334155798378569, 'fraction_numerical': 0.037451533309834334, 'mean_word_length': 3.7805391743892165, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 41, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '495978', 'license': 'MIT', 'n_tokens_mistral': 5658, 'n_tokens_neox': 5366, 'n_words': 586, 'path': 'VISUALIZING_MODELS,_DATA,_AND_TRAINING_WITH_TENSORBOARD.ipynb', 'repo_name': 'perfectpanda-works/machine-learning', 'size': '11348'}