가중치 매개변수의 적절한 값을 데이터로부터 자동으로 학습하는 능력을 지님
저자 제작
은닉층의 뉴런은 겉으로 드러나 있지 않음
입력 신호의 총합을 출력 신호로 변환하는 함수
$$ y=h(b+w_1x_1+w_2x_2)\\ h(x) = \begin{cases} 1 & \text{$x \gt 0$}\\ 0 & \text{$x \le0$}\end{cases} $$
위의 식은 다음의 두 단계로 나눌 수 있음:
저자 제작 - 동작을 더 명확히 드러낼때 위와 같이 표기
계단 함수: 임계값을 경계로 출력이 바뀜
단층 네트워크에서 사용
def step_function(x):
if x > 0:
return 1
else:
return 0
------------------------
def step_function_numpy(x):
y = x > 0
return y.astype(np.int)
계단 함수의 그래프
시그모이드 함수(Sigmoid Function): $y = \frac{1}{1+e^{-x}}$
def sigmoid(x):
return 1 / (1+np.exp(-x))
시그모이드 함수의 그래프
계단 함수 vs. 시그모이드 함수
공통점:
비선형 함수
출력이 0에서 1 사이
입력이 작아지면 출력은 0에 가깝고 입력이 커지면 출력이 1에 가까움
차이점:
시그모이드 함수는 부드러운 곡선이며 출력이 연속적으로 변함 + 실수 반환
계단 함수는 0을 경계로 출력이 바뀜 + 정수 반환
비선형 함수: (직선 한 개로 그릴 수 없는 함수 - 계단 함수도 비선형)
신경망에서는 비선형 함수를 활성화 함수로 사용 - 선형은 사용하지 않음
선형 함수은 활성화 함수로 사용할 경우 은닉층이 사라짐
$h(x)=cx$를 활성화 함수로 사용한 3층 네트워크는 $y(x) = h(h(h(x))) = c^3x$이 됨
즉, 층을 쌓는 이점이 사라짐
ReLU 함수(Rectified Linear Unit): $h(x) = \begin{cases} x & \text{$x \gt 0$}\\ 0 & \text{$x \le0$}\end{cases}$
*Rectified: "정류된", 정류 - 전기회로 용어로 -흐름을 차단한다고 생각하면 됨
def relu(x):
return np.maximum(0, x)
ReLU 함수의 그래프
행렬: (센솔님의 블로그 중 이산수학 카테고리 참고) - 밑은 Numpy 활용 코드 소개
import numpy as np
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
np.ndim(A) -> A가 몇차원 배열인지
[np.array].shape -> MxN 행렬에서 (M, N)을 반환
np.dot(A, B) -> 곱
*표기법: 자료마다 다를 수 있으니 확인 필수
가중치: 예) $w^{(1)}_{12}$
$$ w^{(N층의\hspace{1mm}가중치)}_{다음\hspace{1mm}층의\hspace{1mm}N번째\hspace{1mm}뉴런|앞\hspace{1mm}층의\hspace{1mm}M번째\hspace{1mm}뉴런} $$
은닉층 뉴런: 예)$a^{(1)}_1$
$$ a^{(N층의\hspace{1mm}뉴런)}_{현재\hspace{1mm}층의\hspace{1mm}N번째\hspace{1mm}뉴런} $$
편향: 예) $b^{(1)}_1$
$$ b^{N층의 \hspace{1mm}뉴런}_{다음\hspace{1mm}층의\hspace{1mm}N번째\hspace{1mm}뉴런} $$
저자 제작
*σ()는 항등 함수로 입력을 그대로 출력함 - 위의 그림에서는 출력층의 활성화 함수로 사용됨
실행 식 예시:
$$ a^{(1)}1 = w^{(1)}{11}x_1+w^{(1)}_{12}x_2+b^{(1)}_1 $$
$$ A^{(1)} = XW^{(1)}+B^{(1)}\\ A^{(1)} = \begin{pmatrix}a^{(1)}_1&a^{(1)}_2&a^{(1)}_3\end{pmatrix},X=\begin{pmatrix}x_1&x_2\end{pmatrix},B^{(1)}=\begin{pmatrix}b^{(1)}_1&b^{(1)}_2&b^{(1)}_3\end{pmatrix} $$
$$ W^{(1)}=\begin{pmatrix} w^{(1)}{11}&w^{(1)}{21}&w^{(1)}{31}\\ w^{(1)}{12} & w^{(1)}{22} & w^{(1)}{32}\end{pmatrix} $$
# 위의 그림의 식 구현 #
# 1. 입력층에서 1층(첫 번째 은닉층)으로 온 신호 처리
X = np.array([x1, x2])
W1 = np.array([
[w11, w21, w31],
[w12, w22, w32]
])
B1 = np.array([b1, b2, b3])
A1 = np.dot(X, W1) + B1
Z1 = sigmoid(A1) # 시그모이드 함수는 예시로 사용
# 2. 1층에서 2층으로 온 신호 처리
W2 = np.array([
[w11, w21],
[w12, w22],
[w13, w23],
])
B2 = np.array([b1, b2])
A2 = np.dot(Z1, W2) + B2
Z2 = sigmoid(A2) # 시그모이드 함수는 예시로 사용
# 3. 2층에서 출력층으로 온 신호 처리
def identify_function(x):
return x
W3 = np.array([
[w11, w12],
[w12, w22]
])
B3 = np.array([b1, b2])
A3 = np.dot(Z2, W3) + B3
Y = identify_function(A3)
def init_network():
network = {}
network['W1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
network['W1'] = 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['W1'] = np.array([0.1, 0.3, 0.5])
network['W3'] = np.array([[0.1, 0.3], [0.2, 0.4]])
network['W1'] = np.array([0.1, 0.2])
return network
# forward인 이유는 신호가 순방향으로 전달됨을 알리기 위함 <-> backward
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(x, W2) + b2
z2 = sigmoid(a2)
a3 = np.dot(x, W3) + b3
y = identify_function(a3)
return y
network = init_network()
x = np.array([1.0, 0.5])
y = forword(network, x)
print(y) # [0.31682708, 0.69627909]
출력층의 활성화 함수는 문제의 성질에 따라 달라짐