목차
👀, 🤷♀️ , 📜
이 아이콘들을 누르시면 코드, 개념 부가 설명을 보실 수 있습니다:)
전체 딥러닝 학습과정
이번 포스트에선 어딜 배울까? 바로 오차값에 따라 매개변수를 오차가 없는 방향으로 줄여주는 기본적인 메서드를 볼 것이다.
매개변수가 갱신되려면 미분을 통한 기울기 산출을 통해 손실을 최소화 하는 위치로 이동해야한다.
학습 방식
매개변수의 조정 방식(위의 핑크색 부분)은 다음의 과정을 통해 진행된다.
1️⃣ 먼저 임의의 초기 가중치(W) 를 준 뒤 순전파를 통한 결과 값(output)(Y)을 얻는다
2️⃣ 계산 결과와 우리가 원하는 값 사이의 오차를 구한다
3️⃣ 경사 하강법을 이용해 바로 앞 가중치를 오차가 작아지는 방향으로 업데이트한다
4️⃣ 더이상 오차가 줄어들지 않을 때 까지 위의 과정을 반복한다
이 포스트에서는 3️⃣을 구현하기 위해 쓰이는 수단인 경사 하강법을 배울 것 이다
➕ 3️⃣의 구현은 다음 포스트 backpropagation를 참고하자
그럼 초기 미분의 방식(매개변수 갱신 방식)부터 점점 개선해나가보자
경사법(경사 하강법)
[INTRO]
일반적인 문제에서 손실함수를 찾을 때 매개변수 공간이 광대하여 어디가 최솟값이 되는 곳인지를 짐작할 수 없음
이런 상황에서 기울기를 잘 이용해 함수의 최솟값(또는 가능한 한 작은 값) 을 찾으려는 것이 경사법이다.
[PROBLEM]
함수가 극솟값, 최솟값, 또 안장점 saddle point 이 되는 장소에서는 기울기가 0-> 반드시 최솟값아님
plateau, 플래토
복잡하고 찌그러진 모양의 함수라면 (대부분) 평평한 곳으로 파고들면서 학습이 진행되지 않는 정체기에 빠질 수 있음
안장점: 안장점은 어느 방향에서 보면 극댓값이고 다른 방향에서 보면 극솟값이 되는 점
경사법 gradient method
1) 현 위치에서 기울어진 방향으로 일정 거리만큼 이동.
2) 이동한 곳에서도 마찬가지로 기울기를 구하고,
3) 또 그 기울어진 방향으로 나아가기를 반복
-> 이렇게 해서 함수의 값을 점차 줄이는 것이 경사법
경사 하강법 gradient descent method
: 최솟값을 찾을 때 more learn
경사 상승법 gradient ascent method
: 최댓값을 찾을 때
수식
-
\(η\)(= eta, 에타): 갱신하는 양을 나타냄. 학습률 learning rate이라고도 함
- 1회갱신( 이를 반복해야하여 서서히 함숫값down)
- 변수의 수가 늘어도 같은 식(각 변수의 편미분 값)으로 갱신
[학습률]
한 번의 학습으로 얼마만큼 학습해야 할지,
매개변수 값을 얼마나 갱신하느냐를 정하는 것
- 0.01이나 0.001 등 미리 특정 값으로 정해둬야 함
- (너무 크거나 작으면 좋은장소 찾지 못함)
이와 같은 매개변수를 하이퍼파라미터 hyper parameter, 초매개변수라고 함 - 자동으로 설정되는 가중치와 편향 같은 신경망 매개변수와 달리 사람이 직접 설정해야 하는 매개변수
👀코드 보기
# 인수 f: 최적화하려는 함수
# init_x: 초깃값
# lr: learning rate를 의미하는 학습률
# step_ num은 경사법에 따른 반복 횟수
def gradient_descent(f, init_x, lr = 0.01, step _num = 100):
x = init _x
#미분값 조작
for i in range(step _num):
grad = numerical_gradient(f, x)
x - = lr * grad return x
#그림을 그려주는 소스코드 ch04/gradient_ method.py
신경망에서의 기울기
[기울기]
가중치 매개변수(W)에 대한 손실 함수의 기울기(L)
아래의 두 형상(행과 열의 크기)가 같아야 함
- 경사는 2번째처럼 나타냄
- EX) 1행 1번째 원소: \(w_11\)을 조금 변경했을 때 손실 함수 L이 얼마나 변화하느냐를 나타냄
👀코드 보기
import sys, os
sys.path.append(os.pardir)
import numpy as np
from common.functions import softmax, cross _entropy _error
from common.gradient import numerical _gradient
#simpleNet 클래스는 형상이 2×3인 가중치 매개변수 하나를 인스턴스 변수로 갖음
# randn-> 가우시안 표준 정규분포에서 난수 매트릭스 어래이 생성
class simpleNet:
def __init__(self):
self.W = np.random.randn(2,3) # 정규분포로 초기화
# 예측을 수행, 곱해!
def predict(self, x):
return np.dot(x, self.W)
# 손실 함수의 값을 구함
# x는 입력 데이터, t는 정답 레이블
def loss(self, x, t):
z = self.predict(x)
y = softmax(z)
loss = cross_entropy_error(y, t)
return loss
📌 위의 gradient decent의 실제 적용을 보고 싶다면,
- gradient decent: 정말 세세하게 설명해 두었다. 무조건 한번 보는걸 추천한다
그럼 이제 이 경사학습법 내부를 파헤쳐보자!! 경사학습법네 기본이 되는 내용들이다!! 참고용으로 읽어보길 추천한다
수치 미분
아주 작은 차분으로 미분하는 것이다
오차를 포함한다
- 수학시간에 배운 미분: 해석적 미분
- 해석적 미분(analytic): 오차를 포함하지 않는 ‘진정한 미분’ 값
- 이의 근사치를 구하는건 수치미분
수치미분의 오차
x의 ‘작은 변화’가 함수 f (x )를 얼마나 변화시키느냐
좌변: f (x)의 x에 대한 미분(x에 대한 f (x )의 변화량)을 나타내는 기호
구현시 주의
h를 너무 작은 값으로 설정하면 반올림 오차가 일어남(0이됨)
➡ \(10^{-4}\) 정도가 적당
원래 미분
- x 위치의 함수의 기울기(이를 접선이라 함)에 해당
여기서
- (x + h )와 x 사이의 기울기
- 구현값 엄밀히 일치하지 않음(h를 무한히 0으로 좁히지 못하므로) ➡ 즉 수치미분은 오차를 포함한다
중심 차분 or 중앙 차분
위의 오차를 줄이기 위해 (x + h )와 (x -h )일 때의 함수 f의 차분을 계산하는 방법사용
x를 중심으로 그 전후의 차분을 계산한다는 의미
👀 구현 코드 보기
def numerical_diff(f, x):
h = 1e-4 # 0.0001
return (f(x+h) - f(x-h)) / (2*h)
👀 계산 코드 보기
# 아무 함수나 정의
def function_1(x):
return 0.01*x**2 + 0.1*x
# 이 함수 시각화
import numpy as np
import matplotlib.pylab as plt
x = np.arange(0.0, 20.0, 0.1)
y = function_1(x)
plt.xlabel("x")
plt.ylabel("f(x)")
plt.plot(x, y)
plt.show()
# 이 함수 미분값 확인
numerical_diff(function_1, 5)
편미분
위와 같이 모든 변수 각각에 대해 편미분하여 벡터로 정리한 것을 gradient라고 한다.
변수가 2개인 함수 미분
변수가 2개인 함수 식 구현
👀코드 보기
#미분이 아닌 변수 2개인 함수 단순 식 구현
def function _2(x):
return x[0]**2 + x[1]**2
# 또는 return np.sum(x**2)
x는 넘파이 배열이라고 가정하여 시각화
[미분법]
- 따로 함수를 정의하고 각각 미분해서 더하기
- 한번에 \(x_0=3, x_1=4\)일 때 \((x_0, x_1)\) 양쪽 편미분을 묶어 계산
- 기울기: 모든 변수의 편미분을 벡터로 정리한 것
- 기울기: 모든 변수의 편미분을 벡터로 정리한 것
👀 기울기 구현 코드 보기
def numerical_gradient(f, x):
h = 1e-4 # 0.0001
grad = np.zeros_like(x)
# x 와 형상이 같고 그 원소가 모두 0인 배열
for idx in range(x.size):
tmp_val = x[idx]
# f(x+h) 계산
x[idx] = tmp_val + h
fxh1 = f(x)
# f(x-h) 계산
x[idx] = tmp _val - h
fxh2 = f(x)
grad[idx] = (fxh1 - fxh2) / (2*h)
x[idx] = tmp_val # 값 복원
return grad
#미분값 넣어서 프린트 해보기
numerical _gradient(function _2, np.array([3.0, 4.0]))
>>>array([ 6., 8.])
- 위의 결과값은 방향을 가진 벡터(화살표)로 그려짐
- 그림을 보면 기울기는 함수의 ‘가장 낮은 장소(최솟값)’를 가리키는 것 같음
- 화살표가 한점을 향함
- ‘가장 낮은 곳’에서 멀어질수록 화살표의 크기가 커짐
그런데 꼭 ‘가장 낮은 곳’만 찾는 것도 아님 = 기울기는 각 지점 에서 낮아지는 방향을 가리킴
- 기울기가 가리키는 쪽은 각 장소에서 함수의 출력 값을 가장 크게 줄이는 방향 (출력 값을 줄이면 정확도가 올라가죠?)
학습 알고리즘 구현하기
[절차]
0) 전제
- 신경망에는 적응 가능한 가중치와 편향이 있고, 이 가중치와 편향을 훈련 데이터에 적응하도록 조정하는 과정을 ‘학습’이라 함
- 신경망 학습은 다음과 같이 4단계로 수행
1) 미니배치
- 훈련 데이터 중 일부를 무작위로 가져옴
- 이렇게 선별한 데이터를 미니배치라 하며
- 그 미니배치의 손실 함수 값을 줄이는 것이 목표
2) 기울기 산출
- 미니배치의 손실 함수 값을 줄이기 위해 각 가중치 매개변수의 기울기를 구함
- 기울기는 손실 함수의 값을 가장 작게 하는 방향을 제시
3) 매개변수 갱신
- 가중치 매개변수를 기울기 방향으로 아주 조금 갱신
- 경사하강법 사용(stochastic gradient descent, SGD)
4) 반복
- 1~3단계 반복
이번 장에서 배운 내용
● 아주 작은 값을 주었을 때의 차분으로 미분하는 것을 수치 미분이라고 한다.
● 수치 미분을 이용해 가중치 매개변수의 기울기를 구할 수 있다.
● 수치 미분을 이용한 계산에는 시간이 걸리지만, 그 구현은 간단하다. 한편, 다음 장에서 구현하는 (다소 복잡한) 오차역전파법은 기울기를 고속으로 구할 수 있다