신경망은 데이터에 대한 연산을 수행하는 계층(layer)/모듈(module)로 구성되어 있다. torch.nn네임스페이스는 신경망을 구성하는데 필요한 모든 구성 요소를 제공한다. PyTorch의 모든 모듈은 nn.Module의 하위 클래스(subclass)이다. 신경망은 다른 모듈(계층; layer)로 구성된 모듈이다. 이러한 중첩된 구조는 복잡한 아키텍처를 쉽게 구축하고 관리할 수 있다.
학습을 위한 장치 얻기
가능한 경우 GPU와 같은 하드웨어 가속기에서 모델을 학습하려고 한다. torch.cuda를 사용할 수 있는지 확인하고 그렇지 않으면 CPU를 계속 사용한다.
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print('Using {} device'.format(device))
클래스 정의하기
신경망 모델을 nn.Module의 하위클래스로 정의하고, __init__에서 신경망 계층들을 초기화한다. nn.Module을 상속받은 모든 클래스는 forward메소드에 입력 데이터에 대한 연산들을 구현한다.
class NeuralNetwork(nn.Module):
def __init__(self):
super(NeuralNetwork, self).__init__()
self.flatten = nn.Flatten()
self.linear_relu_stack = nn.Sequential(
nn.Linear(28*28, 512),
nn.ReLU(),
nn.Linear(512, 512),
nn.ReLU(),
nn.Linear(512, 10),
nn.ReLU()
)
def forward(self, x):
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
NeuralNetwork의 인스턴스(instance)를 생성하고 이를 device로 이동한 뒤, 구조(structure)를 출력한다.
model = NeuralNetwork().to(device)
print(model)
Out:
NeuralNetwork(
(flatten): Flatten(start_dim=1, end_dim=-1)
(linear_relu_stack): Sequential(
(0): Linear(in_features=784, out_features=512, bias=True)
(1): ReLU()
(2): Linear(in_features=512, out_features=512, bias=True)
(3): ReLU()
(4): Linear(in_features=512, out_features=10, bias=True)
(5): ReLU()
)
)
모델을 사용하기 위해 입력 데이터를 전달한다. 이는 일부 백그라운드 연산들과 함께 모델의 forward를 실행한다. model.forward()를 직접 호출하지 말자. (forward가 더 직접적인 표현이라고 생각해서 사용했었는데 아프로는 사요하지 말아야겠다.)
모델에 입력을 호출하면 각 분류(class)에 대한 원시(raw) 예측값이 있는 10-차원 텐서가 반환된다. 원시 예측값을 nn.Softmax모듈의 인스턴스에 통과시켜 예측 확률을 얻는다.
X = torch.rand(1, 28, 28, device=device)
logits = model(X)
pred_probab = nn.Softmax(dim=1)(logits)
y_pred = pred_probab.argmax(1)
print(f"Predicted class: {y_pred}")
모델 계층(Layer)
FashionMNIST 모델의 계층들을 살펴자. 이를 설명하기 위해, 28x28 크기의 이미지 3개로 구성된 미니배치를 가져와, 신경망을 통과할 때 어떤 일이 발생하는지 알아보자.
input_image = torch.rand(3,28,28)
print(input_image.size())
# torch.Size([3, 28, 28])
nn.Flatten
nn.Flatten계층을 초기화하여 각 28x28의 2D 이미지를 784 픽셀 값을 갖는 연속된 배열로 변환한다. (dim=0의 미니배치 차원은 유지된다.)
flatten = nn.Flatten()
flat_image = flatten(input_image)
print(flat_image.size())
# torch.Size([3, 784])
nn.Linear
선형 계층은 저장된 가중치(weight)와 편향(bias)을 사용하여 입력에 선형 변환(linear transformation)을 적용하는 모듈입이다.
layer1 = nn.Linear(in_features=28*28, out_features=20)
hidden1 = layer1(flat_image)
print(hidden1.size())
# torch.Size([3, 20])
nn.ReLU
비선형 활성화(activation)는 모델의 입력과 출력 사이에 복잡한 관계(mapping)를 만든다. 비선형 활성화는 선형 변환 후에 적용되어 비선형성(nonlinearity)을 도입하고, 신경망이 다양한 현상을 학습할 수 있도록 돕는다.
이 모델에서는 nn.ReLU를 선형 계층들 사이에 사용하지만, 모델을 만들 때는 비선형성을 가진 다른 활성화를 도입할 수도 있다.
print(f"Before ReLU: {hidden1}\n\n")
hidden1 = nn.ReLU()(hidden1)
print(f"After ReLU: {hidden1}")
Out:
Before ReLU: tensor([[ 4.1802e-01, -2.0891e-01, -4.5899e-02, -3.3012e-01, -1.1608e-01,
3.2973e-03, 3.2860e-03, -6.3945e-02, 3.4541e-01, -1.6342e-01,
-7.2333e-01, 1.1853e-01, -6.0752e-02, 5.8124e-02, -8.5588e-01,
-5.5783e-01, -5.4508e-02, 1.9725e-01, 1.3158e-01, 5.1474e-01],
[ 1.8858e-01, -8.4326e-02, -3.4691e-01, -2.7519e-01, -2.3116e-01,
6.7568e-02, 3.7079e-01, -1.7097e-01, 3.3664e-01, -1.7874e-01,
-7.4063e-01, 1.9791e-01, 7.7300e-04, 1.5679e-01, -9.4724e-01,
-6.6287e-01, -2.2564e-01, -2.8688e-01, -8.5341e-03, -9.9795e-04],
[ 1.8742e-01, -2.6774e-01, -3.3508e-01, -5.2455e-01, -2.6225e-01,
-2.3107e-01, 1.2318e-01, -3.0981e-01, 8.8801e-02, -2.9063e-01,
-5.9034e-01, 1.2069e-01, 1.2879e-01, 2.2934e-01, -5.0672e-01,
-6.9769e-01, 6.9980e-02, -1.2551e-01, 1.1706e-01, 4.8915e-01]],
grad_fn=<AddmmBackward>)
After ReLU: tensor([[0.4180, 0.0000, 0.0000, 0.0000, 0.0000, 0.0033, 0.0033, 0.0000, 0.3454,
0.0000, 0.0000, 0.1185, 0.0000, 0.0581, 0.0000, 0.0000, 0.0000, 0.1973,
0.1316, 0.5147],
[0.1886, 0.0000, 0.0000, 0.0000, 0.0000, 0.0676, 0.3708, 0.0000, 0.3366,
0.0000, 0.0000, 0.1979, 0.0008, 0.1568, 0.0000, 0.0000, 0.0000, 0.0000,
0.0000, 0.0000],
[0.1874, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.1232, 0.0000, 0.0888,
0.0000, 0.0000, 0.1207, 0.1288, 0.2293, 0.0000, 0.0000, 0.0700, 0.0000,
0.1171, 0.4891]], grad_fn=<ReluBackward0>)
nn.Sequential
nn.Sequential은 순서를 갖는 모듈의 컨테이너이다. 데이터는 정의된 것과 같은 순서로 모든 모듈들을 통해 전달된다. 순차 컨테이너(sequential container)를 사용하여 아래의 seq_modules와 같은 신경망을 빠르게 만들 수 있다.
seq_modules = nn.Sequential(
flatten,
layer1,
nn.ReLU(),
nn.Linear(20, 10)
)
input_image = torch.rand(3,28,28)
logits = seq_modules(input_image)
nn.Softmax
신경망의 마지막 선형 계층은 nn.Softmax모듈에 전달될 ([-infty, infty] 범위의 원시 값(raw value)인) logits 를 반환한다. logits는 모델의 각 분류(class)에 대한 예측 확률을 나타내도록 [0, 1] 범위로 비례하여 조정(scale)된다. dim매개변수는 값의 합이 1이 되는 차원을 나타낸다.
softmax = nn.Softmax(dim=1)
pred_probab = softmax(logits)
모델 매개변수
신경망 내부의 많은 계층들은 매개변수화(parameterize)된다. 즉, 학습 중에 최적화되는 가중치와 편향과 연관지어진다. nn.Module을 상속하면 모델 객체 내부의 모든 필드들이 자동으로 추적(track)되며, 모델의 parameters()및 named_parameters()메소드로 모든 매개변수에 접근할 수 있게 된다.
아래 예제에서는 각 매개변수들을 순회하며(iterate), 매개변수의 크기와 값을 출력한다.
print("Model structure: ", model, "\n\n")
for name, param in model.named_parameters():
print(f"Layer: {name} | Size: {param.size()} | Values : {param[:2]} \n")
Out:
Model structure: NeuralNetwork(
(flatten): Flatten(start_dim=1, end_dim=-1)
(linear_relu_stack): Sequential(
(0): Linear(in_features=784, out_features=512, bias=True)
(1): ReLU()
(2): Linear(in_features=512, out_features=512, bias=True)
(3): ReLU()
(4): Linear(in_features=512, out_features=10, bias=True)
(5): ReLU()
)
)
Layer: linear_relu_stack.0.weight | Size: torch.Size([512, 784]) | Values : tensor([[-0.0071, -0.0260, 0.0311, ..., 0.0099, -0.0002, 0.0102],
[ 0.0024, -0.0296, 0.0093, ..., -0.0091, 0.0080, 0.0004]],
device='cuda:0', grad_fn=<SliceBackward>)
Layer: linear_relu_stack.0.bias | Size: torch.Size([512]) | Values : tensor([-0.0294, -0.0280], device='cuda:0', grad_fn=<SliceBackward>)
Layer: linear_relu_stack.2.weight | Size: torch.Size([512, 512]) | Values : tensor([[-0.0435, -0.0110, 0.0110, ..., 0.0429, -0.0348, -0.0375],
[-0.0166, -0.0264, 0.0406, ..., 0.0188, 0.0344, -0.0395]],
device='cuda:0', grad_fn=<SliceBackward>)
Layer: linear_relu_stack.2.bias | Size: torch.Size([512]) | Values : tensor([0.0296, 0.0216], device='cuda:0', grad_fn=<SliceBackward>)
Layer: linear_relu_stack.4.weight | Size: torch.Size([10, 512]) | Values : tensor([[ 3.3242e-02, 9.6526e-03, -2.1534e-02, ..., 5.6896e-03,
-7.0137e-03, 2.6827e-02],
[-1.0889e-02, 1.2723e-05, -3.3012e-02, ..., 7.6711e-03,
6.8862e-03, -8.8320e-03]], device='cuda:0', grad_fn=<SliceBackward>)
Layer: linear_relu_stack.4.bias | Size: torch.Size([10]) | Values : tensor([-0.0014, -0.0122], device='cuda:0', grad_fn=<SliceBackward>)
참고: https://tutorials.pytorch.kr/beginner/basics/buildmodel_tutorial.html
'Python > PyTorch' 카테고리의 다른 글
[Pytorch] COCO Data format과 Pycocotools (0) | 2021.09.27 |
---|---|
[Pytorch] TORCH.AUTOGRAD를 사용한 자동 미분 (0) | 2021.09.26 |
[Pytorch] Transform (0) | 2021.09.25 |
[Pytorch] Dataset과 Dataloader (0) | 2021.09.25 |
[Pytorch] .requires_grad(), torch.no_grad(), model.eval() (0) | 2021.09.06 |