본문 바로가기
  • 문과생의 백엔드 개발자 성장기
|Playdata_study/AI

210813_DeepLearning(Neural Net)

by 케리's 2021. 8. 16.

Neural Net 

 

  • FCN (Fully Connected Network)
  • FCN, CNN, RNN, ANN, DNN 등 모든 것을 지칭하는 의미

 

 

 

Epoch

Dataset - 6만개가 있다고 가정하자

train - 5만개

  ex) 문제집 5만권

validation - 1만개

  ex) 모의고사 1만개

 → 1 Epoch 이라 한다. 

 

기본적으로 100 Epoch 정도 돌림

Epoch을 돌릴때 마다 Transforms (변형) 을 진행한다.

   ex) 변형된 문제집, 변형된 모의고사

 

 

 

Training 

1) Forward

2) Backward 

 ※ L · R(W) :: Weight, bias 재분배가 일어남

  

 

 


실습

 

01_Deep_NN

 

1  Pytorch 에서의 Gradient Descent

 

 

머신러닝에서 선형회귀(Linear Regression)에 대해서 간단히 살펴보았다.
이번에는 파이토치 라이브러리를 이용해서 선형회귀 연산 그래프를 만들고

경사하강법을 이해하는 간단한 코드를 살펴보겠다.

 

파이토치는 데이터의 기본 단위로 텐서(Tensor)를 사용한다.
Numpy의 np.array()와 동일하다.

텐서를 생성하는 방법에는 여러 가지가 있지만 가장 단순한 방법으로 torch.Tensor()를 이용한다.

 

import torch  # 파이토치 프레임워크 불러오기 .. 파이토치는 전신이 torch라 그냥 torch로 import 한다.
import torchvision  # 파이토치 내에서 vision이 붙으면 .. Image Processing에 특화된 라이브러리
import torch.nn as nn  # nn은 Neural Net의 약자
import numpy as np
import torchvision.transforms as tf  # 데이터 변형에 특화된 라이브러리 .. Augmentation
X = torch.Tensor(2, 3)  # 2행 3열의 배열을 하나 생성하고 이게 입력데이터가 된다.
X.shape  # shape = Size() 동일
# --- 결과

torch.Size([2, 3])

 

X  # 값이 랜덤하게 초기화 되어서 들어가있다.
# --- 결과

tensor([[2.0826e-18, 3.0840e-41, 3.3631e-44],
        [0.0000e+00,        nan, 1.5002e+00]])

 

 

# 랜덤이 맘에 안든다면?
X = torch.Tensor([[1, 2, 3], [4, 5, 6]])  # Tensor를 생성과 동시에 직접 초기화, 기본 타입은 float?
X
# ---- 결과

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

 

 

'''
tensor() 함수 인자값으로는 
device :: gpu or cpu
requires_grad :: 텐서에 기울기를 적용할지 여부
data 
type 
옵션들이 있다.
'''

x = torch.tensor(data=[2.0, 3.0], requires_grad=True)
x
# x = torch.tensor(data=[2.0, 3.0])  # 이렇게 하면 미분(기울기) 불가능이라 밑에서 에러 발생
# ---- 결과

tensor([2., 3.], requires_grad=True)

 

# y 는 label

y = x ** 2
y
# --- 결과

tensor([4., 9.], grad_fn=<PowBackward0>)

 

# 예측 값 지정 (그냥 만든 것)
pred = 2*y + 3
pred
# --- 결과

tensor([11., 21.], grad_fn=<AddBackward0>)

 

print(type(x))
print(type(y))
print(type(pred))
# --- 결과

<class 'torch.Tensor'>
<class 'torch.Tensor'>
<class 'torch.Tensor'>

 

 

target = torch.tensor([3.0, 4.0])
# target = 3, 4

loss = torch.sum(torch.abs(pred - target))  # (11 - 3) + (21 - 4) = 25
print(loss)
# ---- 결과

tensor(25., grad_fn=<SumBackward0>)

 

'''
Forward 라인이 끝났다
X --> 학습 --> pred --> loss 값 출력

Backward 라인이 시작된다.
loss.Backward를 적용한다.
'''

loss.backward()  # backward() 가 학습 주체 (Weight, Bias) 에 대해서 편미분이 진행된다.
'''
loss.backward()
pred 값은 미분 대상이 아니다.
None이 출력됨
'''
print(x.grad)
print(x)
# --- 결과

tensor([ 8., 12.])
tensor([2., 3.], requires_grad=True)

 

2. Create Tensor ... Neural Net Generator

 

# 입력과 출력값은 이미 고정되어 있다.
x = torch.randn(10, 3)
y = torch.randn(10, 2)
print(x)
print(y)
# ---- 결과

tensor([[-2.0738,  0.1991, -0.4047],
        [-0.7272,  1.1994,  1.5542],
        [ 1.7119,  0.7119, -0.6963],
        [ 0.7168, -1.0973,  1.2486],
        [ 0.4916, -1.0283, -1.4124],
        [ 0.7931, -0.8263, -0.6042],
        [ 0.5859, -0.9777, -0.6152],
        [ 0.2093, -0.0577, -0.5777],
        [ 0.2347,  0.0727, -1.3990],
        [ 0.4495, -1.3137,  1.0553]])
tensor([[-1.5187, -0.7408],
        [-0.0302,  0.7349],
        [-1.4959, -1.4495],
        [ 1.0217,  0.2111],
        [-0.3096,  0.7867],
        [-0.7791,  0.7946],
        [ 0.6554,  0.5776],
        [ 0.3018, -0.3834],
        [ 2.6601, -0.9998],
        [-1.0621,  1.7214]])

 

# 모델을 하나 생성
linear = nn.Linear(3, 2)
print('weight : ', linear.weight )  # 3x2 가 나와야 하는데 2x3으로 출력된다. Trans 되서 나옴
print('bias : ', linear.bias)  # y랑 같은 크기의 행렬이 나와야 되는데 열만 같게 나온다. 행은 늘려도 어차피 같은 값이라 그런 듯
# 결과


weight :  Parameter containing:
tensor([[ 0.5764, -0.3438, -0.1881],
        [-0.4396, -0.4574,  0.2270]], requires_grad=True)
bias :  Parameter containing:
tensor([ 0.1561, -0.0850], requires_grad=True)

 

 

# 모델의 학습주체? Weight, Bias
# BIas를 확인할 수 있는 함수 ★ 모델.parameters() ★
print(linear.parameters())  # 객체를 출력해준다. 학습주체를 해킹하는 함수 -> 이 안에 Weight와 Bias가 들어있다.

# 선으로 정의해두고 써야하는 것 1. Loss Function이 여러 개가 있는데 무엇을 쓸지 2. Optimization 뭐 쓸지
loss_func = nn.MSELoss()
optimizer = torch.optim.SGD(linear.parameters(), lr=0.01)  # 학습주체와 learning_rate

pred = linear (x) # 생성한 NN모델에 입력값을 넣으면 학습된 결과로 예측값(rped)를 내뱉는다.

loss = loss_func(pred, y) # 예측, 정답
print('loss... befor step BackPropagation :: ', loss.item())
# --- 결과

<generator object Module.parameters at 0x7fd4ce1d71d0> # 객체, 학습구조를 해킹하는 함수 

loss... befor step BackPropagation ::  1.1944406032562256

 

loss.backward() # 위 x, y 값에 편미분을 적용해 책임을 물었음?!

print('dL/dw' , linear.weight.grad)
print('dL/db' , linear.bias.grad)
# --- 결과

dL/dw tensor([[ 0.7699, -0.5754, -0.1327],
        [-0.6206, -0.1040, -0.1354]])
dL/db tensor([-0.2020, -0.4098])

 

 

# 실질적인 하강 , 위에서 얻어낸 값으로 step()

optimizer.step() # 수정된 값으로 하강을 한다.
# 반복효과 
pred = linear(x)
loss = loss_func(pred, y)
print('loss ... after step BackPropagation :: ', loss.item())
# ---- 결과
# 위의 값보다 낮아진 것을 확인 할 수 있음

loss ... after step BackPropagation 1.1780799627304077

 

👉 위 Code 정리

 

  • Linear = nn.Linear(x, y) # 최초 입력값 x, y 
  • loss_function = nn.MSELoss() # 어떤 loss/optimization 모델을 사용할 것인지 미리 정의 (선 정의)

      * MSELoss() 알고리즘 ? 정답 - 예측값 또는 예측값 - target 을 제곱해주는 알고리즘 (값이 0에 가까울 수록 좋음)

  • optimizer = torch.optim.SGD(linear.parameters(), lr=0.1) 

     * linear.parameters() : 학습주체 (weight, bias)를 해킹하는 함수 ,

     * 객체(안에 들어있는 값이 하강할 때 수정되는 값 = w, b)가 리턴된다.

     * SGD 종류는 여러가지이다 (ex, Adam, 즉 optimization 의 종류)

 

<PipeLine>

    input → Neural Net  → output  → loss

  • pred = linear(x)
  • loss = loss_func(pred,y)
  • loss.backward()  # 실질적인 계산이 이루어짐
  • optimizer.step() # step () → 하강

 

 

 

 


 

 

02_Deep_NN

 

댓글