1 설치

conda install pytorch torchvision cpuonly -c pytorch

2 기본 연산

2.1 행렬

수식

\begin{bmatrix}
1 & 2 & 3 \\
4 & 5 & 6 \\
\end{bmatrix}

\[ \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ \end{bmatrix} \]

코드

import torch

# torch.ones((2,3), dtype=torch.int8)
# torch.rand((2,3))

torch.tensor([[1, 2 ,3], [4, 5, 6]])
tensor([[1, 2, 3],
        [4, 5, 6]])

2.2 gradient

수식

y = 2 \times x+3

\[ y = 2 \times x + 3 \] 미분 결과

\[ \frac{\partial y}{\partial x} = 2 \]

코드

x = torch.tensor([[1., 2., 3.],
                  [4., 5., 6.]], requires_grad=True)

y = 2 * x + 3
print(y)
tensor([[ 5.,  7.,  9.],
        [11., 13., 15.]], grad_fn=<AddBackward0>)

2.3 형태 변환

수식

\begin{bmatrix}
1 \\
2 \\
3 \\
4
\end{bmatrix}

\to 

\begin{bmatrix}
1 & 2 \\
3 & 4 \\
\end{bmatrix}

\[ \begin{bmatrix} 1 \\ 2 \\ 3 \\ 4 \end{bmatrix} \to \begin{bmatrix} 1 & 2 \\ 3 & 4 \\ \end{bmatrix} \]

코드

a = torch.tensor([1., 2., 3., 4.])

torch.reshape(a, (2, 2))
# a.view((2, 2))
tensor([[1., 2.],
        [3., 4.]])

3 헬로월드

3.1 패션 MNIST 데이터셋

패션 이미지

\(y\) 라벨

라벨 라벨 명칭 라벨 라벨 명칭
0 T-shirt/top 5 Sandal
1 Trouser 6 Shirt
2 Pullover 7 Sneaker
3 Dress 8 Bag
4 Coat 9 Ankle boot

3.2 환경설정과 데이터셋

import torch
from torch import nn
from torchvision import datasets, transforms
import torchvision.models as models

transform = transforms.Compose([transforms.ToTensor(),
                              transforms.Normalize((0.5,), (0.5,)),
                              ])
batch_size = 64

## 훈련 데이터 다운로드
trainset = datasets.FashionMNIST('data/', download=False, train=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=False)

## 시험 데이터 다운로드
testset = datasets.FashionMNIST('data/', download=False, train=False, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False)

3.3 신경망 아키텍처

## 아키텍처 정의

class FashionNetwork(nn.Module):
  
    def __init__(self):
        super().__init__()
        self.hidden1 = nn.Linear(784, 256)
        self.hidden2 = nn.Linear(256, 128)
        self.output = nn.Linear(128, 10)
        self.log_softmax = nn.LogSoftmax()
        self.activation = nn.ReLU()
        self.drop = nn.Dropout(p=0.25)
        
    def forward(self, x):
        x = self.hidden1(x)
        x = self.activation(x)
        x = self.drop(x)
        x = self.hidden2(x)
        x = self.activation(x)
        x = self.drop(x)
        x = self.output(x)
        output = self.log_softmax(x)
        
        return output
      
model = FashionNetwork().to('cuda')

print(model)
FashionNetwork(
  (hidden1): Linear(in_features=784, out_features=256, bias=True)
  (hidden2): Linear(in_features=256, out_features=128, bias=True)
  (output): Linear(in_features=128, out_features=10, bias=True)
  (log_softmax): LogSoftmax(dim=None)
  (activation): ReLU()
  (drop): Dropout(p=0.25, inplace=False)
)

3.4 훈련

from torch import optim

# 오차함수와 최적화 관련 패러미터 설정
criterion =  nn.NLLLoss()
optimizer = optim.Adam(model.parameters(), lr = 0.005)

# 신경망 학습
epochs = 10
losses = []

torch.cuda.is_available()
torch.cuda.current_device()
torch.cuda.get_device_name(0)
torch.cuda.device(0)

device = torch.device(str("cuda:0") if torch.cuda.is_available() else "cpu")

model = model.to('cuda:0')

for _ in range(epochs):
    running_loss = 0
    for image, label in trainloader:
        optimizer.zero_grad()
        image = image.view(image.shape[0],-1).to('cuda')
        pred = model(image)           # 앞서 정의한 모형을 학습
        loss = criterion(pred, label.to('cuda')) # 오차 계산
        loss.backward()               # 역전파
        optimizer.step()              # 스텝
        running_loss += loss.item()   # 오차값을 총 오차에 더함
    else:
        print(f'Training loss: {running_loss/len(trainloader):.4f}')
        losses.append(running_loss/len(trainloader))
        
# Training loss: 0.5576
# Training loss: 0.4172
# Training loss: 0.3854
# Training loss: 0.3652
# Training loss: 0.3495
# Training loss: 0.3365
# Training loss: 0.3280
# Training loss: 0.3180
# Training loss: 0.3094
# Training loss: 0.3015

3.5 모형 저장

## 딥러닝 모형 저장   
torch.save(model.state_dict(), "data/fashion.pth")

# 리스트 학습 손실값 저장
# import json
# with open("data/fashion_mnist_losses.json", "w") as fp:
#    json.dump(losses, fp)

3.6 평가

import torch
from torch import nn
from torchvision import datasets, transforms
import json
   
## 예측모형 불러오기
model =  FashionNetwork()
model.load_state_dict(torch.load('data/fashion.pth'), strict=False)
_IncompatibleKeys(missing_keys=['hidden1.weight', 'hidden1.bias', 'hidden2.weight', 'hidden2.bias', 'output.weight', 'output.bias'], unexpected_keys=['fc1.weight', 'fc1.bias', 'fc2.weight', 'fc2.bias', 'fc3.weight', 'fc3.bias', 'fc4.weight', 'fc4.bias'])
model.eval()

# 테스트 데이터에서 첫 이미지 추출
FashionNetwork(
  (hidden1): Linear(in_features=784, out_features=256, bias=True)
  (hidden2): Linear(in_features=256, out_features=128, bias=True)
  (output): Linear(in_features=128, out_features=10, bias=True)
  (log_softmax): LogSoftmax(dim=None)
  (activation): ReLU()
  (drop): Dropout(p=0.25, inplace=False)
)
testimgs, testlabels = iter(testloader).next()
img = testimgs[0].view(1, 784)

with torch.no_grad():
    logps = model(img)
<string>:20: UserWarning: Implicit dimension choice for log_softmax has been deprecated. Change the call to include dim=X as an argument.
ps = torch.exp(logps)
probabilities = list(ps.numpy()[0])
prediction = probabilities.index(max(probabilities))
# print(prediction)

def mnist_label(label):
    output_mapping = {
      0: "T-shirt/Top",
      1: "Trouser",
      2: "Pullover",
      3: "Dress",
      4: "Coat",
      5: "Sandal",
      6: "Shirt",
      7: "Sneaker",
      8: "Bag",
      9: "Ankle Boot"
    }
    label = (label.item() if type(label) == torch.Tensor else label)
    return output_mapping[label]

mnist_label(prediction) 
'Shirt'
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'

import matplotlib.pyplot as plt

plt.imshow(testimgs[0][0].numpy().squeeze(), cmap='gray_r');
plt.show()