신경망:

가중치 매개변수의 적절한 값을 데이터로부터 자동으로 학습하는 능력을 지님

저자 제작

저자 제작

은닉층의 뉴런은 겉으로 드러나 있지 않음

활성화 함수:

입력 신호의 총합을 출력 신호로 변환하는 함수

$$ y=h(b+w_1x_1+w_2x_2)\\ h(x) = \begin{cases} 1 & \text{$x \gt 0$}\\ 0 & \text{$x \le0$}\end{cases} $$

위의 식은 다음의 두 단계로 나눌 수 있음:

  1. $a = b + w_1x_1 + w_2x_2$
  2. $y = h(a)$

저자 제작 - 동작을 더 명확히 드러낼때 위와 같이 표기

저자 제작 - 동작을 더 명확히 드러낼때 위와 같이 표기

계단 함수: 임계값을 경계로 출력이 바뀜

단층 네트워크에서 사용

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 함수의 그래프

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]

출력층 설계

출력층의 활성화 함수는 문제의 성질에 따라 달라짐