본문 바로가기
Minding's Reading/밑바닥부터 시작하는 딥러닝

[밑바닥부터 시작하는 딥러닝] CH.3 신경망

by Minding 2021. 3. 15.
728x90
반응형

밑딥 데이터셋 다운로드 : github.com/WegraLee/deep-learning-from-scratch

 

WegraLee/deep-learning-from-scratch

『밑바닥부터 시작하는 딥러닝』(한빛미디어, 2017). Contribute to WegraLee/deep-learning-from-scratch development by creating an account on GitHub.

github.com


앞 장에서 배운 퍼셉트론으로 복잡한 함수도 표현가능

신경망의 성질 : 가중치 매개변수의 적절한 값을 데이터로부터 자동으로 학습하는 능력

 

3.1 퍼셉트론에서 신경망으로

3.1.1 신경망의 예

신경망의 구조 예시

가장 왼쪽 줄을 입력층, 맨 오른쪽 줄 출력층, 중간 층을 은닉층이라고 함

 

* 해당 책에서는 위의 신경망 구조를 '2층 신경망이라고 표현'

가중치를 갖는 층이 두 개이기 때문 / 문헌에 따라서는 같은 구조를 '3층 신경망'이라고도 표현

 

3.1.3 활성화 함수의 등장

활성화 함수 - 입력 신호의 총합이 활성화를 일으키는 지 정하는 역할, 입력을 출력으로 변환

a = 입력총합 / h() = 활성화 함수 / y = 출력값

활성화 함수의 처리과정

* 일반적으로 단층 퍼셉트론은 단층 네트워크에서 계단 함수 사용한 모델을 가리키고,

다층 퍼셉트론은 신경망(여러 층으로 구성되고 시그모이드 함수 등의 매끈한 활성화 함수사용)을 가리킴

 

 

3.2 활성화 함수

계단 함수 - 임계값을 경계로 출력이 바뀌는 함수

퍼셉트론에서는 활성화 함수로 계단 함수를 이용한다고 할 수 있음

 

3.2.1 시그모이드 함수 (sigmoid function)

시그모이드 함수를 나타낸 식

exp(-x)는 e^-x를 뜻하며, e는 자연상수로 2.7182...의 값을 갖는 실수

다른 함수와 마찬가지로 입력을 주면 출력을 돌려주는 변환기 역할

 

*계단함수 및 시그모이드함수 구현 생략

 

*시그모이드 함수

exp = exponentially(기하급수적으로)

x의 값이 커질수록 1보다 아주 작은값만큼의 큰 값이 분모의 값이 됨 (0.999....같은)

즉, 전체 값이 1에 가까워짐 /  반대의 경우도 마찬가지로 전체 값이 0에 가까워짐

이런 점을 활용한 함수가 sigmoid() 함수

 

3.2.5 시그모이드 함수와 계단 함수 비교

시그모이드 함수와 계단 함수 그래프비교

- 가장 큰 차이는 '매끄러움'의 차이

- 계단 함수는 0과 1만 반환하는 반면, 시그모이드 함수는 실수를 반환

 

- 공통점으로는 입력이 중요하면 큰 값, 중요하지 않으면 작은 값 출력

- 출력이 0에서 1 사이

 

3.2.6 비선형 함수

선형 함수 - 이 변환기에 무언가 입력했을 대 출력이 입력의 상수배만큼 변하는 함수 (f(x) = ax + b)

                x와 y의 관계가 선형결합[각주:1]으로 표현되는 관계

비선형 함수 - 직선 1개로는 그릴 수 없는 함수

 

신경망에서는 활성화 함수로 비선형 함수를 사용해야함

- 선형함수를 이용하면 신경망의 층을 깊게하는 의미가 없어지기 때문

 

선형함수의 문제는 층을 아무리 깊게해도 '은닉층이 없는 네트워크'로도 똑같은 기능을 할 수 있다는 것

 

3.2.7 ReLU 함수

ReLU 함수

- 입력이 0을 넘으면 그대로, 0 이하면 0을 출력하는 함수

- numpy로 구현시, maximum함수 사용하면 구현 가능

 

3.3 다차원 배열의 계산

숫자가 N차원으로 나열하는 것을 통틀어 다차원 배열이라고 함.

가로방향을 행(row)이라고 하며, 세로방향을 열(column)이라고 함.

1차원 배열일때도 shape은 tuple형태로 반환 ( (,10)과 같은 형태)

#2차원 배열 만들기
B = np.array([[1,2,3], [4,5,6], [7,8,9]])

 

3.3.2 행렬의 곱

왼쪽 행렬의 행(가로)과 오른쪽 행렬의 열(세로)을 원소별로 곱

numpy의 dot함수 이용하면 쉽게 곱셈가능

행렬의 곱 / numpy 구현

 

행렬의 곱에서 주의해야 할 점

- 행렬의 형상(shape)에 주의 해야 함

- 대응하는 차원의 원소 수를 일치시켜야 함 (그렇지 않으면 오류 출력)

- 서로 차원이 다를 때에도 원칙은 똑같이 적용됨

행렬 곱 주의할 점

 

3.3.3 신경망에서의 행렬 곱

편향과 활성화 함수를 생략한 신경망

신경망에서의 행렬 곱

X, W, Y의 형상을 주의해서 보기 (대응하는 차원의 원소 수가 같아야함!)

 

3.4 3층 신경망 구현하기

3층 신경망의 구조

3.4.2 각 층의 신호 전달 구현하기

입력층에서 1층으로 신호 전달

- 편향을 뜻하는 뉴런인 (1)이 추가

- 가중치를 곱한 신호 두 개와 편향을 합친 수식 도출 가능

- numpy를 사용해서 구현하기

X = np.array([1.0, 0.5)]
W1 = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
B1 = np.array([0.1, 0.2, 0.3])

print(W1.shape) # (2,3)
print(X.shape) # (2, )
print(B1.shape) # (3, )

A1 = np.dot(X, W1) + B1

 

1층의 활성화 함수에서의 처리

입력층에서 1층으로의 신호전달 - 활성화 함수 처리

가중치 합을 a로 표기, 활성화 함수 h()로 변환된 신호를 z로 표기

z가 같은 과정 거쳐 2층으로 전달됨

 

3.4.3 구현 정리

numpy로 구현한 3층 신경망
numpy로 구현한 3층신경망 - 결과값

 

3.5 출력층 설계하기

머신러닝(기계학습) 문제는 크게 분류와 회귀로 나뉨

일반적으로 회귀 문제의 경우 항등 함수, 분류에는 소프트맥스 함수 사용

항등함수는 입력을 그대로 출력

항등함수 그림(왼쪽)과 소프트맥스함수 수식 및 그림(오른쪽)

소프트맥스 함수의 분자는 입력신호의 지수함수, 분모는 모든 입력신호의 지수 함수의 합으로 구성

소프트맥스는 출력노드가 모든 입력노드의 영향을 받음

 

3.5.2 소프트맥스 함수 구현 시 주의점

softmax()는 오버플로 문제가 있음 - 너무 큰 값을 출력하여 표현할 수 없는 문제

softmax의 지수함수 계산 시 어떤 정수를 더하거나 빼도 결과는 바뀌지 않음

이를 이용하여 분자, 분모 각각에 정수를 더하여 문제 해결

정수 (C')는 보통 maximum값 이용

소프트맥스 함수 구현시 주의점 - 오버플로 문제 해결

 

3.5.3 소프트맥스 함수의 특징

a = np.array([0.3, 2.9, 4.0])
y = softmax(a)
print(y)
>>> [0.1821127, 0.24519181, 0.73659691]
np.sum(y)
>>> 1.0

소프트맥스 함수의 출력은 0에서 1.0 사이의 실수

또한, 출력 총합이 1

이 성질로 인해 소프트맥스 함수의 출력을 '확률'로 해석가능

 

소프트맥스 적용해도 각 원소의 대소관계는 변하지 않음 (지수함수가 단조증가함수이므로)

결과적으로 소프트맥스 함수는 생략 가능함 (추론단계에서)

신경망 학습 시에는 출력층에서 소프트맥스 함수 사용함.

 

3.5.4 출력층의 뉴런 수 정하기

출력층의 뉴런 수는 풀려는 문제에 맞게 적절히 정해야 함

분류에서는 분류하고 싶은 클래스 수로 설정하는 것이 일반적

 

3.6 손글씨 숫자 인식

이미 학습된 매개변수 사용하여 추론과정만 구현 - 신경망의 순전파(forward propagation)

import sys, os
sys.path.append(os.pardir)
from dataset.mnist import load_mnist

(x_train, t_train), (x_test, t_test) = \
  load_mnist(flatten=True, normalize=False)

load_mnist함수의 파라미터

- normalize: 입력 이미지의 픽셀값을 0.0~1.0 사이의 값으로 정규화할지
- flatten: 입력 이미지를 1차원 배열로 만들지
- one-hot-label: 원-핫 인코딩 형태로 저장할지

 

3.6.2 신경망의 추론 처리

- 입력층 뉴런 : 784개 (이미지크기가 28*28=784이기 때문)

- 출력층 뉴런 : 10개 (0 ~ 9까지, 클래스 수가 10개이기 때문)

- 은닉층 뉴런 : 각 50개 / 100개 (임의로 정한 값)

def get_data():
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
    return x_test, t_test

def init_network():
    #가중치와 편향 매개변수가 딕셔너리 변수로 저장되어 있음
    with open("sample_weight.pkl", 'rb') as f:
        network = pickle.load(f)

    return network
    
def predict(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']

    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = softmax(a3)

    return y
x, t = get_data()
network = init_network()

accuracy_cnt = 0
for i in range(len(x)):
    y = predict(network, x[i]) # 확률 배열로 반환
    p = np.argmax(y) #배열에서 확률이 가장 높은 원소
    if p == t[i]:
        accuracy_cnt += 1

print("Accuracy: "+str(float(accuracy_cnt) / len(x))) # 정확도 파악

정확도를 통해 올바르게 분류한 비율 알아보기

 

* 데이터 전처리 (pre-processing)

위의 예시에서는 normalize = True설정

0 ~ 255 범위인 각 픽셀의 값을 0.0~1.0 범위로 변환 (정규화)

PCA 변환 뒤 분산을 1로 조정 (백색화, whitening)

 

3.6.3 배치 처리

배치처리 - 이미지 여러 개를 한꺼번에 묶어 넘기는 것

배치(batch) - 하나로 묶은 입력 데이터

배치처리를 위한 배열들의 형상 추이

* 배치처리를 할 때에도 원소별 수를 맞춰주어야 한다

 

이미지 100장을 한꺼번에 입력하는 경우 구현

x, t = get_data()
network = init_network()

batch_size = 100 #배치 크기 = 100
accuracy_cnt = 0


for i in range(0, len(x), batch_size): #0부터 len(x)까지 batch_size간격
  x_batch = x[i:i+batch_size]
  y_batch = predict(network, x_batch) # 확률 배열로 반환
  p = np.argmax(y_batch, axis=1) #배열에서 확률이 가장 높은 원소
  accuracy_cnt += np.sum(p == t[i:i+batch_size]) # 100장씩 실제 답과 비교
  
print("Accuracy: "+str(float(accuracy_cnt) / len(x)))

 

이번 장에서 배운 내용

- 신경망에서는 활성화 함수로 시그모이드 함수와 ReLU함수 같은 매끄럽게 변화하는 함수 이용

- 넘파이의 다차원 배열 잘 사용하면 신경망 효율적으로 구현가능

- 기계학습 문제는 크게 회귀와 분류로 나눌 수 있음

- 출력층 활성화 함수로 회귀에서는 주로 항등함수, 분류에서는 주로 소프트맥스 함수 이용

- 분류에서는 출력층의 뉴런 수를 분류하려는 클래스 수와 같게 설정

- 입력데이터를 묶은 것을 배치라 하며, 추론처리를 배치단위로 진행하면 빠른 결과

  1. 벡터의 스칼라배들이 합으로 연결된 형태 [본문으로]
728x90
반응형

댓글