Pytorch学習教程(三)----------ニューラルネットワーク
%matplotlib inline
ニューラルネットワーク
torchを使用できます.nn package構造はニューラルネットワークを構築する.
さっきautogradを簡単に紹介しましたが、nnはautogradに依存してモデルを定義し、それらを区別します.一つnn.Moduleには、あなたが定義したネットワーク層とforward(input)メソッドが含まれています.このメソッドはoutputを返します.
このデジタル画像分類のネットワークの例を見てみましょう.
簡単なフィードフォワードネットワークです.入力を受け入れ、各層の入力は上位層の出力であり、最後に出力が与えられます.
典型的なニューラルネットワークの訓練過程は以下の通りである.
ニューラルネットワークを定義する
import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# 2
# kernel
self.conv1 = nn.Conv2d(1, 6, 3)
self.conv2 = nn.Conv2d(6, 16, 3)
# 3 , y=wx+b
self.fc1 = nn.Linear(16 * 6 * 6, 120) # 6*6 from image dimension
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
# relu
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
# number
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
x = x.view(-1, self.num_flat_features(x))
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
def num_flat_features(self, x):
size = x.size()[1:] # 0 batch number,
num_features = 1
for s in size:
num_features *= s
return num_features
net = Net()
print(net)
Net(
(conv1): Conv2d(1, 6, kernel_size=(3, 3), stride=(1, 1))
(conv2): Conv2d(6, 16, kernel_size=(3, 3), stride=(1, 1))
(fc1): Linear(in_features=576, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
forwardメソッドを定義するだけで、後方関数(微分を自動的に計算する関数)が自動的に定義されます.もちろんautogradパラメータをTrueに設定する必要があります.forwardメソッドでは、テンソルの任意の演算を使用できます.
モデルの学習パラメータはnet.parameters()が返されます.
params = list(net.parameters())
print(len(params))
print(params[0].size()) # conv1's .weight
10
torch.Size([6, 1, 3, 3])
このネットワークは3232のデータセットに適している(13232は1つのコアが5のボリューム層を経て、大きさは62828になる;1つのコアが2のプール化層を経て、大きさは61414になる;もう1つのコアが5のボリューム層を経て、大きさは160100になる;プール化層、165*5、ちょうど次の線形層の入力特徴数である).モデルを実行しましょう.
input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)
tensor([[ 0.0219, 0.0002, 0.0533, -0.0077, -0.0179, -0.0888, -0.0075, 0.0175,
0.0084, 0.0613]], grad_fn=)
勾配を0にクリアし、ランダム勾配を使用して逆方向に伝播します.
net.zero_grad()
out.backward(torch.randn(1, 10))
注意:
torch.nnはバッチデータの処理のみをサポートし、単一のサンプルはサポートしません.
例えばnn.Conv 2 dは入力として4次元テンソルを必要とする:[nSamples,nChannels,Height,Width.]
サンプルが1つしかない場合はinputを使用できます.unsqueeze(0)は、偽のbatch次元を追加します.
継続する前に、学んだばかりのいくつかのクラスを振り返ってみましょう.
その上で、私たちはすでにしました.
残り:
損失関数には、2つの入力(予測値と実際の値)が含まれ、2つの値の距離が返されます.
nn packageには異なる損失関数があります.簡単な損失関数はnn.MSELOssは、平均分散、すなわち、各成分が減算された二乗累計最終除算成分の個数を返す.
output = net(input)
target = torch.randn(10) # a dummy target, for example
target = target.view(1, -1) # make it the same shape as output
criterion = nn.MSELoss()
loss = criterion(output, target)
print(loss)
tensor(1.1062, grad_fn=)
だからlossを呼び出すとbackward()の場合、計算図全体で微分され、すべてのrequires_grad=Trueのテンソルの.gradプロパティは加算されます.
それをよりよく理解するために、わずかなステップをリストします.
print(loss.grad_fn) # MSELoss
print(loss.grad_fn.next_functions[0][0]) # Linear
print(loss.grad_fn.next_functions[0][0].next_functions[0][0]) # ReLU
ぎゃくほうこうでんぱ
誤差を逆方向に伝播するために私たちがしなければならないのはlossを呼び出すだけです.backward().既存の勾配をクリアする必要があります.そうしないと、勾配は既存の勾配と累積されます.
lossを呼び出します.backward()はconv 1’sのbiasの勾配の逆伝搬前後の変化を見た.
net.zero_grad() # zeroes the gradient buffers of all parameters
print('conv1.bias.grad before backward')
print(net.conv1.bias.grad)
loss.backward()
print('conv1.bias.grad after backward')
print(net.conv1.bias.grad)
conv1.bias.grad before backward
tensor([0., 0., 0., 0., 0., 0.])
conv1.bias.grad after backward
tensor([ 0.0098, 0.0003, -0.0068, 0.0056, -0.0279, -0.0121])
損失関数の使用方法を知っています.
後で読む:
nn packageは種々の深さニューラルネットワークのモジュールと損失関数を含む.ここには完全なリストがありますhttp://pytorch.org/docs/nn
私たちがしなければならない最後のステップは、
ネットワークモデルのウェイト値の更新(パラメータ)
ウェイトの更新(Update Weights)
実際によく使われる最も簡単な更新ルールは、Stochastic Gradient Descent(SGD)です.
weight = weight - learning_rate * gradient
上式はpythonコードで実現されます.
learning_rate=0.01
for f in net.parameters():
f.data.sub_(learning_rate*f.grad.data)
しかし、ニューラルネットワークを使用する場合、SGD(ランダム勾配降下法)、Nesterov-SGD、Adam、RMSProp(平均二乗伝播)など、さまざまな更新規則を使用したいと思っています.ライブラリtorchでこれらの方法をすべて実現しました.optim中です.使用も簡単です.
import torch.optim as optim
# create your optimizer
optimizer = optim.SGD(net.parameters(), lr=0.01)
# in your training loop:
optimizer.zero_grad() # zero the gradient buffers
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step() # Does the update
注意:
勾配キャッシュを0、すなわちoptimizerに手動で設定する必要があることが観察された.zero_grad()は,逆伝搬の節でも述べたように勾配が積算されるためである.