티스토리 뷰

신경망

퍼셉트론과 신경망의 가장 큰 차이점은 매개변수를 신경망은 직접 학습하는 능력이 있다는 것이고 그것을 알기위해 신경망에 대해 다가가보자.


신경망의 예

신경망의 3가지 층

입력층 : 입력신호가 들어오는 층

은닉층 : 입력층과 출력층의 사이에 있는 신경망을 구성하는 층

출력층 : 출력함수를 통해 결과가 들어가는 곳으로 출력값이 나오는 층

 

노란색부분을 보자! 위의 그림에서 b가 생략되었다고 하고 편향 b를 도입해서 다시 그려보면 다음과 같다.

이전 노드의 x1,x2가 가중치를 만나서 곱해져서 다 더해지고 편향을 도입한 결과값을 a라고 하자.

a를 얼마나 큰 값으로 혹은 작은 값으로 y가 인식할 것인가를 판별해주는 것이 h(x)라는 함수이고 h(x)는 활성화시키는 정도를 결정짓는다.

 

h(x)란 무엇일까?

활성화함수 : 입력 신호의 총합을 출력 신호로 변환하는 함수를 일반적으로 활성화 함수라고하며 입력신호의 총합이 활성화를 일으키는지를 결정젓는 역할을 한다.

=> 위의 사진에서 h(x)를 활성화함수라고한다.

이해를 돕기 위해 노드의 과정을 다시 보자!

=> 다음과 같이 이해하면 된다.


활성화 함수의 종류

1. 시그모이드 함수

h(x) = 1 / 1 + exp(-x)

 

#넘파이를 활용한 시그모이드함수 구현
import numpy as np
def sigmoid(x):
    return 1/(1+np.exp(-x))
x = np.array([-1.0,1.0,2.0])
print(sigmoid(x))

import matplotlib.pylab as plt
x = np.arange(-5.0,5.0,0.01)
y = sigmoid(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)#y축의 범위를 지정
plt.show()

[0.26894142 0.73105858 0.88079708]

sigmoid함수

시그모이드는 신경망에서 계단함수와 비교해서 비선형적인 모델이기때문에 실생활에서 다뤄지는 값들을 표현하기에 더 적절하다.  시그모이드의 특징은 아무리 작아져도 0이고 아무리커져도 1이 된다는 점에서 0과 1사이의 값들을 표현할때 사용할 수 있다. 또한 비선형함수로 은닉층이 주는 신경망의 이점을 살리기 위해서 적합한 함수라는 특징을 가진다.

 

2. 계단 함수

퍼셉트론에서 사용했던 활성화함수로 특정 값을 기준으로 이상이면 1 아니면 0이 되는 함수

 

#계단함수 구현
def step_function(x):
    if x>0:
        return 1
    else:
        return 0
    
#넘파이를 활용한 계단함수 구현
import numpy as np
def step_function(x):
    y = x>0
    return y.astype(np.int)
#x가 np.array일때 위의 함수를 적용하면 됨.

x = np.array([-1.0,1.0,2.0])
print(step_function(x))

[0 1 1]

계단함수와 같은 선형함수의 문제점은 은닉층이 없다는 문제점이 있다. 저번 퍼셉트론에서 살펴본것처럼 단계수를 늘리지 못해서 1차원의 선형식만 표현할 수 있는것과 같다. 여러층으로 구성된 네트워크를 표현하고 싶다면 반드시 활성화함수로 비선형함수를 사용해야합니다.

 

3. RELU 함수

x값이 (입력값이) 0보다 작거나 같으면 0이 출력되고 0보다 크다면 들어간 입력값 x가 y값이 된다.

h(x) = x (x>0) or 0 (x<=0)

 

#ReLU함수

def relu(x):
    return np.maximum(0,x)

#numpy의 메서드중 maxinum을 사용하면 "두값중 큰 값"을 결과값으로 준다.


import matplotlib.pylab as plt
x = np.arange(-5.0,5.0,0.01)
y = relu(x)
plt.plot(x,y)
plt.ylim(-0.1,5.1)#y축의 범위를 지정
plt.show()

ReLU함수

*지금까지 활성화 함수로 신경망 분야에서 시그모이드함수가 오래전부터 사용되었지만 최근에는 ReLU함수가 주로 사용된다.

 


신경망에서의 행렬의 곱

넘파이 행렬을 사용해서 신경망을 구현해보자!

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(X.shape)
print(W1.shape)
print(B1.shape)
#행렬의 계산이 되는지 우선 np.shape로 체크가능

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

(2,) (2, 3) (3,) [0.57444252 0.66818777 0.75026011]

=> 두개의 층의 입력과 출력 과정을 살펴보았다. 여러단계를 거칠때를 알아보자!

방금 구한 Z1이 input값이 된다면? 3층신경망(입력층,2개의은닉층,출력층의 구성)을 알아보자

def sigmoid(x):
    return 1 / (1 + np.exp(-x))


# 항등함수
def identity_function(x):
    return x


# 3.4.3 구현 정리



def identity_function(x):
    return x
    #현재 출력함수를 항등함수로 정의하였다.
    
#네트워크의 매개변수들을 초기화해주는 함수인 init_network()함수
def init_network():
    network = {}
    network['W1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
    network['b1'] = np.array([0.1, 0.2, 0.3])
    network['W2'] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
    network['b2'] = np.array([0.1, 0.2])
    network['W3'] = np.array([[0.1, 0.3], [0.2, 0.4]])
    network['b3'] = np.array([0.1, 0.2])

    return network # 딕셔너리 형태로 반환한다.


def forward(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 = identity_function(a3)#출력층에서는 활성화함수가 아닌 identity_function을 출력한다.

    return y #최종결과가 담긴 배열을 반환한다.


network = init_network()
x = np.array([1.0, 0.5])#입력값 2개
y = forward(network, x)  #순방향으로 진행되는 순서로 작성해놓은 forward를 불러옴
# [ 0.31682708  0.69627909] => 출력값 2개

print(y)

*출력함수로는 위의 예시처럼 항등함수가 될 수 있고 혹은 소프트맥스함수를 활용할 수 있다.

*소프트맥스함수는 출력층의 뉴런값들중 가장 큰 값과의 차이들을 모두 지수함수에 입력으로 넣고 나온 총 합을 각각의 값들로 나눈 값을 결과로 하는 함수이다.

import numpy as np
a = np.array([0.3, 2.9, 4.0])
y = softmax(a)
print(y)  # [ 0.01821127  0.24519181  0.73659691]
print(np.sum(y))  # 1.0

#지수함수 성질을 가지고 있기에 오버플로우가 날 수 있고 이를 위해 최댓값을 빼준다.
def softmax(a):
    c = np.max(a)
    exp_a = np.exp(a - c)  # 오버플로 대책
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a

    return y

<소트프맥스 함수>

출력은 0에서 1사이의 실수이며 출력의 총합은 1이고 확률로 해석이 가능하다.
출력의 결과의 대소관계와 원소의 대소 관계가 일치하기에 자원 낭비를 줄이기 위해 생략하기도 한다는 특징이 있다.
기계 학습의 문제 풀이는 학습과 추론의 두 단계로 이루어진다.
추론 단계에서는 출력층의 소프트맥스 함수를 생략하는 것이 일반적이며,
학습시킬때는 출력층에서 소프트맥스 함수를 사용한다.