ABOUT ME

-

  • [Pytorch] 간단한 신경망 구현
    딥러닝 2020. 3. 16. 00:13

    Pytorch 공식 튜토리얼 중 신경망 관련 내용에 대한 저의 코드입니다.

    Medium https://medium.com/dair-ai/a-simple-neural-network-from-scratch-with-pytorch-and-google-colab-c7f3830618e0 예제에서는 직접 설정한 도함수를 이용해 BackPropagation을 실행하지만 저는 Pytorch의 backwatd 함수를 사용하였습니다.

     

    본 예제에서 만드는 딥러닝 모델은 다음과 같은 간단한 모델입니다.

    모델 구조

    보시는 바와 같이 1개의 Hidden Layer로 구성된 매우 간단한 신경망입니다.

    본 예제에서는 1x2 크기의 벡터를 입력으로 하고 1x1 텐서 (스칼라)를 출력으로 합니다.

     

    먼저 학습 데이터입니다. X 텐서에 학습 데이터와 각각에 대응되는 결과값을 y 텐서에 넣었습니다. xPredicted는 실행시키고자 하는 데이터입니다.

    X = torch.tensor(([7, 1], [5, 2], [6, 4], [7, 6], [8, 9]), dtype=torch.float)
    y = torch.tensor(([23], [40], [60], [62], [90]), dtype=torch.float)
    xPredicted = torch.tensor(([5, 5]), dtype=torch.float)

    다음으로는 X텐서와 y텐서에 값들을 스케일링하겠습니다.

    X_max, _ = torch.max(X, 0)
    xPredicted_max, _ = torch.max(xPredicted, 0)
    
    X = torch.div(X, X_max)
    xPredicted = torch.div(xPredicted, xPredicted_max)
    y = torch.div(y, torch.tensor(([100]), dtype=torch.float))

    y의 경우는 최대를 100으로 설정하였습니다.

     

    다음으로는 핵심인 신경망입니다.

    import torch.nn as nn
    
    class NeuralNetwork(nn.Module):
        def __init__(self, ):
            self.inputSize = 2
            self.outputSize = 1
            self.hiddenSize = 3
            
            self.w1 = torch.randn(self.inputSize, self.hiddenSize, requires_grad=True)
            self.w2 = torch.randn(self.hiddenSize, self.outputSize, requires_grad=True)
            
            self.learning_rate = 0.001
            
        def forward(self, X):
            self.z1 = torch.matmul(X, self.w1)
            self.z2 = torch.sigmoid(self.z1)
            self.z3 = torch.matmul(self.z2, self.w2)
            out = torch.sigmoid(self.z3)
            return out
            
        def train(self, X, y):
            out = self.forward(X)
            error = ((y-out)**2).mean()
            error.backward()
            self.w1.data += self.learning_rate*(self.w1).grad
            self.w2.data += self.learning_rate*(self.w2).grad
            
        def saveWeights(self, model):
            torch.save(model, "NerualNetwork")
        
        def predict(self):
            print("Input Data: ", str(xPredicted))
            print("Predicted: ", str(self.forward(xPredicted)))

    Pytorch의 nn 을 사용하여 구현하였으며 hidden layer는 한 개이므로 두 개의 weight을 사용하였습니다.

    이때 학습 과정에서는 단순화를 위해 bias는 사용하지 않았으며 각각의 wieght를 조정하여 학습하기 위해 requires_grad=True으로 설정하였습니다. train 과정에서는 에러를 계산하고 이 에러를 편미분 하여 각각의 weight에 대한 변화율을 계산합니다. 이때 self.w1.data와 같이 설정한 것은 self.w1으로 설정할 경우 runtime error가 나기 때문입니다. 이는 leaf variable을 replace 할 경우 생기는 문제입니다. 

     

    결과를 확인하기 위한 과정은 다음과 같습니다.

    NN = NeuralNetwork()
    trainIdx = 1000
    for idx in range(trainIdx):
        if idx%100==0:
            print("#"+str(idx)+" Loss: "+str(torch.mean((y-NN.forward(X))**2).detach().item()))
        NN.train(X, y)
        
    NN.saveWeights(NN)
    NN.predict()
    #0 Loss: 0.07525341957807541
    #100 Loss: 0.08975683152675629
    #200 Loss: 0.15257836878299713
    #300 Loss: 0.2301979959011078
    #400 Loss: 0.2512035667896271
    #500 Loss: 0.25329679250717163
    #600 Loss: 0.25344881415367126
    #700 Loss: 0.2534591853618622
    #800 Loss: 0.25345999002456665
    #900 Loss: 0.25345999002456665
    Input Data:  tensor([1., 1.])
    Predicted:  tensor([1.], grad_fn=<SigmoidBackward>)

    원하는 결과를 얻은 것을 볼 수 있습니다.

    '딥러닝' 카테고리의 다른 글

    [Pytorch] EMNIST CNN  (0) 2020.04.03
    [Pytorch] MNIST CNN  (0) 2020.03.31
    [Pytorch] MNIST 신경망 구현  (0) 2020.03.28
Designed by Tistory.