1. nn.Module을 이용해 모델 생성
■ 합성곱 신경망은 이미지에 대한 특징을 추출(학습)한 다음, 추론을 위해 평탄화한 후 출력층에 데이터를 넣게 된다.
■ CNN에는 합성곱(Conv) 계층과 풀링(Pooling) 계층이 존재한다. '합성곱 계층 - 활성화 함수 계층 - (풀링 계층)' 흐름으로 연결되며, 풀링 계층을 생략하기도 한다.
합성곱 신경망(CNN) (1)
1. 합성곱 신경망(Convolutional Neural Network, CNN)■ 합성곱 신경망CNN은 컨브넷(convnet)이라고도 부르며 이미지 인식, 음성 등 다양한 곳에 사용된다. 특히 이미지 인식 분야에서 활용도가 높다.■ 인접
hyeon-jae.tistory.com
■ 파이토치는 예를 들어 데이터가 2차원 이미지 데이터이면 합성곱 계층은 nn.Conv2d, 최대 풀링 계층은 nn.MaxPool2d를 사용하고, 추론을 위한 FCN 구조의 계층은 nn.Linear를 사용한다.
■ 예를 들어 CIFAR-10 데이터 셋을 사용해서 nn.ModuleI로 CNN 모델을 설계해 보자.
- CIFAR-10 데이터 셋은 비행기, 자동차, 트럭, 고양이, 개, 말, 새, 개구리 등 10개의 클래스로 구성돼 있으며, 학습 데이터 셋은 각 클래스별 5,000장 이미지, 검증 데이터 셋은 각 클래스별 1,000장의 이미지로 이뤄져 있다.
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms, datasets
BATCH_SIZE = 32
train_dataset = datasets.CIFAR10(root = "../data/CIFAR_10",
train = True,
download = True,
transform = transforms.ToTensor())
test_dataset = datasets.CIFAR10(root = "../data/CIFAR_10",
train = False,
transform = transforms.ToTensor())
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)
for (X_train, y_train) in train_loader:
print('X_train:', X_train.size(), 'type:', X_train.type())
print('y_train:', y_train.size(), 'type:', y_train.type())
break
```#결과#```
X_train: torch.Size([32, 3, 32, 32]) type: torch.FloatTensor
y_train: torch.Size([32]) type: torch.LongTensor
````````````
- x_train의 형상을 보면, 1개의 미니배치에 32 x 32 크기의 이미지 32개로 이뤄진 것을 확인할 수 있다.
- 이때, 채널의 수가 3이므로 이미지는 red, green, blue 즉, RGB 색상으로 이뤄진 컬러 이미지임을 확인할 수 있다.
- 즉, 32 x 32 크기의 컬러 이미지 32개로 이뤄진 것이다.
- 32개의 이미지 데이터 각각에 대해 레이블 값이 1개가 존재하므로, y_train은 32개의 값을 가진다.
■ 만약, MLP를 설계한다면 입력 데이터를 1차원 벡터로 펼쳐서 사용해야 하기 때문에 첫 번째 완전연결 층의 입력은 32 x 32 x 3 = 3,072 개의 차원을 갖는 벡터가 된다.
■ 이렇게 1차원 벡터로 진행할 경우 이미지의 공간 정보가 무시된다. 특히, 채널 수가 1인 흑백 이미지보다 채널 수가 3으로 다양한 색을 나타내는 컬러 이미지의 공간 정보 손실이 더 클 수밖에 없다. 그러므로 MLP 모델보다는 CNN 모델을 사용하는 것이 바람직하다.
- CIFAR-10 이미지 데이터는 32 x 32 x 3으로 32 x 32 크기의 2차원 이미지 3개가 겹쳐 이미지를 형성하므로 28 x 28 크기의 2차원 이미지 1개로 구성된 FashionMNIST 이미지 데이터보다 1차원으로 펼쳤을 때 이미지의 특징을 잃어버리는 것에 더욱 민감할 수밖에 없다. 그러므로 다음과 같은 CNN 모델을 사용하는 것이 바람직하다.
class CNN(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(in_channels = 3, out_channels = 8,
kernel_size = 3, stride=1, padding = 1)
self.conv2 = nn.Conv2d(8, 16, 3, 1, 1)
self.pool = nn.MaxPool2d(kernel_size = 2, stride = 2)
self.fc1 = nn.Linear(8 * 8 * 16, 64)
self.fc2 = nn.Linear(64, 32)
self.fc3 = nn.Linear(32, 10)
self.bh2d_1 = nn.BatchNorm2d(num_features = 8)
self.bh2d_2 = nn.BatchNorm2d(16)
self.bh1d_1 = nn.BatchNorm1d(64)
self.bh1d_2 = nn.BatchNorm1d(32)
def forward(self, x):
x = self.conv1(x)
x = self.bh2d_1(x)
x = F.relu(x)
x = self.pool(x)
x = self.conv2(x)
x = self.bh2d_2(x)
x = F.relu(x)
x = self.pool(x)
x = x.view(-1, 8 * 8 * 16) # 평탄화
x = self.fc1(x)
x = self.bh1d_1(x)
x = F.relu(x)
x = self.fc2(x)
x = self.bh1d_2(x)
x = F.relu(x)
x = self.fc3(x)
x = F.log_softmax(x)
return x
■ nn.Conv2d 메서드를 이용해 컨볼루션 연산을 하는 필터(커널)를 정의한다.
(1) in_channels
- 이때, 채널 수는 입력 이미지의 채널 수와 동일하게 맞춰야 한다. 이 예에서는 입력 이미지는 컬러 이미지라서 채널 수는 3이다. (red, green, blue channel)
- 그러므로, 3개 채널의 픽셀에 대해 동시에 컨볼루션 연산을 진행하기 위해 첫 번째 컨볼루션 계층의 in_channels = 3으로 설정한다. in_channels에는 입력 채널의 개수를 지정한다.
(2) out_channels
- nn.Conv2d의 out_channels은 출력 채널의 개수, 즉 컨볼루션 연산을 진행하는 필터(커널)의 개수이다.
- 여기서 지정한 필터 개수만큼 output의 depth(채널 수)가 정해진다. 필터 개수만큼 앞뒤로 쌓아 피처 맵을 형성하기 때문이다. 이 예에서는 in_channels = 8로 지정했기 때문에 첫 번째 컨볼루션 결과는 depth가 8인 피처맵이 생성된다.
- 필터의 개수가 많을수록 이미지에서 더 복잡한 특징을 학습(추출)할 수 있지만, 모델의 파라미터 개수가 증가한다.
(3) kernel_size, stride, padding
- kernel_size는 컨볼루션 필터의 크기를 설정하는 부분이다.
- 예를 들어 3 x 3 필터를 사용하고 싶으면 kernel_size = 3 또는 kernel_size = (3, 3)으로 필터의 크기를 지정할 수 있다.
- stride는 필터의 이동 간격, padding은 출력 피처 맵의 크기를 보존하기 위해 입력 데이터의 가장자리에 추가되는 패딩의 크기를 설정하는 부분이다.
- padding = 1로 지정하면 가장자리의 왼쪽, 오른쪽, 위, 아래쪽에 층을 하나 더 만들고, 그 안에는 0을 채운다.
- 패딩을 지정하지 않는다면, 필터가 이미지 위를 돌아다니면서 겹치는 영역(컨볼루션 연산을 하는 부분)이 구석 부분보다 중앙 부분이 자주 겹치므로, 이미지 구석 부분에 대한 특징 추출이 중앙 부분보다 덜할 수밖에 없다.
- 패딩을 지정하면 이미지 구석(모서리) 부분과 중앙 부분이 컨볼루션 연산되는 횟수를 동일하게 맞출 수 있다.
(4) bias = True
- bias = True는 기본값으로 컨볼루션 연산 이후 bias 값을 더해줄 것인지를 선택하는 옵션이다.
- 만약, Conv2d 레이어 직후에 BatchNorm2d 레이어가 있는 경우 컨볼루션 레이어의 편향은 필요하지 않아 bias = False로 설정해도 된다.
- BatchNorm 레이어에서 평균을 빼기 때문에 bias의 효과가 상쇄된다.
Performance Tuning Guide — PyTorch Tutorials 2.5.0+cu124 documentation
Note Click here to download the full example code Performance Tuning Guide Author: Szymon Migacz Performance Tuning Guide is a set of optimizations and best practices which can accelerate training and inference of deep learning models in PyTorch. Presented
pytorch.org
- 이 예에서는 bias = True로 설정하였다.
■ 첫 번째 Conv2d 함수는 2차원의 입력 이미지 데이터를 컨볼루션 연산하는 필터의 속성을 정의한 것이다. 이제, 두 번째 Conv2d 함수에는 첫 번째 Conv2d 함수의 결과로 나온 피처 맵과 컨볼루션 연산을 진행하는 필터의 속성을 정의한다.
- 두 번째 Conv2d 함수의 in_channels은 첫 번째 컨볼루션 결과, 출력 채널 개수 8이 두 번째 Conv2d의 입장에서는 입력 채널 개수 8이므로 in_channels = 8으로 지정한다.
- 이 예에서는 out_channels = 16으로 지정했다. 그러므로 두 번째 컨볼루션 연산 결과는 depth가 16인 피처 맵이 생성된다.
■ 컨볼루션 연산을 통해 피처 맵이 생성됐을 때, 최대 풀링을 이용해 2차원 피처 맵의 크기를 줄이면서, 피처 맵에서 가장 큰 피처 맵의 값만 사용할 수 있다.
- 이 예에서 사용한 최대 풀링의 크기는 2 x 2이다.
- 2 x 2 필터가 피처 맵을 지정한 stride 값만큼 이동하면서 2 x 2 = 4개의 값 중 최댓값 1개만 선택하므로 나머지 3개의 값은 버려진다.
■ 컨볼루션 연산 과정이 모두 끝나면, FCN 분류기를 통해 이미지를 분류하기 위해 생성된 최종 피처 맵을 1차원으로 펼쳐 여러 층의 완전연결 계층에 통과시킨다.
■ 컨볼루션 연산을 하는 이유는 이미지 내 주변 픽셀과의 조합을 통해서 이미지의 특징을 추출(학습)하기 위해서이다.
■ 여러 번의 컨볼루션 연산을 통해 산출된 피처 맵은 이미지의 지역 정보를 반영한 결괏값이다.
■ 즉, 피처 맵을 1차원으로 펼쳐도 이미 지역 정보가 반영되어 있으므로, 지역 정보를 전혀 반영하지 못하는 기존 MLP의 문제점을 해결할 수 있다.
■ 이 예에서 최종 피처 맵의 크기는 8 x 8 x 16이므로, view 함수를 통해 이 피처 맵을 1차원으로 평탄화시킨다.
- 최종 피처 맵의 크기가 8 x 8 x 16이 된 이유는
- 먼저, 입력 이미지의 크기 (H, W) = (32, 32)이고, 첫 번째 Conv의 필터 크기는 3 x 3, stride = 1, padding = 1이므로 출력 크기는 OH = (32 + 2 - 3)/1 + 1 = 32, OW = (32 + 2 - 3)/1 + 1 = 32로 32 x 32이며, 출력 채널의 개수를 8로 지정했으므로 첫 번째 컨볼루션 연산으로 생성되는 피처 맵은 32 x 32 x 8이다.
- 그다음, 풀링의 필터 크기는 2 x 2, stride = 2이므로 OH = (32 + 0 - 2)/2 + 1 = 16, OW = (32 + 0 - 2)/2 + 1 = 16이므로 피처 맵의 크기는 다운 샘플링되어 16 x 16 x 8이 된다.
- 따라서 두 번째 합성곱의 입력 채널의 수 in_channels = 8로 설정해야 한다.
- 두 번째 Conv의 필터 크기는 3 x 3, stride = 1, padding = 1이므로 OH = (16 + 2 - 3)/1 + 1 = 16, OW = (16 + 2 - 3)/1 + 1 = 16으로 출력 크기는 16 x 16이 되며, 출력 채널의 개수를 16으로 설정했으므로 두 번째 컨볼루션 연산으로 생성되는 피처 맵의 크기는 16 x 16 x 16이 된다.
- 그다음, 풀링의 필터 크기는 2 x 2, stride = 2이므로 OH = (16 + 0 - 2)/2 + 1 = 8, OW = (16 + 0 - 2)/2 + 1 = 8이므로 피처 맵의 크기는 다운 샘플링되어 8 x 8 x 16이 된다.
- 최종 산출된 피처 맵을 평탄화시키면 첫 번째 완전연결 계층의 노드 수는 8 x 8 x 16 = 1024개가 된다.
■ 순전파 과정을 정의한 forward 함수를 보면, CNN 부분의 흐름은 '합성곱 계층 - 활성화 함수 계층 - (풀링 계층)'으로 흐르고, FCN 부분의 흐름은 '어파인 계층 - (활성화 함수 계층) -.... - 어파인 계층 - 출력층'으로 흘러간다.
- 데이터 셋의 클래스의 개수는 10개이므로 마지막 완전연결 계층의 output의 크기는 10으로 지정해야 한다.
def initialize_weights(m):
if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear):
nn.init.kaiming_uniform_(m.weight.data, nonlinearity='relu')
- 활성화 함수로 비선형 함수인 relu를 사용하므로, 가중치 초깃값은 He 초깃값을 사용한다. 이때, 위와 같이 가중치 데이터가 있는 Conv2d와 Linear에 He 초깃값을 적용한다.
model = CNN().to(DEVICE)
model.apply(initialize_weights) # He 초깃값 적용
optimizer = torch.optim.Adam(model.parameters(), lr = 0.001)
criterion = nn.CrossEntropyLoss()
cf) Conv2d의 가중치 값은 .weight를 통해 확인할 수 있다.
layer = nn.Conv2d(1,2,2,1).to(torch.device('cpu'))
layer
```#결과#```
Conv2d(1, 2, kernel_size=(2, 2), stride=(1, 1))
````````````
weight = layer.weight # Conv2d의 weight 값
describe_tensor(weight)
```#결과#```
형상: torch.Size([2, 1, 2, 2])
값: Parameter containing:
tensor([[[[ 0.3494, -0.1288],
[ 0.2530, 0.3442]]],
[[[ 0.3413, 0.0840],
[-0.3290, 0.2409]]]], requires_grad=True)
dtype: torch.float32
````````````
cf) 이 weight 값은 detach( ) 함수를 통해 꺼내줘야 numpy( ) 변환이 가능하다.
weight = weight.detach()
weight
```#결과#```
tensor([[[[-0.4485, 0.1075],
[ 0.1829, -0.1226]]],
[[[ 0.4412, -0.1767],
[ 0.1863, 0.4597]]]])
````````````
weight = weight.numpy() # 넘파이 변환
weight.shape
```#결과#```
(2, 1, 2, 2)
````````````
weight
```#결과#```
array([[[[ 0.34938955, -0.12882715],
[ 0.25297606, 0.3441702 ]]],
[[[ 0.3413334 , 0.08397621],
[-0.32903033, 0.2409085 ]]]], dtype=float32)
````````````
■ 생성한 모델이 어떤 계층으로 이뤄져 있는지 확인하고 싶으면 다음과 같이 생성한 모델에 children( )을 적용하면 된다.
print(list(model.children()))
```#결과#```
[Conv2d(3, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), Conv2d(8, 16, kernel_size=(3, 3),
stride=(1, 1), padding=(1, 1)), MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode
=False), Linear(in_features=1024, out_features=64, bias=True), Linear(in_features=64, out_features=
32, bias=True), Linear(in_features=32, out_features=10, bias=True), BatchNorm2d(8, eps=1e-05, momen
tum=0.1, affine=True, track_running_stats=True), BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=Tr
ue, track_running_stats=True), BatchNorm1d(64, eps=1e-05, momentum=0.1, affine=True, track_running_
stats=True), BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)]
````````````
■ 이 정보와 모델 구조를 동시에 확인하고 싶으면 생성한 모델에 modules( )를 적용하면 된다.
print(list(model.modules()))
```#결과#```
[CNN(
(conv1): Conv2d(3, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(conv2): Conv2d(8, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(fc1): Linear(in_features=1024, out_features=64, bias=True)
(fc2): Linear(in_features=64, out_features=32, bias=True)
(fc3): Linear(in_features=32, out_features=10, bias=True)
(bh2d_1): BatchNorm2d(8, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(bh2d_2): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(bh1d_1): BatchNorm1d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(bh1d_2): BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
), Conv2d(3, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), Conv2d(8, 16, kernel_size=(3,
3), stride=(1, 1), padding=(1, 1)), MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_
mode=False), Linear(in_features=1024, out_features=64, bias=True), Linear(in_features=64, out_featu
res=32, bias=True), Linear(in_features=32, out_features=10, bias=True), BatchNorm2d(8, eps=1e-05, m
omentum=0.1, affine=True, track_running_stats=True), BatchNorm2d(16, eps=1e-05, momentum=0.1, affin
e=True, track_running_stats=True), BatchNorm1d(64, eps=1e-05, momentum=0.1, affine=True, track_runn
ing_stats=True), BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)]
````````````
■ 텐서플로의 summary( ) 함수처럼 파이토치도 torchsummary의 summary( ) 함수를 통해서 모델 구조를 요약해서 확인할 수 있다. 단, 입력 이미지의 (C, H, W) 정보를 넣어줘야 한다.
from torchsummary import summary
summary(model, input_size = (3, 32, 32))
```#결과#```
----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv2d-1 [-1, 8, 32, 32] 224
BatchNorm2d-2 [-1, 8, 32, 32] 16
MaxPool2d-3 [-1, 8, 16, 16] 0
Conv2d-4 [-1, 16, 16, 16] 1,168
BatchNorm2d-5 [-1, 16, 16, 16] 32
MaxPool2d-6 [-1, 16, 8, 8] 0
Linear-7 [-1, 64] 65,600
BatchNorm1d-8 [-1, 64] 128
Linear-9 [-1, 32] 2,080
BatchNorm1d-10 [-1, 32] 64
Linear-11 [-1, 10] 330
================================================================
Total params: 69,642
Trainable params: 69,642
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.01
Forward/backward pass size (MB): 0.21
Params size (MB): 0.27
Estimated Total Size (MB): 0.49
----------------------------------------------------------------
````````````
■ CNN 결과와 MLP 결과를 비교하기 위해 다음과 같은 MLP 모델을 정의하자.
class MLP(nn.Module):
def __init__(self):
super(MLP, self).__init__()
self.fc1 = nn.Linear(32 * 32 * 3, 512)
self.fc2 = nn.Linear(512, 256)
self.fc3 = nn.Linear(256, 10)
self.batch_norm1 = nn.BatchNorm1d(512)
self.batch_norm2 = nn.BatchNorm1d(256) #
def forward(self, x):
x = x.view(-1, 32 * 32 * 3)
x = self.fc1(x)
x = self.batch_norm1(x)
x = F.relu(x)
x = self.fc2(x)
x = self.batch_norm2(x)
x = F.relu(x)
x = self.fc3(x)
x = F.log_softmax(x, dim = 1)
return x
def mlp_initialize_weights(m):
if isinstance(m, nn.Linear):
nn.init.kaiming_uniform_(m.weight.data, nonlinearity='relu')
mlp_model = MLP().to(DEVICE)
mlp_model.apply(mlp_initialize_weights)
optimizer = torch.optim.Adam(mlp_model.parameters(), lr = 0.001)
criterion = nn.CrossEntropyLoss().to(DEVICE)
- 두 모델 모두 빠르게 과적합하지만, MLP 모델의 정확도는 50% 정도에 그친 반면, 컨볼루션 연산이 추가된 CNN 모델의 정확도는 65% 정도로 향상된 것을 확인할 수 있다.
2. nn.Sequential을 이용해 모델 생성
■ 위에서 정의한 CNN 구조를 nn.Sequential을 이용해 동일하게 만들 수 있다.
■ 다음과 같이 nn.Sequential 객체로 그 안에 각 모듈을 순차적으로 실행하는 구조로 만들 수 있다.
class CNN2(nn.Module):
def __init__(self):
super().__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(3, 8, 3, 1, 1),
nn.BatchNorm2d(8),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size = 2, stride = 2)
)
self.layer2 = nn.Sequential(
nn.Conv2d(8, 16, 3, 1, 1),
nn.BatchNorm2d(16),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size = 2, stride = 2)
)
self.layer3 = nn.Sequential(
nn.Linear(8 * 8 * 16, 64),
nn.BatchNorm1d(64),
nn.ReLU(inplace=True),
nn.Linear(64, 32),
nn.BatchNorm1d(32),
nn.ReLU(inplace=True),
nn.Linear(32, 10),
)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = x.view(x.shape[0],-1) # 평탄화
x = self.layer3(x)
x = F.log_softmax(x, dim = 1)
return x
- nn.ReLU( )에는 inplace라는 인수가 있다. 이 inplace 인수를 사용하면 ReLU 함수의 연산을 in-place로 수행해서 연산 속도를 향상시킬 수 있다.
- 단, inplace를 사용할 경우 원본 텐서가 직접 수정되기 때문에, 원본 텐서를 사용하는 다른 연산에 영향을 줄 수 있다.
model2 = CNN2().to(DEVICE)
summary(model2, input_size = (3, 32, 32))
```#결과#```
----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv2d-1 [-1, 8, 32, 32] 224
BatchNorm2d-2 [-1, 8, 32, 32] 16
ReLU-3 [-1, 8, 32, 32] 0
MaxPool2d-4 [-1, 8, 16, 16] 0
Conv2d-5 [-1, 16, 16, 16] 1,168
BatchNorm2d-6 [-1, 16, 16, 16] 32
ReLU-7 [-1, 16, 16, 16] 0
MaxPool2d-8 [-1, 16, 8, 8] 0
Linear-9 [-1, 64] 65,600
BatchNorm1d-10 [-1, 64] 128
ReLU-11 [-1, 64] 0
Linear-12 [-1, 32] 2,080
BatchNorm1d-13 [-1, 32] 64
ReLU-14 [-1, 32] 0
Linear-15 [-1, 10] 330
================================================================
Total params: 69,642
Trainable params: 69,642
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.01
Forward/backward pass size (MB): 0.31
Params size (MB): 0.27
Estimated Total Size (MB): 0.58
----------------------------------------------------------------
````````````
3. 모델 저장 및 로드
https://tutorials.pytorch.kr/beginner/saving_loading_models.html
모델 저장하기 & 불러오기
Author: Matthew Inkawhich, 번역: 박정환, 김제필,. 이 문서에서는 PyTorch 모델을 저장하고 불러오는 다양한 방법을 제공합니다. 이 문서 전체를 다 읽는 것도 좋은 방법이지만, 필요한 사용 예의 코드만
tutorials.pytorch.kr
■ 파이토치 모델 저장 및 로드하는 방법으로 torch.save와 torch.load_state_dict가 있다.
■ torch.save와 torch.load는 pickle을 사용하며, torch.save는 지정한 경로에 모델의 state_dict( )을 저장한다. state_dict은 각 계층의 매개변수(가중치와 편향) 텐서를 매핑한 파이썬 딕셔너리 객체이다.
■ torch.load_state_dict는 지정한 경로에 있는 state_dict( )을 불러온다.
PATH = './fashion_mnist.pth'
torch.save(model2.state_dict(),PATH) # 저장
model3 = CNN2()
model3.load_state_dict(torch.load(PATH)) # 로드
model3 = model3.to(DEVICE)
summary(model3, input_size = (3, 32, 32))
```#결과#```
----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv2d-1 [-1, 8, 32, 32] 224
BatchNorm2d-2 [-1, 8, 32, 32] 16
ReLU-3 [-1, 8, 32, 32] 0
MaxPool2d-4 [-1, 8, 16, 16] 0
Conv2d-5 [-1, 16, 16, 16] 1,168
BatchNorm2d-6 [-1, 16, 16, 16] 32
ReLU-7 [-1, 16, 16, 16] 0
MaxPool2d-8 [-1, 16, 8, 8] 0
Linear-9 [-1, 64] 65,600
BatchNorm1d-10 [-1, 64] 128
ReLU-11 [-1, 64] 0
Linear-12 [-1, 32] 2,080
BatchNorm1d-13 [-1, 32] 64
ReLU-14 [-1, 32] 0
Linear-15 [-1, 10] 330
================================================================
Total params: 69,642
Trainable params: 69,642
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.01
Forward/backward pass size (MB): 0.31
Params size (MB): 0.27
Estimated Total Size (MB): 0.58
----------------------------------------------------------------
````````````
'파이토치' 카테고리의 다른 글
파이토치 합성곱 신경망(CNN) (2) (2) | 2024.12.06 |
---|---|
torch.nn (2) (0) | 2024.12.04 |
torch.nn (1) (0) | 2024.12.04 |