728x90
◎ 밑바닥부터 시작하는 딥러닝(1)¶
● chapter 3. 신경망¶
- ANO, OR 게이트의 진리표를 보면서 인간이 적절한 가중치 값을 정해야 하는 단점이 있었습니다.
- 신경망은 가중치 매개변수의 적절한 값을 데이터로부터 자동으로 학습하는 능력이 있습니다.
3.1 퍼셉트론에서 신경망으로
- 신경망은 입력층, 출력층, 은닉층으로 구성
- 입력 신호의 총합을 출력 신호로 변환하는 함수를 활성화 함수라 한다.
3.2 활성화 함수
- 임계값을 경계로 출력이 바뀌는 함수를 계단 함수라 한다.
- 신경망에서 자주 이용하는 활성화 함수인 시그모이드 함수는 h(x) = 1 / (1+exp(-x))로 나타낸다.
In [1]:
import numpy as np
import matplotlib.pylab as plt
# 계단 함수 구현하기
def step_function(x):
y = x>0
return y.astype(np.int)
# 넘파이 배열의 자료형을 변환할 때는 astype() 매서드 사용
In [2]:
x = np.arange(-5,5,0.1)
y = step_function(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)
plt.show()
In [3]:
# 시그모이드 함수 구현하기
def sigmoid(x):
return 1/(1+np.exp(-x))
x = np.arange(-5,5,0.1)
y = sigmoid(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)
plt.show()
- 퍼셉트론 = 계단식 함수 / 신경망 = 시그모이드 함수로 표현할 수 있다. (둘의 공통점은 둘 모두 비선형 함수이다.)
- 즉, 신경망에서는 연속적인 실수가 흐름을 알 수 있습니다.
- 신경망에서는 비선형 함수를 사용해야 합니다. (선형 함수를 이용하면 신경망의 층을 깊게 하는 의미가 없어지기 때문)
- 최근 시그모이드 함수 대신 ReLU 함수를 주로 사용
In [4]:
# ReLU 함수 구현하기
def relu(x):
return np.maximum(0,x)
x = np.arange(-1,2,0.1)
y = relu(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)
plt.show()
3.3 다차원 배열의 계산
- 신경망을 효율적으로 구현하기 위해 다차원 배열의 계산법에 숙달할 필요가 있다.
In [5]:
import numpy as np
# 1차원 배열
A = np.array([1,2,3,4])
print(A)
print(np.ndim(A)) # 차원의 수
print(A.shape) # 배열의 형상
[1 2 3 4] 1 (4,)
In [6]:
# 2차원 배열
B = np.array([[1,2],[3,4],[5,6]])
print(B)
print(np.ndim(B))
print(B.shape)
[[1 2] [3 4] [5 6]] 2 (3, 2)
In [7]:
# 행렬의 곱 2X2 * 2X2 = 2X2
A=np.array([[1,2],[3,4]])
B=np.array([[5,6],[7,8]])
np.dot(A,B)
Out[7]:
array([[19, 22], [43, 50]])
In [8]:
# 2X3 * 2X2 = Error
A=np.array([[1,2,3],[4,5,6]])
C=np.array([[1,2],[3,4]])
np.dot(A,C)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-8-b995d7e0e020> in <module> 2 A=np.array([[1,2,3],[4,5,6]]) 3 C=np.array([[1,2],[3,4]]) ----> 4 np.dot(A,C) <__array_function__ internals> in dot(*args, **kwargs) ValueError: shapes (2,3) and (2,2) not aligned: 3 (dim 1) != 2 (dim 0)
3.4 3층 신경망 구현하기
In [9]:
# 신경망 순방향 구현
def identity_fuction(x):
return x
# 가중치와 편향 초기화
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 # 1층 신경망
z1 = sigmoid(a1) # 위에서 만든 sigmoid 함수
a2 = np.dot(z1,W2) + b2 # 2층 신경망
z2 = sigmoid(a2)
a3 = np.dot(z2, W3) + b3 # 3층 신경망
y = identity_fuction(a3)
return y
network = init_network()
x=np.array([1.0,0.5])
y=forward(network,x)
print(y)
[0.31682708 0.69627909]
3.5 출력층 설계하기
- 신경망은 분류와 회귀 모두 이용 가능
- 분류는 어느 클래스에 속하냐는 문제, 회귀는 수치를 예측하는 문제입니다.
- 항등 함수 : 입력 신호가 그대로 출력 신호가 된다.
소프트맥스 함수(yk) = exp(ak) / ∑exp(ai)
- 소프트맥스 함수의 분모에서 보듯, 출력층의 각 뉴런이 모든 입력 신호로부터 영향을 받습니다.
In [10]:
# 소프트맥스 함수 구현하기
def softmax(a):
exp_a = np.exp(a) # 지수 함수
sum_exp_a = np.sum(exp_a) # 지수 함수의 합
y = exp_a / sum_exp_a
return y
a = np.array([0.3,2.9,4.0])
softmax(a)
Out[10]:
array([0.01821127, 0.24519181, 0.73659691])
소프트맥스 함수는 지수 함수를 사용하므로 수의 범위를 벗어하는 오버플로(overflow) 문제가 발생할 가능성이 높다. (지수 함수란 것이 쉽게 아주 큰 값을 내뱉기 때문)
In [11]:
a = np.array([1010,100,990])
softmax(a) # 값이 너무 커 오버플로문제 발생
<ipython-input-10-4ec827885b93>:4: RuntimeWarning: overflow encountered in exp exp_a = np.exp(a) # 지수 함수 <ipython-input-10-4ec827885b93>:6: RuntimeWarning: invalid value encountered in true_divide y = exp_a / sum_exp_a
Out[11]:
array([nan, 0., nan])
In [12]:
# 오버플로 문제 해결 방법
def softmax2(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
In [13]:
softmax2(a) # 오버플로 문제 해결
Out[13]:
array([9.99999998e-01, 0.00000000e+00, 2.06115362e-09])
In [14]:
# 소프트맥스 함수의 특징
a = np.array([0.3,2.9,4.0])
y = softmax(a)
np.sum(y)
# 1. 출력 총합은 1이 된다.
Out[14]:
1.0
In [15]:
# 2. 출력값이 0과 1 사이의 실수임을 통해 확률로 해석 가능하다.
print(y)
[0.01821127 0.24519181 0.73659691]
소프트맥스 함수는 단조 증가 함수이기 때문에 대소 관계가 그대로 이어진다.
결과적으로 신경망으로 분류할 때는 지수 함수 계산에 드는 자원 낭비를 줄이고자 출력층의 소프트맥스 함수를 생략해도 된다.
기계학습의 문제 풀이는 학습과 추론 두 단계로 이루어지며 추론 단계에서는 출력층의 소프트맥스 함수를 생략하는 것이 일반적이지만 신경망을 학습시킬 때는 출력층에서 소프트맥스 함수를 사용한다.
출력층의 뉴런 수는 분류하고 싶은 클래스 수로 설정하는 것이 일반적이다.
3.6 손글씨 숫자 인식
- 순전파(forward propagation) : 신경망의 추론 과정을 일컫는 말
- 데이터를 특정 범위로 변환하는 처리를 정규화(normalization)
- § 정규화 외에도 데이터를 균일하게 분포시키는 데이터 백색화(whitening)이 있다.
- 특정 변환을 가하는 것을 전처리(pre-processing)
In [16]:
import sys, os
sys.path.append('C:/Users/설위준/Desktop/deep-learning-from-scratch-master') # 부모 디렉터리의 파일을 가져올 수 있도록 설정
from dataset.mnist import load_mnist
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)
# 각 데이터의 형상 출력
print(x_train.shape)
print(t_train.shape)
print(x_test.shape)
print(t_test.shape)
(60000, 784) (60000,) (10000, 784) (10000,)
In [17]:
import sys, os
sys.path.append('C:/Users/설위준/Desktop/deep-learning-from-scratch-master') # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import numpy as np
from dataset.mnist import load_mnist
from PIL import Image
def img_show(img):
pil_img = Image.fromarray(np.uint8(img))
pil_img.show()
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)
# 데이터 하나 출력해보기
img = x_train[0]
label = t_train[0]
print(label) # 5
print(img.shape) # (784,)
img = img.reshape(28, 28) # 형상을 원래 이미지의 크기로 변형
print(img.shape) # (28, 28)
img_show(img)
5 (784,) (28, 28)
배치(batch)
- 입력 데이터를 묶은 것을 배치라 하며, 추론 처리를 이 배치 단위로 진행하면 결과를 훨씬 빠르게 얻을 수 있다.
- 큰 배열을 효율적으로 처리할 수 있도록 고도로 최적화되어 있다.(배치 처리를 통해 큰 배열로 이뤄진 계산을 하게 된다.)
- 배치 처리를 함으로써 버스에 주는 부하를 줄일 수 있다.
In [18]:
from IPython.core.display import display, HTML
display(HTML("<style>.container {width:80% !important;}</style>"))
728x90
'Book report > Deep Learning from Scratch' 카테고리의 다른 글
Chapter 6. 학습 관련 기술들 (0) | 2021.10.10 |
---|---|
Chapter 5. 오차역전파법 (0) | 2021.10.09 |
Chapter 4. 신경망 학습 (0) | 2021.10.06 |
Chapter 2. 퍼셉트론 (0) | 2021.08.15 |