본문 바로가기
AI/딥러닝

[딥러닝] Neural Network

by snow_white 2022. 4. 26.
심층 신경망(Deep Neural Network, DNN)
심층 신경망(Deep Neural Network, DNN)은 입력층(input layer)과 출력층(output layer) 사이에 여러 개의 은닉층(hidden layer)들로 이뤄진 인공신경망(Artificial Neural Network, ANN)이다. 심층 신경망은 일반적인 인공신경망과 마찬가지로 복잡한 비선형 관계(non-linear relationship)들을 모델링할 수 있다.

예를 들어, 사물 식별 모델을 위한 심층 신경망 구조에서는 각 객체가 이미지 기본 요소들의 계층적 구성으로 표현될 수 있다. 이때, 추가 계층들은 점진적으로 모여진 하위 계층들의 특징들을 규합시킬 수 있다. 심층 신경망의 이러한 특징은, 비슷하게 수행된 인공신경망에 비해 더 적은 수의 유닛(unit, node)들 만으로도 복잡한 데이터를 모델링할 수 있게 해준다. 
이전의 심층 신경망들은 보통 앞먹임 신경망으로 설계되어 왔지만, 최근의 연구들은 심층 학습 구조들을 순환 신경망(Recurrent Neural Network, RNN)에 성공적으로 적용했다. 일례로 언어 모델링(language modeling) 분야에 심층 신경망 구조를 적용한 사례 등이 있다.

합성곱 신경망(Convolutional Neural Network, CNN)의 경우에는 컴퓨터 비전(computer vision) 분야에서 잘 적용되었을 뿐만 아니라, 각각의 성공적인 적용 사례에 대한 문서화 또한 잘 되어 있다. 더욱 최근에는 합성곱 신경망이 자동 음성인식 서비스(Automatic Response Service, ARS)를 위한 음향 모델링(acoustic modeling) 분야에 적용되었으며, 기존의 모델들 보다 더욱 성공적으로 적용되었다는 평가를 받고 있다.

 

Neuron

  • Structure of a neuron
  • Artificial NN ⇒ 생물학적 신경망에서 영감 받았음, 인간의 뇌 구조를 모방하려는 의도로 시작되었다.

 

다양한 종류의 심층 신경망 구조가 존재하지만, 대부분의 경우 대표적인 몇 가지 구조들에서 파생된 것이다. 그렇지만 여러 종류의 구조들의 성능을 동시에 비교하는 것이 항상 가능한 것은 아닌데, 그 이유는 특정 구조들의 경우 주어진 데이터 집합에 적합하도록 구현되지 않은 경우도 있기 때문이다.

 

가지 돌기로부터 들어온 자극이 cell body에서 자극에 대한 해석이 이루어지면

축삭 돌기(Axon)를 통해 다음 세포로 전달된다. 여기서 역치값 threshold 이상을 넘어야 자극이 전달된다.

하나의 뉴런의 출력이 또 다른 뉴런의 입력으로 들어감 (Hidden layer 원리)

입력된 값에 대한 해석은 사실상 두 번에 걸쳐 진행된다.

function1 : 각각의 값에 대해서 나름이 신념 부여하기 (=가중치를 곱하기)

function2 : 각각에 대한 중요도, 전체가 가지고 있는 공통의 신념

x1 ⇒ W1*x1 + b

x2 = W2*x2 + b

x3 = W3*x3 + b

 

  • 활성화 함수 activation function인간에게는 sigmoid
  • 딥러닝에서는 Relu
  • 일정한 값 이상만을 다음 뉴런으로 전달해 줌.

이미지넷 대회에서 얀 루큰이 CNN으로 10%대로 성능 높였는데 이 때 Relu도 함께 사용됨

  • 딥러닝에서는 activation 함수로 sigmoid Relu 많이 쓸 수 있음
  • Relu 함수의 파형 : 0 아니면 양수(무한대까지 가능)를 가짐, x가 0보다 작으면 전부 0, x가 0보다 크면 x값은 발산함
  • tanh(sigmoid는 위아래로 늘렸을 때), Leanky ReLU(ReLU에서 x축이 음수)

Q. Deep에서 Activation 함수 쓰는 이유?

A. 미미한 값으로는 출력할 수 없기 때문에 어느 정도

중간 출력층은 또 다른 레이어의 입력이 된다.

f(X) = Wx + b

첫 번째 출력 값 W1x1+b1

두 번째 출력 값 W2( W1x1+b1) + b2

세 번째 출력 값 W3( W2( W1x1+b1) + b2) + b3

...

선형 함수 하나를 여러 개 쌓으면 거대한 선형 함수를 처리해야 하는 것과 같음...

선 선형함수만 이용해서 block(층)을 쌓게 되면 선형+선형+선형+ .. 

⇒ Layer를 깊이 쌓는 의미를 : “Deep” 잃게 됨.

⇒ 복잡한 모델일 때 이렇게 설계를 복잡하게 함.

모델의 복잡도가 높아서 등장한 것이 activation function

 

DataLoader_CIFAR10 실습

import torch
import torchvision
import torch.nn  as nn
import numpy as np
import torchvision.transforms as transforms
import matplotlib.pyplot as plt

# CIFAR10 Dataset Loading & Show Image
# 이미지 처리, train 데이터를 가져와라
train_dataset = torchvision.datasets.CIFAR10(root='../../data',
                             train=True,
                             transform=transforms.ToTensor(),
                             download=True
                             )

print (train_dataset[0]) # 5만 개 이미지 중에서 첫 번째 이미지를 출력
# scaling 하지 않아도 위의 셀 속성 중 ToTenser() 함수의 첫 번째 역할: scale 알아서  255로 나눠서 Normalization 역할을 해 줌
# 라벨은 0~9까지 10개 있는데 아래 6출력된 것은 라벨 중 7번째 이미지를 의미함
'''
(tensor([[[0.2314, 0.1686, 0.1961,  ..., 0.6196, 0.5961, 0.5804],
         ...,
         [0.6941, 0.6588, 0.7020,  ..., 0.8471, 0.5922, 0.4824]],

        [[0.2431, 0.1804, 0.1882,  ..., 0.5176, 0.4902, 0.4863],
         ...,
         [0.5647, 0.5059, 0.5569,  ..., 0.7216, 0.4627, 0.3608]],

        [[0.2471, 0.1765, 0.1686,  ..., 0.4235, 0.4000, 0.4039]
         ...,
         [0.4549, 0.3686, 0.3412,  ..., 0.5490, 0.3294, 0.2824]]]), 6)
'''

image, label = train_dataset[0]
print('Image', image)
print('label', label)
'''
Image tensor([[[0.2314, 0.1686, 0.1961,  ..., 0.6196, 0.5961, 0.5804],
         ...,
         [0.6941, 0.6588, 0.7020,  ..., 0.8471, 0.5922, 0.4824]],

        [[0.2431, 0.1804, 0.1882,  ..., 0.5176, 0.4902, 0.4863]
         ...,
         [0.5647, 0.5059, 0.5569,  ..., 0.7216, 0.4627, 0.3608]],

        [[0.2471, 0.1765, 0.1686,  ..., 0.4235, 0.4000, 0.4039],
         ...,
         [0.4549, 0.3686, 0.3412,  ..., 0.5490, 0.3294, 0.2824]]])
label 6
'''

print('image size', image.size())
print('image.shpae', image.shape)
'''
image size torch.Size([3, 32, 32])
image.shpae torch.Size([3, 32, 32])
color(channel)이 앞으로 나왔다! ToTensor()의 두 번째 역할! channel을 앞으로 보냄
numpy => tensor로 변환

데이터 로드해서 물리적인 장소로 다운로드하는 순간 ToTensor 적용함

이미지를 학습시킬 때 size와 shape은 동일해야 한다.
'''

# numpy로 변환
image = image.numpy()
image
'''
array([[[0.23137255, 0.16862746, 0.19607843, ..., 0.61960787,
         0.59607846, 0.5803922 ],
        [0.0627451 , 0.        , 0.07058824, ..., 0.48235294,
         0.46666667, 0.47843137],
        [0.09803922, 0.0627451 , 0.19215687, ..., 0.4627451 ,
         0.47058824, 0.42745098],
        ...,
        [0.8156863 , 0.7882353 , 0.7764706 , ..., 0.627451  ,
         0.21960784, 0.20784314],
        [0.7058824 , 0.6784314 , 0.7294118 , ..., 0.72156864,
         0.38039216, 0.3254902 ],
        [0.69411767, 0.65882355, 0.7019608 , ..., 0.84705883,
         0.5921569 , 0.48235294]],

       [[0.24313726, 0.18039216, 0.1882353 , ..., 0.5176471 ,
         0.49019608, 0.4862745 ],
        [0.07843138, 0.        , 0.03137255, ..., 0.34509805,
         0.3254902 , 0.34117648],
        [0.09411765, 0.02745098, 0.10588235, ..., 0.32941177,
         0.32941177, 0.28627452],
        ...,
        [0.6666667 , 0.6       , 0.6313726 , ..., 0.52156866,
         0.12156863, 0.13333334],
        [0.54509807, 0.48235294, 0.5647059 , ..., 0.5803922 ,
         0.24313726, 0.20784314],
        [0.5647059 , 0.5058824 , 0.5568628 , ..., 0.72156864,
         0.4627451 , 0.36078432]],

       [[0.24705882, 0.1764706 , 0.16862746, ..., 0.42352942,
         0.4       , 0.40392157],
        [0.07843138, 0.        , 0.        , ..., 0.21568628,
         0.19607843, 0.22352941],
        [0.08235294, 0.        , 0.03137255, ..., 0.19607843,
         0.19607843, 0.16470589],
        ...,
        [0.3764706 , 0.13333334, 0.10196079, ..., 0.27450982,
         0.02745098, 0.07843138],
        [0.3764706 , 0.16470589, 0.11764706, ..., 0.36862746,
         0.13333334, 0.13333334],
        [0.45490196, 0.36862746, 0.34117648, ..., 0.54901963,
         0.32941177, 0.28235295]]], dtype=float32)
'''

 

 

import numpy as np
image = np.moveaxis(image, 0, -1) # 맨 앞에 있는 것을 맨 뒤로 보내라.

print(image.shape) # (32, 32, 3)

plt.imshow(image) # 이미지를 그릴 땐 show 아니고 imshow

댓글