ニューラルネットワークの構築
ニューラルネットワークとは
データに対して演算を実行するレイヤー、モジュールで構成されています。
torch.nnでニューラルネットワークの構築ができる
FashionMNISTデータセットを利用してニューラルネットワークを構築してみよう
必要なライブラリのインポート
import os
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
まず、処理に時間がかかるため実行環境の確認
device = torch.accelerator.current_accelerator().type if torch.accelerator.is_available() else "cpu"
print(f"Using {device} device")
Using mps device
mpsを使用していることを確認
クラス
ニューラルネットワークはnn.Moduleのサブクラス化によって定義される。
__init__でレイヤーの初期化を実施
forward入力されたデータを操作する
class NeuralNetwork(nn.Module):
def __init__(self):
super().__init__()
self.flatten = nn.Flatten()
self.linear_relu_stack = nn.Sequential(
nn.Linear(28*28, 512),
nn.ReLU(),
nn.Linear(512, 512),
nn.ReLU(),
nn.Linear(512, 10),
)
def forward(self, x):
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
NeuralNetworkのインスタンスを作成し
to(device)でデバイスでの実行に切りかえる。
→CPUでの実行だと時間がかかるため
model = NeuralNetwork().to(device)
print(model)
NeuralNetwork(
(flatten): Flatten(start_dim=1, end_dim=-1)
(linear_relu_stack): Sequential(
(0): Linear(in_features=784, out_features=512, bias=True)
(1): ReLU()
(2): Linear(in_features=512, out_features=512, bias=True)
(3): ReLU()
(4): Linear(in_features=512, out_features=10, bias=True)
)
)
torch.rand(1, 28, 28, device=device)
→28*28ピクセルのランダムな画像を一枚生成
logits = model(X)
→モデルに画像を取り込む※logitsは10個の数字が入ったデータのようなもの
pred_probab = nn.Softmax(dim=1)(logits)
→バラバラなデータ値を合計で100%に変換
y_pred = pred_probab.argmax(1)
→一番大きな値が入っているものを返す
X = torch.rand(1, 28, 28, device=device)
logits = model(X)
pred_probab = nn.Softmax(dim=1)(logits)
y_pred = pred_probab.argmax(1)
print(f"Predicted class: {y_pred}")
Predicted class: tensor([6], device='mps:0')
モデルレイヤー
28*28ピクセルの画像3枚からミニバッチを作成
input_image = torch.rand(3,28,28)
print(input_image.size())
torch.Size([3, 28, 28])
nn.Flattenを使用し28*28画像を784ピクセルの値の連続配列に変換
→フラット処理
flatten = nn.Flatten()
flat_image = flatten(input_image)
print(flat_image.size())
torch.Size([3, 784])
nn.Linear(in_features=28*28, out_features=20)
→28*28の784データを20個のデータ数に凝縮
layer1(flat_image)
→平坦化されたデータを取り込む
layer1 = nn.Linear(in_features=28*28, out_features=20)
hidden1 = layer1(flat_image)
print(hidden1.size())
torch.Size([3, 20])
print(f"Before ReLU: {hidden1}\n\n")
hidden1 = nn.ReLU()(hidden1)
print(f"After ReLU: {hidden1}")
Before ReLU: tensor([[-0.0833, -0.0873, -0.3112, 0.0640, 0.1106, 0.1902, 0.1830, 0.2539,
-0.1484, 0.0062, -0.0096, 0.1291, -0.0294, -0.0135, 0.1557, 0.2018,
0.0746, 0.1054, 0.1798, -0.2982],
[-0.1108, -0.0929, -0.3736, 0.0069, 0.1355, 0.1841, 0.2582, 0.2416,
-0.1363, 0.0652, 0.0499, -0.0467, 0.0152, -0.1365, 0.2464, 0.1839,
0.0821, 0.0255, 0.1317, -0.2054],
[ 0.0902, -0.0412, -0.2321, -0.0199, -0.0354, 0.1543, 0.0782, 0.2038,
-0.2241, 0.1196, 0.0558, 0.0124, -0.0048, 0.0214, 0.1170, 0.1462,
0.0751, 0.0632, 0.0855, -0.3060]], grad_fn=)
After ReLU: tensor([[0.0000, 0.0000, 0.0000, 0.0640, 0.1106, 0.1902, 0.1830, 0.2539, 0.0000,
0.0062, 0.0000, 0.1291, 0.0000, 0.0000, 0.1557, 0.2018, 0.0746, 0.1054,
0.1798, 0.0000],
[0.0000, 0.0000, 0.0000, 0.0069, 0.1355, 0.1841, 0.2582, 0.2416, 0.0000,
0.0652, 0.0499, 0.0000, 0.0152, 0.0000, 0.2464, 0.1839, 0.0821, 0.0255,
0.1317, 0.0000],
[0.0902, 0.0000, 0.0000, 0.0000, 0.0000, 0.1543, 0.0782, 0.2038, 0.0000,
0.1196, 0.0558, 0.0124, 0.0000, 0.0214, 0.1170, 0.1462, 0.0751, 0.0632,
0.0855, 0.0000]], grad_fn=)
確かにマイナスの値は0へ変換されておりますね。
nn.Sequentialで定義した順序でニューラルネットワークの構造を通過していく。
seq_modules = nn.Sequential(
flatten,
layer1,
nn.ReLU(),
nn.Linear(20, 10)
)
input_image = torch.rand(3,28,28)
logits = seq_modules(input_image)
nn.Softmax
→予測確率を0から1で表すモジュール
softmax = nn.Softmax(dim=1)
pred_probab = softmax(logits)
モデルパラメータ
どのような順番、パラメータで処理されているかを確認できる。
print(f"Model structure: {model}\n\n")
for name, param in model.named_parameters():
print(f"Layer: {name} | Size: {param.size()} | Values : {param[:2]} \n")
Model structure: NeuralNetwork(
(flatten): Flatten(start_dim=1, end_dim=-1)
(linear_relu_stack): Sequential(
(0): Linear(in_features=784, out_features=512, bias=True)
(1): ReLU()
(2): Linear(in_features=512, out_features=512, bias=True)
(3): ReLU()
(4): Linear(in_features=512, out_features=10, bias=True)
)
)
Layer: linear_relu_stack.0.weight | Size: torch.Size([512, 784]) | Values : tensor([[-0.0141, 0.0296, 0.0188, ..., -0.0072, -0.0260, 0.0188],
[-0.0080, 0.0066, -0.0264, ..., -0.0011, -0.0103, 0.0216]],
device='mps:0', grad_fn=)
Layer: linear_relu_stack.0.bias | Size: torch.Size([512]) | Values : tensor([-0.0057, 0.0293], device='mps:0', grad_fn=)
Layer: linear_relu_stack.2.weight | Size: torch.Size([512, 512]) | Values : tensor([[-0.0316, -0.0375, 0.0118, ..., 0.0259, -0.0312, -0.0413],
[-0.0374, 0.0159, 0.0280, ..., -0.0438, -0.0147, 0.0140]],
device='mps:0', grad_fn=)
Layer: linear_relu_stack.2.bias | Size: torch.Size([512]) | Values : tensor([ 0.0002, -0.0439], device='mps:0', grad_fn=)
Layer: linear_relu_stack.4.weight | Size: torch.Size([10, 512]) | Values : tensor([[ 0.0309, -0.0203, -0.0233, ..., 0.0111, -0.0332, -0.0273],
[-0.0198, -0.0037, -0.0407, ..., 0.0338, -0.0421, -0.0027]],
device='mps:0', grad_fn=)
Layer: linear_relu_stack.4.bias | Size: torch.Size([10]) | Values : tensor([-0.0320, 0.0096], device='mps:0', grad_fn=)
