자꾸 까먹어서 공식홈 튜토리얼 보고 그냥 따라쳤다.
신경망 정의하기(LeNet)
import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
#Channel in 1, Channel out 6, filter 3x3
self.conv1 = nn.Conv2d(1, 6, 3)
self.conv2 = nn.Conv2d(6, 16, 3)
self.fc1 = nn.Linear(16 * 6 * 6, 120) # 6*6 = Image Dimension
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
# (2, 2) max pooling
x = self.conv1(x)
x = F.relu(x)
x = F.max_pool2d(x, (2, 2))
x = self.conv2(x)
x = F.relu(x)
x = F.max_pool2d(x, 2) # Same as (2,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:] # except batch dimension
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
함수만 정의하면 backward
함수는 autograd
를 사용하여 자동으로 정의됨
학습 가능한 매개변수 반환: net.parameters()
params = list(net.parameters())
print(len(params))
print(params[0].size()) #conv1 .weight
10
torch.Size([6, 1, 3, 3])
임의의 32x32
입력값 넣기
지금 신경망(LeNet)의 입력 크기는 32x32이므로 다를 경우 전처리 해줘야 함
input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)
tensor([[ 0.1355, 0.0196, 0.0171, 0.0212, -0.0444, 0.1296, -0.0707, -0.1405,
0.0687, 0.1195]], grad_fn=<AddmmBackward>)
torch.nn
은 미니배치만 지원함
nnConv2d
는nSamples x nChannels x Height x Width
의 4차원 Tensor를 입력으로 함
하나의 샘플만 있을 경우
input.unsqueeze(0)
을 사용해서 가상의 차원을 추가
손실 함수
output = net(input)
target = torch.randn(10)
target = target.view(1, -1)
criterion = nn.MSELoss()
loss = criterion(output, target)
print(loss)
tensor(0.9602, grad_fn=<MseLossBackward>)
역전파(BackPropagation)
net.zero_grad()
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.0241, 0.0114, -0.0016, 0.0101, 0.0079, 0.0082])
가중치 갱신
개념
learning_rate = 0.01
for f in net.parameters():
f.data.sub_(f.grad.data * learning_rate)
하지만 이렇게 하지는 않고 torch.optim
을 사용
import torch.optim as optim
optimizer = optim.SGD(net.parameters(), lr=0.01) # Stochastic Gradient Descent
# Training Loop
optimizer.zero_grad()
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step()
optimizer.zero_grad()
를 사용하여 수동으로 변화도 버퍼를 0으로 설정(누적방지)