6강에 이어서 7강에서는 뉴런 네트워크를 효과적으로 구축하기 위한 방식에 대해 이야기한다.
가장 중요한 것은 최적화 문제
두개의 가중치 W_2, W_1을 최적화시키는 문제라고 할 때, 가장 붉은색 지점 (가장 낮은 loss를 가진 지점)을 찾는 것
#간단한 알고리즘 Vanilla Gradient Descent
while True:
weights_grad = evaluate_gradient(loss_fun, data, weights)
weights += - step_size * weights_grad #perform parameter update
gradient의 방향이 고르지 못함. loss에 영향ㅇㅇ
고차원 공간에서 훨씬 빈번하게 발생
미니배치의 데이터들만을 가지고 구할 수 있음
추정값만을 구할 뿐임
노이즈가 들어가면 더 오래 걸릴 것임
vx = 0
while True:
dx = compute_gradient(x)
vx = rho * vx + dx
x += learning_rate * vx
velocity를 유지하는 것. gradient 방향만 고려하는 것이 아니라 velocity 고려
rho로 velocity의 영향력을 맞춰줌 (0.9 정도로 크게)
local minima에 도달해도 velocity가 있어서 넘어가서 내려갈 수 있음. saddle point에서도 마찬가지
noise가 평균화 되어버림
minima를 향해 부드럽게 움직임
velocity와 gradient의 벡터합
Nesterov momentum 계산 순서를 바꿈
현재지점 - graident와 velocity를 더함
convex problem에서 성능이 좋음
velocity의 초기값은 0
dx = compute_gradient(x)
old_v = v
v = rho * v - learning_rate * dx
x += -rho * old_v + (1 + rho) * v
좁고 깊은 minima는 더 심한 overfit을 불러옴. 이런 minima는 애초에 좋지 않음. 그래서 지나가는 것을 걱정할 필요는 없음 flat minima가 필요함
momentum의 특징이라고 할 수 있음
훈련도중 계산되는 gradients를 활용하는 방법 velocity term 대신해서
non-convex 인 경우 멈출 수 있음
grad_squared = 0
while True:
dx = compute_gradient(x)
grad_squared += dx * dx
x -= learning_rate * dx / (np.sqrt(grad_squared) + le-7)
gradients의 제곱을 계속해서 누적해 나감
grad_squared = 0
while True:
dx = compute_gradient(x)
grad_squared = decay_rate * grad_squared + (1 - decay_rate) * dx * dx
x -= learning_rate * dx / (np.sqrt(grad_squared) + le - 7)
decay rate는 보통 0.9, 0.99
점점 속도가 줄어드는 문제를 해결할 수 있음
momentum의 경우 overshoot한 다음 돌아오면
RMSProp은 적절하게 궤도를 수정해서 옴
알고리즘 별로 다른 lr를 적용해서 visualization비교하자
모멘텀은 방향, RMSProp은 보폭을 조정해줌
초기에 second momentum 0, 1회 없데이트 하고 나면 0에 가까운데 나눠주는 값이 크기 때문에 초기 step이 엄청나게 커지게 됨. 근데 이게 인공적인 현상임
엉뚱한 곳으로 이동해서 수렴할 수 없을 수도 있음
그래서 보정하는 항을 추가해줌
first_moment = 0
second_moment = 0
for t in range(num_iterations):
first_moment = beta1 * first_moment + (1 - beta1) * dx #Momentum
second_moment = beta2 * second_moment + (1 - beta2) * dx * dx
first_unbias = first_moment / (1 - beta1 ** t) #Bias correction
second_unbias = secodn_moment / (1 - beta2 ** t)
x -= learning_rate * first_unbias / (np.sqrt(second_unbias) + 1e-7)) #AdaGrad/RMSProp
다양한 문제들에서도 잘 작동함
일반적으로 beta1 = 0.9, beta2 = 0.999 lr = 1e-3 or le-4 정도면 시작하기 좋음
Momentum스러우면서 RMSProp스러움
손실함수가 회전된 타원형일 경우 다루기 힘든 문제임. 다른 optimization도 마찬가지임 근데
좋은 learning rate 구하는 방법은 뭘까
learning rates decay 설정하기
높게 설정 -> 점점 낮추기
learning rate decay는 SGD Momentum에 더 많이 씀
초기 부터 고려하지는 않음. 그냥 잘 선택하는 것이 중요 (학습 초기)
First-Order Optimization이었음
2차 근사 정보를 사용하는 것은? second-order taylor
Newton step
Hessian matrix를 계산, 역행렬을 이용하여 손실함수의 2차 근사를 이용해 minima로 곧장 이동
learning rate가 없음!
하지만 사실상 필요함. minima 방향으로 이동하는 거니까
근데 deep learning에서 불가...너무 커져서..역행렬계산도 안됨..
근사시키는 방법을 쓰기도 함
second-order optimization이긴 함
사실상 DNN에서 잘 안 씀
2차 근사가 잘 적용되지 않으니까
full batch update가 가능하고 stochasticity이 적은 경우라면 좋은 선택일 수 있음
다시 정리
optimization 알고리즘은 training error를 줄이고 손실함수를 최소화시키기 위한 역할
근데 training error보다는 test error가 더 중요한 거임
한번도 보지 못한 데이터에 대한 성능은 어떠한가?
여러 모델 결과의 평균을 이용하는 것
보통 2%증가함.
학습 도중 중간 모델을 저장(snapshot)하고 ensemble도 가능 이게?
그럼 어떤 모델을 앙상블하는 게 좋은가?
서로 다른 하이퍼파라미터로 앙상블
학습하는 동안 파라미터의 exponentially decaying average를 계속 계산
checkpoint에서의 파라미터를 그대로 쓰지 않고
Polyak averaging
단일 모델 성능 올리기?가 진짜 원하는 거임
L2 regularization은 별로 잘 맞지 않음
forward pass 과정에서 일부 뉴런을 0으로 만드는 것
일부 뉴런만 사용하게 됨.
forward pass iteration 마다 그 모양이 바뀌게 됨
activation을 0으로 두게 되는 것
네트워크에 z라는 입력이 추가됨 - random dropout mask
이미 학습된 네트워크의 test time에는 이런 stochasticity은 적절하지 않음
그 대신 randomness를 average out 시킴
근데 적분을 다루기가 좀 까다로움
cheap한 방법은 dropout probability를 네트워크의 출력에 곱함
test time에는 기존 연산을 그대로 사용하고 대신 train time에서 p를 나눠줌.
(test time에서는 계산 효율이 중요하니까..)
전체 학습시간은 늘어남 - 왜???
Training : Add some kind of randomness
Testing : Average out randomness
이미지를 무작위로 변환시키기. 레이블은 그대로 두고
원본이미지가 아니라 무작위로 변환된 이미지 사용하는 것
train time에는 stochasticity가 추가, test time에는 marginalize out
activation이 아닌 weight matrix를 임의적으로 0으로 만들어주는 방법
Dropout과 비슷
pooling연산을 수행할 지역이 임의로 선정됨
pooling regions를 고정시켜 버리거나 혹은 여러개의 pooling regions을 만들고 averaging over시킴
bn을 가장 많이씀
이래도 충분한데 overfitting이 발생하면 dropout쓰기 가능
충분한 데이터가 없을 때 오버피팅 생김
imagenet에서 학습된 feature을 내가 가진 작은 데이터셋에 적용
freeze시키고 마지막 레이어만 가지고 내 데이터 학습시킴
데이터가 더 있으면 전체 데이터를 파인튜닝할 수 있음