[PyTorch] 각 Layer별 역할 및 파라미터

PyTorch Layer 이해하기

Load Packages

1
2
3
4
5
6
import torch
from torchvision import datasets, transforms

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

예제 불러오기

1
2
3
4
5
6
7
8
9
10
11
train_loader = torch.utils.data.DataLoader(
datasets.MNIST('dataset', train=True, download=True,
transform=transforms.Compose([
transforms.ToTensor()
])),
batch_size=1)

image, label = next(iter(train_loader))
image.shape, label.shape

=> (torch.Size([1, 1, 28, 28]), torch.Size([1]))
1
2
plt.imshow(image[0, 0, :, :], 'gray')
plt.show()

각 Layer별 설명

Network 쌓기 위한 준비를 합니다.

1
2
3
import torch
import torch.nn as nn
import torch.nn.functional as F

Convolution

  • in_channels : 받게 될 channel의 갯수
  • out_channels : 보내고 싶은 channel의 갯수
  • kernel_size : 만들고 싶은 kernel(weights)의 사이즈
1
2
3
4
# Device type : cpu, cuda, mkldnn, opengl, opencl, ideep, hip, msnpu
layer = nn.Conv2d(in_channels=1, out_channels=20, kernel_size=5, stride=1).to(torch.device('cpu'))

=> Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))

weight 시각화를 위해 slice하고 numpy화 합니다.

1
2
3
4
weight = layer.weight
weight.shape

=> torch.Size([20, 1, 5, 5])
  • 여기서 weight는 학습 가능한 상태이기 때문에 바로 numpy로 뽑아낼 수 없다.
  • detach() method는 그래프에서 잠깐 꺼내서 gradient에 영향을 받지 않게 한다.
1
2
3
4
weight = weight.detach().numpy()
weight.shape

=> (20, 1, 5, 5)
1
2
3
plt.imshow(weight[0, 0, :, :], 'jet')
plt.colorbar()
plt.show()

  • output 시각화 준비를 위해 numpy화 합니다.
1
2
3
4
5
6
output_data = layer(image)
output_data = output_data.data
output = output_data.cpu().numpy()
output.shape

=> (1, 20, 24, 24)
  • input으로 들어간 이미지 numpy화 한다.
1
2
3
4
image_arr = image.numpy()
image_arr.shape

=> (1, 1, 28, 28)
1
2
3
4
5
6
7
8
9
10
11
plt.figure(figsize=(15, 30))
plt.subplot(131)
plt.title('Input')
plt.imshow(np.squeeze(image_arr), 'gray')
plt.subplot(132)
plt.title('Weight')
plt.imshow(weight[0, 0, :, :], 'jet')
plt.subplot(133)
plt.title('Output')
plt.imshow(output[0, 0, :, :], 'gray')
plt.show()

Pooling

input을 먼저 앞에 넣고, 뒤어 kernel 사이즈와 stride를 순서대로 넣는다.

1
2
3
4
pool = F.max_pool2d(image, 2, 2)
pool.shape

=> torch.Size([1, 1, 14, 14])

MaxPool Layer는 weight가 없기 때문에 바로 numpy() 사용 가능하다.

1
2
3
4
pool_arr = pool.numpy()
pool_arr.shape, image_arr.shape

=> ((1, 1, 14, 14), (1, 1, 28, 28))
1
2
3
4
5
6
7
8
plt.figure(figsize=(10, 15))
plt.subplot(121)
plt.title("Input")
plt.imshow(np.squeeze(image_arr), 'gray')
plt.subplot(122)
plt.title('Output')
plt.imshow(np.squeeze(pool_arr), 'gray')
plt.show()

Linear

nn.Linear는 2D가 아닌 1D만 들어가기 때문에 view() 함수를 사용하여 1D로 펼쳐줘야 한다.

1
2
3
4
5
# image size가 28 이기 때문에 28 * 28을 넣는다.
flatten = image.view(1, 28 * 28)
flatten.shape

=> torch.Size([1, 784])
1
2
3
4
5
6
7
8
9
lin = nn.Linear(784, 10)(flatten)
lin.shape

=> torch.Size([1, 10])

lin

=> tensor([[-0.1198, 0.2404, -0.0522, -0.3474, -0.3997, -0.0318, -0.0630, 0.2680,
0.1849, 0.1000]], grad_fn=<AddmmBackward>)
1
2
plt.imshow(lin.detach().numpy(), 'jet')
plt.show()

Softmax

결과를 numpy로 꺼재기 위해선 weight가 담긴 Linear에 weight를 꺼줘야 한다.

1
2
3
4
5
6
7
8
9
with torch.no_grad():
flatten = image.view(1, 28 * 28)
lin = nn.Linear(784, 10)(flatten)
softmax = F.softmax(lin, dim=1)

softmax

=> tensor([[0.0846, 0.1084, 0.0792, 0.1265, 0.1004, 0.0897, 0.0990, 0.1113, 0.1239,
0.0769]])
1
2
np.sum(softmax.numpy())
=> 0.99999994

Layer 쌓기

예제 출처 : https://pytorch.org/tutorials/beginner/pytorch_with_examples.html#id23

nn 과 nn.functional의 차이점

  • nn은 학습 파라미터가 담긴 것
  • nn.functional은 학습 파라미터가 없는 것
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 20, 5, 1)
self.conv2 = nn.Conv2d(20, 50, 5, 1)
self.fc1 = nn.Linear(4 * 4 * 50, 500)
self.fc2 = nn.Linear(500, 10)

def forward(self, x):
# Feature Extraction
x = F.relu(self.conv1(x))
x = F.max_pool2d(x, 2, 2)
x = F.relu(self.conv2(x))
x = F.max_pool2d(x, 2, 2)

# Fully Connected (Classficiation)
x = x.view(-1, 4 * 4 * 50)
x = F.relu(self.fc1(x))
x = self.fc2(x)

return F.log_softmax(x, dim=1)

image를 Model에 넣어서 결과를 확인한다.

1
2
3
4
5
model = Net()
result = model.forward(image)

=> tensor([[-2.3262, -2.2901, -2.2722, -2.2262, -2.3148, -2.3693, -2.2773, -2.2977,
-2.3222, -2.3371]], grad_fn=<LogSoftmaxBackward>)
Share