In [1]:
import torch
import torchvision
import torch.nn as nn
import numpy as np
import torch.utils.data as data
import torchvision.transforms as transforms
import torchvision.datasets as dsets
from torch.autograd import Variable
In [5]:
# create tensors
# Variableは自動微分の対象になる
x = Variable(torch.Tensor([1]), requires_grad=True)
w = Variable(torch.Tensor([2]), requires_grad=True)
b = Variable(torch.Tensor([3]), requires_grad=True)
# build a computational graph
y = w * x + b # y = 2 * x + 3
# compute gradients
y.backward()
# print gradients
print(x.grad) # dy/dx = w
print(w.grad) # dy/dw = x
print(b.grad) # dy/db = 1
In [33]:
# autograd 2
x = Variable(torch.randn(5, 3))
y = Variable(torch.randn(5, 2))
# linear layer
linear = nn.Linear(3, 2)
print('w:', linear.weight)
print('b:', linear.bias)
# loss and optimizer
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(linear.parameters(), lr=0.01)
# forward
pred = linear(x)
# compute loss
loss = criterion(pred, y)
print('loss:', loss.data[0])
# backpropagation
loss.backward()
# print out the gradients
print('dL/dw:', linear.weight.grad)
print('dL/db:', linear.bias.grad)
print('*** by hand')
# optimizer.step()の中身は下の計算をしている
# 計算結果が一致する
print(linear.weight.data.sub(0.01 * linear.weight.grad.data))
print(linear.bias.data.sub(0.01 * linear.bias.grad.data))
# gradient descent
optimizer.step()
print('*** by step()')
print(linear.weight)
print(linear.bias)
In [40]:
# Loading data from numpy
a = np.array([[1, 2], [3, 4]])
b = torch.from_numpy(a) # ndarray => tensor
c = b.numpy() # tensor => ndarray
print(type(a))
print(type(b))
print(type(c))
print(a)
print(b)
print(c)
In [56]:
# Implementing the input pipeline
# Download and construct dataset
# Datasetクラスのサブクラス(__getitem__と__len__が実装されている)
train_dataset = dsets.CIFAR10(root='./data',
train=True,
transform=transforms.ToTensor(),
download=True)
# select one data pair
# ディスクからデータを読む
image, label = train_dataset[0]
print(image.size())
print(label)
print(len(train_dataset))
In [58]:
# data loader
# Datasetを渡すとバッチ単位でファイルからデータを取り出せる
# num_workersを指定することでマルチプロセッサで並列に読み出せる?
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=100,
shuffle=True,
num_workers=2)
data_iter = iter(train_loader)
# ミニバッチ単位で画像とラベルをロード
images, labels = data_iter.next()
print(images.size(), labels.size())
In [59]:
# 実際はiterを使わなくてforループでOK
for images, labels in train_loader:
print(images.size(), labels.size())
break
__getitem__()
と __len__()
を定義する
In [62]:
class CustomDataset(data.Dataset):
def __init__(self):
# initialize file path or list of file names.
pass
def __getitem__(self, index):
# 1. Read one data from file (e.g. using numpy.fromfile, PIL.Image.open)
# 2. Preprocess the data (e.g. torchvision.Transform)
# 3. Return a data pair (e.g. image and label)
pass
def __len__(self):
# return total size of your dataset
return 0
custom_dataset = CustomDataset()
train_loader = torch.utils.data.DataLoader(dataset=custom_dataset,
batch_size=100,
shuffle=True,
num_workers=2)
In [63]:
# download and load pretrained resnet
resnet = torchvision.models.resnet18(pretrained=True)
In [64]:
resnet
Out[64]:
In [68]:
# finetuneしたいときはパラメータを固定する
for param in resnet.parameters():
param.requires_grad = False
# topのfc層を置き換える
resnet.fc = nn.Linear(resnet.fc.in_features, 100)
In [74]:
# 新しく追加したfc層のパラメータは更新対象
for param in resnet.fc.parameters():
print(param.requires_grad)
In [75]:
# test
images = Variable(torch.randn(10, 3, 256, 256))
outputs = resnet(images)
print(outputs.size())
In [91]:
# 74番目のクラスに分類された
print(np.argmax(outputs[0].data.numpy()))
In [92]:
# save and load the entire model
torch.save(resnet, 'model.pkl')
model = torch.load('model.pkl')
print(model)
In [93]:
# save and load only the model parameters
# こちらのほうが推薦されている
# ファイルサイズは変わらない?
torch.save(resnet.state_dict(), 'params.pkl')
resnet.load_state_dict(torch.load('params.pkl'))
In [4]:
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
from torch.autograd import Variable
# hyper parameters
input_size = 1
output_size = 1
num_epochs = 60
learning_rate = 0.001
# toy dataset
# 15 samples, 1 features
x_train = np.array([3.3, 4.4, 5.5, 6.71, 6.93, 4.168, 9.779, 6.182, 7.59, 2.167,
7.042, 10.791, 5.313, 7.997, 3.1], dtype=np.float32)
y_train = np.array([1.7, 2.76, 2.09, 3.19, 1.694, 1.573, 3.366, 2.596, 2.53, 1.221,
2.827, 3.465, 1.65, 2.904, 1.3], dtype=np.float32)
x_train = x_train.reshape(15, 1)
y_train = y_train.reshape(15, 1)
# linear regression model
class LinearRegression(nn.Module):
def __init__(self, input_size, output_size):
super(LinearRegression, self).__init__()
self.linear = nn.Linear(input_size, output_size)
def forward(self, x):
out = self.linear(x)
return out
model = LinearRegression(input_size, output_size)
# loss and optimizer
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
# train the model
for epoch in range(num_epochs):
# convert numpy array to torch Variable
# ndarray => Tensor => Variable
inputs = Variable(torch.from_numpy(x_train))
targets = Variable(torch.from_numpy(y_train))
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, targets)
loss.backward()
optimizer.step()
if (epoch + 1) % 10 == 0:
print('Epoch [%d/%d], Loss: %.4f' % (epoch + 1, num_epochs, loss.data[0]))
In [5]:
# plot the graph
predicted = model(Variable(torch.from_numpy(x_train))).data.numpy()
plt.plot(x_train, y_train, 'ro', label='Original data')
plt.plot(x_train, predicted, label='Fitted line')
plt.legend()
plt.show()
In [119]:
# save the model
torch.save(model.state_dict(), 'model.pkl')
In [132]:
import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.autograd import Variable
# Hyper Parameters
input_size = 784
num_classes = 10
num_epochs = 5
batch_size = 100
learning_rate = 0.001
# MNIST Dataset (Images and Labels)
train_dataset = dsets.MNIST(root='./data',
train=True,
transform=transforms.ToTensor(),
download=True)
test_dataset = dsets.MNIST(root='./data',
train=False,
transform=transforms.ToTensor())
# Dataset Loader (Input Pipline)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
batch_size=batch_size,
shuffle=False)
In [133]:
print(len(train_dataset))
print(len(test_dataset))
image, label = iter(train_loader).next()
print(type(image), type(label))
print(image.size(), label.size())
In [136]:
# Model
class LogisticRegression(nn.Module):
def __init__(self, input_size, num_classes):
super(LogisticRegression, self).__init__()
self.linear = nn.Linear(input_size, num_classes)
def forward(self, x):
# ここではlogitsを返してsoftmaxを通さないので注意
# LinearRegressionとまったく同じ
out = self.linear(x)
return out
model = LogisticRegression(input_size, num_classes)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
# Training the Model
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
images = Variable(images.view(-1, 28 * 28))
labels = Variable(labels)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
if (i + 1) % 100 == 0:
print('Epoch: [%d/%d], Step: [%d/%d], Loss: %.4f'
% (epoch + 1, num_epochs, i + 1, len(train_dataset) // batch_size, loss.data[0]))
In [145]:
# Test the Model
correct = 0
total = 0
for images, labels in test_loader:
images = Variable(images.view(-1, 28 * 28))
outputs = model(images)
# torch.maxは最大値とそのインデックスの両方を返す
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
# predicted == labelsはByteTensor
correct += (predicted == labels).sum()
print('Accuracy of the model on the 10000 test images: %d %%' % (100 * correct / total))
In [146]:
# Save the model
torch.save(model.state_dict(), 'model.pkl')
In [147]:
import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.autograd import Variable
# Hyper Parameters
input_size = 784
hidden_size = 500
num_classes = 10
num_epochs = 5
batch_size = 100
learning_rate = 0.001
# MNIST Dataset
train_dataset = dsets.MNIST(root='./data',
train=True,
transform=transforms.ToTensor(),
download=True)
test_dataset = dsets.MNIST(root='./data',
train=False,
transform=transforms.ToTensor())
# Data Loader (Input Pipeline)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
batch_size=batch_size,
shuffle=False)
In [154]:
class Net(nn.Module):
def __init__(self, input_size, hidden_size, num_classes):
super(Net, self).__init__()
self.fc1 = nn.Linear(input_size, hidden_size)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(hidden_size, num_classes)
def forward(self, x):
out = self.fc1(x)
out = self.relu(out)
out = self.fc2(out)
return out
net = Net(input_size, hidden_size, num_classes)
In [155]:
# Loss and Optimizer
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=learning_rate)
# Train the Model
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
# Convert torch tensor to Variable
images = Variable(images.view(-1, 28 * 28))
labels = Variable(labels)
# Forward + Backward + Optimize
optimizer.zero_grad() # zero the gradient buffer
outputs = net(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
if (i+1) % 100 == 0:
print ('Epoch [%d/%d], Step [%d/%d], Loss: %.4f'
%(epoch + 1, num_epochs, i + 1, len(train_dataset) // batch_size, loss.data[0]))
In [156]:
# Test the Model
correct = 0
total = 0
for images, labels in test_loader:
images = Variable(images.view(-1, 28 * 28))
outputs = net(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum()
print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))
# Save the Model
torch.save(net.state_dict(), 'model.pkl')
In [15]:
import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.autograd import Variable
# Hyper Parameters
num_epochs = 5
batch_size = 100
learning_rate = 0.001
# MNIST Dataset
train_dataset = dsets.MNIST(root='./data/',
train=True,
transform=transforms.ToTensor(),
download=True)
test_dataset = dsets.MNIST(root='./data/',
train=False,
transform=transforms.ToTensor())
# Data Loader (Input Pipeline)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
batch_size=batch_size,
shuffle=False)
# CNN Model
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
# [Conv > BN > ReLU > Pool] のブロックをまとめられる
# in:[N, 1, 28, 28] out:[N, 16, 14, 14]
self.layer1 = nn.Sequential(
# PyTorchではin_channel, out_channelの両方とも明示する必要あり
nn.Conv2d(1, 16, kernel_size=5, padding=2),
# PyTorchではBatchNormも入力のfeatures数を明示する必要あり
nn.BatchNorm2d(16),
nn.ReLU(),
nn.MaxPool2d(2))
# in:[N, 16, 14, 14] out:[N, 32, 7, 7]
self.layer2 = nn.Sequential(
nn.Conv2d(16, 32, kernel_size=5, padding=2),
nn.BatchNorm2d(32),
nn.ReLU(),
nn.MaxPool2d(2))
# in:[N, 7*7*32] out:[N, 10]
self.fc = nn.Linear(7 * 7 * 32, 10)
def forward(self, x):
# print('in:', x.size())
out = self.layer1(x)
# print('out layer1:', out.size())
out = self.layer2(out)
# print('out layer2:', out.size())
out = out.view(out.size(0), -1)
out = self.fc(out)
# print('out fc:', out.size())
return out
cnn = CNN()
# モデルの各層のテンソルサイズを見たいときはダミーの入力を渡すと簡単
# images, labels = iter(test_loader).next()
# cnn(Variable(images))
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(cnn.parameters(), lr=learning_rate)
# Train the Model
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
images = Variable(images)
labels = Variable(labels)
# Forward + Backward + Optimize
optimizer.zero_grad()
outputs = cnn(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
if (i+1) % 100 == 0:
print ('Epoch [%d/%d], Iter [%d/%d] Loss: %.4f'
%(epoch + 1, num_epochs, i + 1, len(train_dataset) // batch_size, loss.data[0]))
# Test the Model
# BNを使っているときはモデルをevalモードにする
cnn.eval()
correct = 0
total = 0
for images, labels in test_loader:
images = Variable(images)
outputs = cnn(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum()
print('Test Accuracy of the model on the 10000 test images: %d %%' % (100 * correct / total))
# Save the Trained Model
torch.save(cnn.state_dict(), 'cnn.pkl')
In [58]:
import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.autograd import Variable
# Image Processing
# Data Augmentation
transform = transforms.Compose([
transforms.Scale(40), # 少し大きめに拡張してランダムクロップする
transforms.RandomHorizontalFlip(),
transforms.RandomCrop(32),
transforms.ToTensor()])
# CIFAR-10 dataset
train_dataset = dsets.CIFAR10(root='./data/',
train=True,
transform=transform,
download=True)
# テストデータは Data Augmentation しない
test_dataset = dsets.CIFAR10(root='./data/',
train=False,
transform=transforms.ToTensor())
# Data Loader
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=100,
shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
batch_size=100,
shuffle=False)
# 3x3 convolution
def conv3x3(in_channels, out_channels, stride=1):
return nn.Conv2d(in_channels, out_channels, kernel_size=3,
stride=stride, padding=1, bias=False)
# Residual Block
class ResidualBlock(nn.Module):
def __init__(self, in_channels, out_channels, stride=1, downsample=None):
super(ResidualBlock, self).__init__()
self.conv1 = conv3x3(in_channels, out_channels, stride)
self.bn1 = nn.BatchNorm2d(out_channels)
self.relu = nn.ReLU(inplace=True)
self.conv2 = conv3x3(out_channels, out_channels)
self.bn2 = nn.BatchNorm2d(out_channels)
self.downsample = downsample
def forward(self, x):
residual = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
# 入力のresidualを足し込めるようにサイズやチャネル数を調整するdownsampleを入れる
if self.downsample:
residual = self.downsample(x)
out += residual
out = self.relu(out)
return out
# ResNet Module
class ResNet(nn.Module):
def __init__(self, block, layers=[2, 2, 2], num_classes=10):
super(ResNet, self).__init__()
self.in_channels = 16
self.conv = conv3x3(3, 16)
self.bn = nn.BatchNorm2d(16)
self.relu = nn.ReLU(inplace=True)
self.layer1 = self.make_layer(block, 16, layers[0])
self.layer2 = self.make_layer(block, 32, layers[1], stride=2)
self.layer3 = self.make_layer(block, 64, layers[2], stride=2)
self.avg_pool = nn.AvgPool2d(8)
self.fc = nn.Linear(64, num_classes)
def make_layer(self, block, out_channels, blocks, stride=1):
downsample = None
# チャネル数が変化するタイミングでdownsampleを入れる
if stride != 1 or self.in_channels != out_channels:
downsample = nn.Sequential(
conv3x3(self.in_channels, out_channels, stride=stride),
nn.BatchNorm2d(out_channels))
layers = []
layers.append(block(self.in_channels, out_channels, stride, downsample))
# 残りはin_channels == out_channelsなのでdownsampleは入らない
self.in_channels = out_channels
for i in range(1, blocks):
layers.append(block(out_channels, out_channels))
return nn.Sequential(*layers)
def forward(self, x):
# print('x:', x.size()) # (N, 3, 32, 32)
out = self.conv(x)
# print('out1:', out.size()) # (N, 16, 32, 32)
out = self.bn(out)
out = self.relu(out)
out = self.layer1(out)
# print('out2:', out.size()) # (N, 16, 32, 32)
out = self.layer2(out) # stride=2なのでサイズは半分になる
# print('out3:', out.size()) # (N, 32, 16, 16)
out = self.layer3(out) # stride=2なのでサイズは半分になる
# print('out4:', out.size()) # (N, 64, 8, 8)
out = self.avg_pool(out)
# print('out5:', out.size()) # (N, 64, 1, 1)
out = out.view(out.size(0), -1)
# print('out6:', out.size()) # (N, 64)
out = self.fc(out)
# print('out7:', out.size()) # (N, 10)
return out
resnet = ResNet(ResidualBlock, [2, 2, 2])
criterion = nn.CrossEntropyLoss()
lr = 0.001
optimizer = torch.optim.Adam(resnet.parameters(), lr=lr)
# training
for epoch in range(80):
for i, (images, labels) in enumerate(train_loader):
images = Variable(images)
labels = Variable(labels)
optimizer.zero_grad()
outputs = resnet(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
if (i + 1) % 100 == 0:
print ("Epoch [%d/%d], Iter [%d/%d] Loss: %.4f" %(epoch + 1, 80, i + 1, 500, loss.data[0]))
# decaying learning rate
if (epoch + 1) % 20 == 0:
lr /= 3
optimizer = torch.optim.Adam(resnet.parameters(), lr=lr)
# Test
correct = 0
total = 0
for images, labels in test_loader:
images = Variable(images)
outputs = resnet(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum()
print('Accuracy of the model on the test images: %d %%' % (100 * correct / total))
# Save the Model
torch.save(resnet.state_dict(), 'resnet.pkl')
In [59]:
# resnet = ResNet(ResidualBlock, [2, 2, 2])
# images, labels = iter(test_loader).next()
# out = resnet(Variable(images))
In [60]:
resnet
Out[60]:
In [31]:
import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.autograd import Variable
# Hyper parameters
sequence_length = 28
input_size = 28
hidden_size = 128
num_layers = 2
num_classes = 10
batch_size = 100
num_epochs = 2
learning_rate = 0.01
# MNIST Dataset
train_dataset = dsets.MNIST(root='./data/',
train=True,
transform=transforms.ToTensor(),
download=True)
test_dataset = dsets.MNIST(root='./data/',
train=False,
transform=transforms.ToTensor())
# Data Loader (Input Pipeline)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
batch_size=batch_size,
shuffle=False)
# RNN Model (Many-to-One)
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, num_classes):
super(RNN, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
# num_layersが1より大きい場合はStacked LSTMになる
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, num_classes)
def forward(self, x):
# x: (batch, seq_len, input_size)
# 入力はinput_sizeの特徴ベクトルのシーケンス
# set initial states
# バッチ内のサンプルごとに状態を別々に管理している
h0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size))
c0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size))
# print('h0:', h0.size())
# print('c0:', c0.size())
# forward propagate RNN
out, _ = self.lstm(x, (h0, c0))
# print('out1:', out.size())
# decode hidden state of last time step
# 入力の各シーケンスごとに出力されている
# many-to-oneの場合は最後の出力を使う
# out: (batch, seq_len, hidden_size)
out = self.fc(out[:, -1, :])
# print('out2:', out.size())
return out
rnn = RNN(input_size, hidden_size, num_layers, num_classes)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(rnn.parameters(), lr=learning_rate)
# train the model
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
images = Variable(images.view(-1, sequence_length, input_size))
labels = Variable(labels)
optimizer.zero_grad()
outputs = rnn(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
if (i + 1) % 100 == 0:
print ('Epoch [%d/%d], Step [%d/%d], Loss: %.4f'
%(epoch + 1, num_epochs, i + 1, len(train_dataset) // batch_size, loss.data[0]))
In [28]:
# test
images, labels = iter(train_loader).next()
print(images.size(), labels.size())
# 28x28の画像を28次元ベクトルの長さ28の系列とみなす
images = images.view(-1, 28, 28)
print(images.size())
rnn(Variable(images))
Out[28]:
In [32]:
# Test the Model
correct = 0
total = 0
for images, labels in test_loader:
images = Variable(images.view(-1, sequence_length, input_size))
outputs = rnn(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum()
print('Test Accuracy of the model on the 10000 test images: %d %%' % (100 * correct / total))
# Save the Model
torch.save(rnn.state_dict(), 'rnn.pkl')
In [37]:
import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.autograd import Variable
# Hyper Parameters
sequence_length = 28
input_size = 28
hidden_size = 128
num_layers = 2
num_classes = 10
batch_size = 100
num_epochs = 2
learning_rate = 0.003
# MNIST Dataset
train_dataset = dsets.MNIST(root='./data/',
train=True,
transform=transforms.ToTensor(),
download=True)
test_dataset = dsets.MNIST(root='./data/',
train=False,
transform=transforms.ToTensor())
# Data Loader (Input Pipeline)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
batch_size=batch_size,
shuffle=False)
class BiRNN(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, num_classes):
super(BiRNN, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
self.lstm = nn.LSTM(input_size, hidden_size, num_layers,
batch_first=True, bidirectional=True)
# bidirectionalのときは出力が順方向と逆方向で2倍になる
self.fc = nn.Linear(hidden_size * 2, num_classes)
def forward(self, x):
# set initial states
h0 = Variable(torch.zeros(self.num_layers * 2, x.size(0), self.hidden_size))
c0 = Variable(torch.zeros(self.num_layers * 2, x.size(0), self.hidden_size))
# forward propagate RNN
out, _ = self.lstm(x, (h0, c0))
# decode hidden state of last time step
out = self.fc(out[:, -1, :])
return out
rnn = BiRNN(input_size, hidden_size, num_layers, num_classes)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(rnn.parameters(), lr=learning_rate)
# train the model
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
images = Variable(images.view(-1, sequence_length, input_size))
labels = Variable(labels)
optimizer.zero_grad()
outputs = rnn(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
if (i + 1) % 100 == 0:
print ('Epoch [%d/%d], Step [%d/%d], Loss: %.4f'
%(epoch + 1, num_epochs, i + 1, len(train_dataset) // batch_size, loss.data[0]))
In [36]:
rnn
Out[36]:
In [38]:
# Test the Model
correct = 0
total = 0
for images, labels in test_loader:
images = Variable(images.view(-1, sequence_length, input_size))
outputs = rnn(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum()
print('Test Accuracy of the model on the 10000 test images: %d %%' % (100 * correct / total))
# Save the Model
torch.save(rnn.state_dict(), 'rnn.pkl')
In [ ]: