티스토리 뷰

1. Intro

퍼셉트론 : 층을 쌓는 방법을 통해 복잡한 함수를 표현할 수 있으며 가중치 설정을 직접 수동으로 해야하는 단점이 있다.

신경망 : 퍼셉트론의 단점을 해결해 줄 수 있는 개념으로 가중치를 학습할 수 있게 되었다.

 

2. 퍼셉트론 ⇒ 신경망

hidden layer 1개가 추가된 신경망

Hidden Layer는 사람 눈에 보이지 않는 층(input, output만 쉽게 볼 수 있으므로)이라는 의미로 쓰이며, 층은 3개지만 가중치는 2개의 층에만 존재하므로 2층 신경망이라고도 부른다. 그림 상으로는 퍼셉트론과 차이가 없다.

 

퍼셉트론에 대해서는 아래 링크에서 다뤘으니 확인!

https://dreamkkt.com/10

 

[딥러닝 Basic] XOR 문제로 간단하게 살펴보는 퍼셉트론

1. 퍼셉트론?? 인공 뉴런 / 단순 퍼셉트론으로 불리며, 그림에서 처럼 2개의 노드로부터 입력을 받아 $y$를 출력하는 형태이다. $x_1, x_2$를 노드 $w_1, w_2$를 가중치 $y$를 출력값으로 한다. 퍼셉트론

dreamkkt.com

퍼셉트론 복습

$$ y = \begin{cases} 0 (b+w_1x_1+w_2x_2 \le 0) \\ 1 (b+w_1x_1+w_2x_2 \ge 0) \end{cases} $$

위의 식을 다른 방법으로 표현하면 다음과 같다.

$$ y = h(b+w_1x_1+w_2x_2) $$

$$ h(x) = \begin{cases} 0 (x \le 0) \\ 1 (x \ge 0) \end{cases} $$

입력의 총합이 $h(x)$ 함수를 거쳐서 변환되어 그 변환된 값이 y의 출력으로 보여주는 형태이다.

 

활성화 함수(Actication Function)??

활성화 함수 : $h(x)$ 처럼 입력의 총합을 출력으로 변환하는 함수

$$ a = b + w_1x_1 + w_2x_2 $$

$$ y = h(a) $$

 

활성화함수가 추가된 신경망

활성화함수 여부가 퍼셉트론과 신경망의 차이

참고) 일반적으로는 신경망과 똑같이 퍼셉트론을 활성화함수까지 포함된 개념으로 보는 경우도 있다.

 

3. 활성화 함수 (Activation Function)

함수 중 임계값을 경계로 출력이 바뀌는 경우 계단 함수라 불린다. (Step Function) 활성화함수를 다양하게 사용하여 신경망을 다양하게 구성할 수 있다.

1. Sigmoid 구현

$$ h(x) = \frac{1}{1 + \exp{(-x)}} $$

Sigmoid : 신경망에서 자주 이용되었던 활성화 함수이며, 참고로 Sigmoid는 'S자 모양'을 뜻하는 단어이다.

그래프는 다음과 같으며 코드로 구현할 수 있다.

import numpy as np
import matplotlib.pyplot as plt
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

x = np.arange(-5, 5, 0.01)
y = sigmoid(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1)
plt.title('Sigmoid')
plt.show()

matplotlib 로 시각화한 sigmoid

2. Step Function 구현

## Numpy 배열도 받을 수 있게 하자
import numpy as np
def step_function(x):
    y = x > 0
    return y.astype(int)

print(step_function(np.array([3 ,- 1, 5])))

## 그래프를 그려보자
import matplotlib.pyplot as plt

x = np.arange(-5, 5, 0.01)
y = step_function(x)

plt.plot(x, y)
plt.show()

Step Function

3. Sigmoid vs Step

Sigmoid vs Step

Step Function과 다르게 Sigmoid는 매끄러운 함수로 값이 연속적으로 변한다. (미분가능하다는 점)

입력이 작으면 모두 0에 가깝고, 입력이 커지면 출력이 1에 가까워진다. 극단적인 값이 들어와도 출력값은 0 ~ 1사이를 넘지 않는다.

 

4. 비선형 함수 (nonlinear Function)

Step, Sigmoid 모두 비선형 함수이다. 신경망에서는 활성화 함수로 비선형 함수를 사용해야하는데, 선형함수를 사용하면 층을 깊게 하는 의미가 없어진다. (수학적으로 여러개의 linear 층을 하나의 linear 층으로 표현가능하기 때문)

 

Example)

$h(x) = cx$로 하는 3층 네트워크에 대해서 $y(x) = h(h(h(x)))$가 성립하며, $y(x) = c*c*c*x$인데 이것은 $y(x) = ax$와 같이 표현할 수 있다. 즉, 은닉층이 없는 네트워크로 표현이 가능하며, 이것은 여러 층으로 구성하는 이점을 살리기 어렵다. 층을 쌓아서 표현력을 더 다양하게 하려면 비선형 함수를 사용하는 것이 좋다.

 

ReLU

$$ h(x) = \begin{cases} x (x > 0) \\ 0 (x \le 0 ) \end{cases} $$

코드로 구현하면 다음과 같다.

import numpy as np
import matplotlib.pyplot as plt
def ReLU(x):
    result = np.zeros(x.shape)
    result[x > 0] = x[x > 0]
    return result

x = np.arange(-5, 5, 0.1)
y = ReLU(x)
plt.xlim(-5, 5)
plt.plot(x, y, linewidth=3)

plt.show()

matplotlib로 시각화한 ReLU

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

다음과 같이 간단하게 구현할 수 있다.

 

5. 다차원 배열의 계산

import numpy as np

X = np.array([1, 2])
W = np.array([[1, 3, 5], [2, 4, 6]])

print(np.dot(X, W))
# [5, 11, 17]

6. 3층 신경망 구현

import numpy as np

def ReLU(x):
    return np.maximum(0, x)
def Sigmoid(x):
    return 1 / (1 + np.exp(-x))

X = np.array([1, 2])
W1 = np.array([[1, 3, 5], [2, 4, 6]])
b1 = -5
a1 = np.dot(X, W1) + b1
z1 = Sigmoid(a1)
print(a1)
print(z1)

W2 = np.array([[3, 4], [5, 6], [7, 8]])
b2 = -3
a2 = np.dot(z1, W2) + b2
z2 = Sigmoid(a2)
print(a2)
print(z2)

W3 = np.array([[-5, 3], [-2, 6]])
b3 = -4
a3 = np.dot(z2, W3) + b3
Y = Sigmoid(a3)
print(a3)
print(Y)

X : 입력값, W : 가중치, b : bias, a : hidden layer에서의 합성 결과

z : activation 통과 후 값, Y : 최종 출력값

함수화하면??

import numpy as np

def ReLU(x):
    return np.maximum(0, x)
def Sigmoid(x):
    return 1 / (1 + np.exp(-x))

def init_weight():
    network = {}
    network['w1'] = np.array([[1, 3, 5], [2, 4, 6]])
    network['w2'] = np.array([[3, 4], [5, 6], [7, 8]])
    network['w3'] = np.array([[-5, 3], [-2, 6]])
    network['b1'] = -5
    network['b2'] = -4
    network['b3'] = 3

    return network

def Layer3_NeuralNetwork(w_dict, x):
    a1 = np.dot(x, w_dict['w1']) + w_dict['b1']
    z1 = Sigmoid(a1)

    a2 = np.dot(z1, w_dict['w2']) + w_dict['b2']
    z2 = Sigmoid(a2)

    a3 = np.dot(z2, w_dict['w3']) + w_dict['b3']
    z3 = ReLU(a3)

    return a3, z3

X = np.array([1, 2])
w_dict = init_weight()

print(Layer3_NeuralNetwork(w_dict, X))

 

다음 글에서는 출력층에 대해서 이야기하려고 한다.