[밑바닥부터 시작하는 딥러닝] CH3. 신경망(1) - 계단함수, 시그모이드 함수, ReLU 함수, 다차원 배열, 행렬의 곱
CH3. 신경망
- 퍼셉트론으로 가중치를 설정하는 작업(원하는 결과를 출력하도록 가중치 값을 적절히 정하는 작업)은 할 수 없음
- 신경망은 가중치 매개변수의 적절한 값을 데이터로부터 자동으로 학습하는 능력이 있음
1. 퍼셉트론에서 신경망으로
1) 신경망
- (왼->오 방향 순서대로) 입력층, 은닉층, 출력층이고, 차례로 0층, 1층, 2층이라고 함
- 은닉층의 뉴런은 보이지 않음
그림의 신경망은 3층으로 구성되지만, 가중치를 갖는 층은 2개뿐이기에 '2층 신경망'이라고 함.
책에서는 실제로 가중치를 갖는 층의 개수(입력층, 은닉층, 출력층의 함계에서 1을 뺀 값)를 기준으로 함
2) 퍼셉트론 복습
b : 편향 - 뉴런이 얼마나 쉽게 활성화되느냐를 제어함
w1, w2 : 가중치 - 각 신호의 영향력 제어
- 가중치가 b이고, 입력이 1인 뉴런이 추가됨
- 이 퍼셉트론의 동작은 x1, x2, 1이라는 3개의 신호가 뉴런에 입력되어, 각 신호에 가중치를 곱한 후, 다음 뉴런에 전달 됨
- 다음 뉴런에서는 이 신호들의 값을 더하여, 그 합이 0을 넘으면 1을 출력하고 그렇지 않으면 0을 출력
편향의 입력신호는 항상 1이기 때문에 다른 뉴런과 구별하기 위해 해당 뉴런을 빗금칠함.
- 조건 분기의 동작(0 넘으면 1출력, 그렇지 않으면 0 출력)을 하나의 함수로 나타냄
- 입력 신호의 총합이 h(X)라는 함수를 거쳐 변환되어, 그 변환된 값이 y의 출력이 됨을 보여줌
- 즉, h(x) 합수 입력이 0을 넘으면 1을, 그렇지 않으면 0 출력
2) 활성화 함수
활성화 함수: 입력 신호의 총합을 출력 신호로 변환하는 함수(즉, 입력 신호의 총합이 활성화를 일으키는지를 정하는 역할)
- a = b + w1x1 + w2x2 (가중치가 곱해진 입력 신호와 편향의 총합 계산)
- y = h(a) (합을 활성화 함수에 입력해 결과를 냄, a를 gkatn h()에 넣어 y 출력)
- 가중치 신호 조합한 결과 a라는 노드 되고, 활성화 함수 h()를 통과하여 y라는 노드로 변환되는 과정이 나타남
- 책에서 뉴런 = 노드
- 단순 퍼셉트론 = 단층 네트워크에서 계단 함수(임계값을 경계로 출력이 바뀌는 함수)를 활성화 함수로 사용한 모델
- 다층 퍼셉트론 = 신경망(여러 층으로 구성되고 시그모이드 함수 등의 매끈한 활성화 함수를 사용하는 네트워크)을 가리킴
2-1) 계단 함수
계단 함수(step function)
: 임계값을 경계로 출력이 바뀌는 활성화 함수
- 퍼셉트론은 활성화 함수로 계단 함수 이용
- 활성화 함수를 계단 함수에서 다른 함수로 변경하는 것이 신경망의 세계로 나아가는 열쇠
계단 함수 구현하기
# 입력이 0을 넘으면 1 출력, 그 외에는 0 출력
# 인수 x는 실수만 받아들여서, 넘파이 배열을 인수로 넣을 수 없음
def step_function_1(x):
if x > 0:
return 1
else:
return 0
# 넘파이 배열 인수로 넣기
import numpy as np
def step_fucntion_2(x):
y = x > 0
return y.astype(np.int)
# 넘파이 배열에 부등호 연산을 수행하면 배열의 원소 각각에 부등호 연산을 수행한 bool 배열이 생성됨
# 즉, y는 bool 배열
# 하지만 계단함수는 0이나 1의 'int형'dmf cnffurgksms gkatn -> y의 원소를 bool에서 int형으로 바꿔줌
# numpy 자료형 변환 astype() 메서드 사용
계단 함수 그래프
import matplotlib.pylab as plt
def step_function_3(x):
return np.array(x > 0, dtype=np.int)
x = np.arange(-5.0, 5.0, 0.1) # -5.0에서 5.0 전까지 0.1 간격의 넘파이 배열 생성
y = step_function_3(x) # 인수로 받은 넘파이 배열의 원소 각각을 인수로 계단 함수 실행, 그 결과를 다시 배열로 만들어 돌려줌
plt.plot(x, y)
plt.ylim(-0.1, 1.1) # y축의 범위 지정
plt.show()
- 이렇게 계단 함수는 0을 경계로 출력이 0에서 1로 바뀜
- 바뀌는 형태가 계단처럼 생겨서 '계단함수'
신경망에서 이용하는 활성화 함수
2-2) 시그모이드 함수
시그모이드 함수(sigmoid function)
시그모이드 함수 구현하기
def sigmoid(x):
return 1 / (1 + np.exp(-x))
- 인수 x가 넘파이 배열이어도 결과 올바르게 나옴
- np.exp(-x)가 넘파이 배열을 반환하기 때문!
시그모이드 함수 그래프
x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1) # y축의 범위 지정
plt.show()
- '시므도이드 = S자 모양'이라는 점만 확실히 기억하기
계단 함수와 시그모이드 함수 비교
- 시그모이드 함수는 부드러운 곡선이며 입력에 따라 출력이 연속적으로 변화함
=> 신경망에서는 연속적인 실수가 흐름- 둘 다 입력이 작을 때의 출력은 0에 가깝고, 입력이 커지면 출력이 1에 가까워 지는 구조
=> 두 함수 모두 입력이 중요하면 큰 값을 출력하고, 중요하지 않으면 작은 값을 출력함- 입력이 아무리 작거나 커도 두 함수의 출력은 0에서 1 사이
계단 함수와 시그모이드 함수 비교(공통점) - 비선형 함수
선형 함수 : 출력이 입력의 상수배만큼 변하는 함수. 즉, 곧은 1개의 직선
비선형 함수 : '선형이 아닌' 함수. 즉, 직선 1개로는 그릴 수 없는 함수.
2-3) ReLU 함수
ReLU 함수
- 시그모이드 함수는 신경망 분야에서 오래전부터 이용해왔으나, 최근엔는 ReLU 함수를 주로 이용함
- 입력이 0을 넘으면 그 입력을 그대로 출력하고, 0 이하면 0을 출력하는 함수
<수식 그림>
ReLU 함수 구현하기
def relu(x):
return np.maximum(0,x)
# numpy의 maximum 함수 사용, 두 입력 중 큰 값을 선택해 반환하는 함수
ReLU 함수 그래프
x = np.arange(-6.0, 6.0, 2)
y = relu(x)
plt.plot(x, y)
plt.ylim(-1, 5, 1) # y축의 범위 지정
plt.show()
참고) 다차원 배열
- 넘파이의 다차원 배열을 사용한 계산법을 숙달하면 신경망을 효율적으로 구현할 수 있음
- 숫자가 한 줄로 늘어선 것, 직사각형으로 늘어놓은 것, n차원으로 나열한 것을 통틀어 다차원 배열이라고 함
1차원 배열
A = np.array([1, 2, 3, 4])
print(A)
# array([1, 2, 3, 4])
np.ndim(A) # 배열의 차원 수 확인
# 1 1차원 배열
A.shape # 배열의 형상
# (4,) 4개 원소로 구성
2차원 배열
B = np.array([[1,2],[3,4],[5,6]])
print(B)
# array([[1, 2],
# [3, 4],
# [5, 6]])
np.ndim(B)
# 2
B.shape
# (3, 2)
# 3*2 배열
# 0번째 차원에는 원소가 3개, 1번째 차원에는 원소가 2개 있다는 의미
# 2차원 배열은 행렬(matrix)라 부르고, 배열의 가로 방향을 행row, 세로 방향을 열column이라고 함
행렬의 곱
- 행렬의 곱은 왼쪽 행렬의 행(가로)와 오르쪽 행렬의 열(세로)을 원소별로 곱하고, 그 값들을 더해서 계산함
A = np.array([[1,2], [3,4]])
A.shape
# (2, 2)
B = np.array([[5,6], [7,8]])
B.shape
# (2, 2)
np.dot(A, B) # 두 행렬의 곱
# 참고로 np.dot(A, B)과 np.dot(B, A)는 다른 값이 될 수 있음
# array([[19, 22],
[43, 50]])
A = np.array([[1,2,3], [4,5,6]])
A.shape
# (2, 3)
B = np.array([[1,2], [3,4], [5,6]])
B.shape
# (3, 2)
np.dot(A, B)
# array([[22, 28],
[49, 64]])
- 행렬의 shape에 주의해야 함. 행렬 A의 1번째 차원의 원소 수 (열 수)와 행렬 B의 0번째 차원의 원소 수 (행수)가 같아야 함
- 즉, 다차원 배열을 곱하려면 두 행렬의 대응하는 차원의 원소 수를 일치시켜야 함
신경망에서의 행렬 곱
X = np.array([1,2])
X.shape
# (2,)
W = np.array([[1, 3, 5], [2, 4, 6]])
print(W)
# array([[1, 3, 5],
[2, 4, 6]])
W.shape
# (2, 3)
Y = np.dot(X, W)
print(Y)
# array([ 5, 11, 17])
- 스칼라곱을 구해주는 np.dot 함수를 사용하면 단번에 결과 Y를 계산할 수 있음
- 행렬의 곱으로 한꺼번에 계산해주는 기능은 신경망 구현할 때 매우 중요
Author And Source
이 문제에 관하여([밑바닥부터 시작하는 딥러닝] CH3. 신경망(1) - 계단함수, 시그모이드 함수, ReLU 함수, 다차원 배열, 행렬의 곱), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@suding/밑바닥부터-시작하는-딥러닝-CH3.-신경망저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)