専門ユニット2/山内研セミナー(2023/10/24)
関連サイトと資料
2.開発環境
その1
%%time
import torch
from torch import optim
import torch.nn as nn
import torch.nn.functional as F
from torchvision.datasets import CIFAR10
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
cifar10_train = CIFAR10("./data", train=True, download=True, transform=transforms.ToTensor())
cifar10_test = CIFAR10("./data", train=False, download=True, transform=transforms.ToTensor())
batch_size = 64
train_loader = DataLoader(cifar10_train, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(cifar10_test, batch_size=len(cifar10_test), shuffle=False)
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size=5)
self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5)
self.fc1 = nn.Linear(in_features=16*5*5, out_features=256)
self.fc2 = nn.Linear(in_features=256, out_features=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*5*5)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
net = Net()
if torch.cuda.is_available():
net.cuda()
loss_fnc = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters())
record_loss_train = []
record_loss_test = []
x_test, t_test = next(iter(test_loader))
if torch.cuda.is_available():
x_test, t_test = x_test.cuda(), t_test.cuda()
for i in range(10):
net.train()
loss_train = 0
for j, (x, t) in enumerate(train_loader):
if torch.cuda.is_available():
x, t = x.cuda(), t.cuda()
y = net(x)
loss = loss_fnc(y, t)
loss_train += loss.item()
optimizer.zero_grad()
loss.backward()
optimizer.step()
loss_train /= j+1
record_loss_train.append(loss_train)
net.eval()
y_test = net(x_test)
loss_test = loss_fnc(y_test, t_test).item()
record_loss_test.append(loss_test)
3.PyTorchで実装する簡単な深層学習
Tensor
その2
import torch
a = torch.tensor([1,2,3])
print(a, type(a))
その3
print("--- 2次元のリストから生成 ---")
b = torch.tensor([[1, 2],
[3, 4]])
print(b)
print("--- dypeを指定し、倍精度のTensorにする ---")
c = torch.tensor([[1, 2],
[3, 4]], dtype=torch.float64)
print(c)
print("--- 0から9までの数値で初期化 ---")
d = torch.arange(0, 10)
print(d)
print("--- 全ての値が0の、2×3のTensor ---")
e = torch.zeros(2, 3)
print(e)
print("--- 全ての値が乱数の、2×3のTensor ---")
f = torch.rand(2, 3)
print(f)
print("--- Tensorの形状はsizeメソッドで取得 ---")
print(f.size())
その4
print("--- -5から5までの連続値を10生成 ---")
g = torch.linspace(-5, 5, 10)
print(g)
その5
print("--- Tensor → NumPy ---")
a = torch.tensor([[1, 2],
[3, 4.]])
b = a.numpy()
print(b)
print("--- NumPy → Tensor ---")
c = torch.from_numpy(b)
print(c)
その6
a = torch.tensor([[1, 2, 3],
[4, 5, 6]])
print("--- 2つのインデックスを指定 ---")
print(a[0, 1])
print("--- 範囲を指定 ---")
print(a[1:2, :2])
print("--- リストで複数のインデックスを指定 ---")
print(a[:, [0, 2]])
print("--- 3より大きい要素のみを指定 ---")
print(a[a>3])
print("--- 要素の変更 ---")
a[0, 2] = 11
print(a)
print("--- 要素の一括変更 ---")
a[:, 1] = 22
print(a)
print("--- 10より大きい要素のみ変更 ---")
a[a>10] = 33
print(a)
その7
# ベクトル
a = torch.tensor([1, 2, 3])
b = torch.tensor([4, 5, 6])
# 行列
c = torch.tensor([[6, 5, 4],
[3, 2, 1]])
print("--- ベクトルとスカラーの演算 ---")
print(a + 3)
print("--- ベクトル同士の演算 ---")
print(a + b)
print("--- 行列とスカラーの演算 ---")
print(c + 2)
print("--- 行列とベクトルの演算(ブロードキャスト) ---")
print(c + a)
print("--- 行列同士の演算 ---")
print(c + c)
その8
a = torch.tensor([0, 1, 2, 3, 4, 5, 6, 7]) # 1次元のTensor
b = a.view(2, 4) # (2, 4)の2次元のTensorに変換
print(b)
その9
c = torch.tensor([0, 1, 2, 3, 4, 5, 6, 7]) # 1次元のTensor
d = c.view(2, -1) # (2, 4)の2次元のTensorに変換
print(d)
その10
e = torch.tensor([[[0, 1],
[2, 3]],
[[4, 5],
[6, 7]]]) # 3次元のTensor
f = c.view(-1) # 1次元のTensorに変換
print(f)
その11
print("--- 要素数が1の次元が含まれる4次元のTensor ---")
g = torch.arange(0, 8).view(1, 2, 1, 4)
print(g)
print("--- 要素数が1の次元を削除 ---")
h = g.squeeze()
print(h)
その12
print("--- 2次元のTensor ---")
i = torch.arange(0, 8).view(2, -1)
print(i)
print("--- 要素数が1の次元を、一番内側(2)に追加 ---")
j = i.unsqueeze(2)
print(j)
その13
a = torch.tensor([[1, 2, 3],
[4, 5, 6.]])
print("--- 平均値を求める関数 ---")
m = torch.mean(a)
print(m.item()) # item()で値を取り出す
print("--- 平均値を求めるメソッド ---")
m = a.mean()
print(m.item())
print("--- 列ごとの平均値 ---")
print(a.mean(0))
print("--- 合計値 ---")
print(torch.sum(a).item())
print("--- 最大値 ---")
print(torch.max(a).item())
print("--- 最小値 ---")
print(torch.min(a).item())
その14
import torch
a = torch.tensor([[1, 2, 3],
[4, 5, 6]])
b = torch.tensor([1, 2, 3])
print("--- 和 ---")
print(a + b)
print("--- 差 ---")
print(a - b)
print("--- 積 ---")
print(a * b)
print("--- 商(小数) ---")
print(a / b)
print("--- 商(整数) ---")
print(a // b)
print("--- 余り ---")
print(a % b)
活性化関数
その15
import torch
from torch import nn
import matplotlib.pylab as plt
m = nn.Sigmoid() # シグモイド関数
x = torch.linspace(-5, 5, 50)
y = m(x)
plt.plot(x, y)
plt.show()
その16
import torch
from torch import nn
import matplotlib.pylab as plt
m = nn.Tanh() # tanh
x = torch.linspace(-5, 5, 50)
y = m(x)
plt.plot(x, y)
plt.show()
その17
import torch
from torch import nn
import matplotlib.pylab as plt
m = nn.ReLU() # ReLU
x = torch.linspace(-5, 5, 50)
y = m(x)
plt.plot(x, y)
plt.show()
その18
mport torch
import matplotlib.pylab as plt
x = torch.linspace(-5, 5, 50)
y = x # 恒等関数
plt.plot(x, y)
plt.show()
その19
import torch
from torch import nn
import matplotlib.pylab as plt
m = nn.Softmax(dim=1) # 各行でソフトマックス関数
x = torch.tensor([[1.0, 2.0, 3.0],
[3.0, 2.0, 1.0]])
y = m(x)
print(y)
その20
import torch
import matplotlib.pylab as plt
x = torch.linspace(-5, 5, 50)
y = torch.sigmoid(x)
plt.plot(x, y)
plt.show()
損失関数
その21
import torch
from torch import nn
y = torch.tensor([3.0, 3.0, 3.0, 3.0, 3.0]) # 出力
t = torch.tensor([2.0, 2.0, 2.0, 2.0, 2.0]) # 正解
loss_func = nn.MSELoss() # 平均二乗誤差
loss = loss_func(y, t)
print(loss.item())
その22
import torch
from torch import nn
# ソフトマックス関数への入力
x = torch.tensor([[1.0, 2.0, 3.0], # 入力1
[3.0, 1.0, 2.0]]) # 入力2
# 正解(one-hot表現における1の位置)
t = torch.tensor([2, # 入力1に対応する正解
0]) # 入力2に対応する正解
loss_func = nn.CrossEntropyLoss() # ソフトマックス関数 + 交差エントロピー誤差
loss = loss_func(x, t)
print(loss.item())
シンプルな深層学習の実装
その23
import matplotlib.pyplot as plt
from sklearn import datasets
digits_data = datasets.load_digits()
n_img = 10 # 表示する画像の数
plt.figure(figsize=(10, 4))
for i in range(n_img):
ax = plt.subplot(2, 5, i+1)
ax.imshow(digits_data.data[i].reshape(8, 8), cmap="Greys_r")
ax.get_xaxis().set_visible(False) # 軸を非表示に
ax.get_yaxis().set_visible(False)
plt.show()
print("データの形状:", digits_data.data.shape)
print("ラベル:", digits_data.target[:n_img])
その24
import torch
from sklearn.model_selection import train_test_split
digit_images = digits_data.data
labels = digits_data.target
x_train, x_test, t_train, t_test = train_test_split(digit_images, labels) # 25%がテスト用
# Tensorに変換
x_train = torch.tensor(x_train, dtype=torch.float32) # 入力: 訓練用
t_train = torch.tensor(t_train, dtype=torch.int64) # 正解: 訓練用
x_test = torch.tensor(x_test, dtype=torch.float32) # 入力: テスト用
t_test = torch.tensor(t_test, dtype=torch.int64) # 正解: テスト用
その25
from torch import nn
net = nn.Sequential(
nn.Linear(64, 32), # 全結合層
nn.ReLU(), # ReLU
nn.Linear(32, 16),
nn.ReLU(),
nn.Linear(16, 10)
)
print(net)
その26
from torch import optim
# ソフトマックス関数 + 交差エントロピー誤差関数
loss_fnc = nn.CrossEntropyLoss()
# SGD モデルのパラメータを渡す
optimizer = optim.SGD(net.parameters(), lr=0.01) # 学習率は0.01
# 損失のログ
record_loss_train = []
record_loss_test = []
# 訓練データを1000回使う
for i in range(1000):
# パラメータの勾配を0に
optimizer.zero_grad()
# 順伝播
y_train = net(x_train)
y_test = net(x_test)
# 誤差を求めて記録する
loss_train = loss_fnc(y_train, t_train)
loss_test = loss_fnc(y_test, t_test)
record_loss_train.append(loss_train.item())
record_loss_test.append(loss_test.item())
# 逆伝播(勾配を計算)
loss_train.backward()
# パラメータの更新
optimizer.step()
if i%100 == 0: # 100回ごとに経過を表示
print("Epoch:", i, "Loss_Train:", loss_train.item(), "Loss_Test:", loss_test.item())
その27
plt.plot(range(len(record_loss_train)), record_loss_train, label="Train")
plt.plot(range(len(record_loss_test)), record_loss_test, label="Test")
plt.legend()
plt.xlabel("Epochs")
plt.ylabel("Error")
plt.show()
その28
y_test = net(x_test)
count = (y_test.argmax(1) == t_test).sum().item()
print("正解率:", str(count/len(y_test)*100) + "%")
その29
# 入力画像
img_id = 0
x_pred = digit_images[img_id]
image = x_pred.reshape(8, 8)
plt.imshow(image, cmap="Greys_r")
plt.show()
x_pred = torch.tensor(x_pred, dtype=torch.float32)
y_pred = net(x_pred)
print("正解:", labels[img_id], "予測結果:", y_pred.argmax().item())