6.1 매개변수 갱신
최적화 : 손실 함수의 값을 가능한 한 낮추는 최적의 매개변수를 찾는 것
6.1.2 확률적 경사 하강법(SGD)
#SGD
class SGD:
def __init__(self, lr=0.01):
self.lr = lr
def update(self, params, grads):
for key in params.keys():
params[key] -= self.lr*grads[key]
- params 매개변수들에 대해 learning rate * key에 대한 gradient만큼 빼주는 방법
6.1.3 SGD의 단점
- 비효율적
- 현재 장소에서 기울어진 방향을 따라서 이동하는데, 현재 위치에서 기울어진 방향이 global minimum의 방향과 차이가 날 수 있어서 지그재그를 그리면서 비효율적인 경로를 따라 움직임 (비등방성 함수)
6.1.4 모멘텀
- v 새로운 변수 : 속도 - 기울기 방향으로 힘을 받아 물체가 가속된다는 물리 법칙
- Loss function에서 기울기가 가파르면 v가 커지고 기울기가 완만하면 v가 작아짐
- SGD에서는 loss function의 기울기에 따라 W를 update 하는 비율이 learning rate로 일정
- 모멘텀에서는 loss function의 기울기에 따라 W를 update 하는 비율이 달라짐
- v가 크면 W가 크게 움직이고 v가 작으면 W가 조금 움직임
#모멘텀
class Momentum:
def __init__(self, lr=0.01, momentum=0.9):
self.lr = lr
self.momentum = momentum
self.v = None
def update(self, params, grads):
if self.v is None:
self.v = {}
for key, val in params.items():
self.v[key] = np.zeros_like(val)
#params딕셔너리 변수의 key에 저장된 val과 같은 형태의 행렬을 만들고 그 행렬을 0으로 채운뒤, v라는 딕셔너리 변수에 저장
#초기 한번만 실행
#v를 갱신한 뒤, 가중치에 대해 갱신
for key in params.key():
self.v[key] = (self.momentum*self.v[key]) - (self.lr*grads[key])
params[key]+=self.v[key]
- SGD와 비교했을 때, 지그재그 정도가 덜함
- f(x,y)의 기울기가 x축은 완만하고 y축은 가파르게 변함
- x축은 일정한 방향으로 가속하고 y축의 방향 속도는 일정하지 않아서 x축으로 빠르게 다가감 -> SGD보다 효율적
6.1.5 AdaGrad
- 신경망 학습에서 학습률 값이 중요
- 학습률을 정하는 효과적 기술 :학습률 감소
- 학습을 진행하면서 학습률을 점차 줄여가는 방법
- 전체의 학습률 값을 각각의 매개변수에 맞게 낮추는 방법 : AdaGrad
- h 새로운 변수 : 기존 기울기 값을 제곱하여 계속 더해줌
- 학습률에 1/√h를 곱해줌
-> L의 변화율이 큰 (dL/dW^2가 큰) 원소는 (1/√h가 작아서) W가 조금 바뀌고 L의 변화율이 작은 (dL/dW^2가 작은) 원소는 (1/√h가 작아서) W가 크게 바뀜 - 매개변수의 원소마다 학습률이 다르게 적용되고, W가 많이 바뀌어서 학습이 많이 된 원소는 학습률이 낮아짐
#AdaGrad
class AdaGrad:
def __init__(self, lr = 0.01):
self.lr = lr
self.h = None
def update(self, params, grads):
if self.h == None:
self.h = {}
for key, val in params.items():
self.h[key] = np.zeros_like(val)
for key in params.keys():
self.h[key] += grads[key] * grads[key]
params[key] -= self.lr*grads[key] / (np.sqrt(self.h[key]) +1e-7)
# 1e-7 : h[key]에 0이 있는 경우 0으로 나누는 것을 방지. 이 값도 설정 가능
- 최솟값을 향해 효율적으로 움직임
- y축 방향은 기울기가 커서 처음에는 크게 움직이지만, 갱신 정도도 큰 폭으로 작아지도록 조정.
-> y축 방향으로 갱신 강도가 빠르게 약해지고, 지그재그 움직임이 줄어듬
6.1.6 Adam
- 모멘텀과 AdaGrad 기법 융합
- 매개변수 공간 효율적으로 탐색
- 하이퍼파라미터의 편향 보정 진행
- 모멘텀과 비슷한 패턴이지만 모멘텀 때보다 공의 좌우 흔들림이 적음
-> 학습의 갱신 강도를 적응적으로 조정하기 때문
6.1.7 어떤 갱신 방법을 이용할 것인가?
- 풀어야 할 문제가 무엇이냐에 따라 달라짐
- 하이퍼파라미터를 어떻게 설정하느냐에 따라서도 달라짐
- 모든 문제에서 항상 뛰어난 기법이라는 것은 아직 없음
- 일반적으로 SGD보다 다른 세 기법이 빠르게 학습하고, 때로는 최종 정확도도 높게 나타남
6.1.8 MNIST 데이터셋으로 본 갱신 방법 비교
- SGD의 학습 진도가 가장 느림
- 나머지 세 기법의 진도는 비슷, AdaGrad가 제일 빠름
- 하이퍼파라미터인 학습률과 신경마의 구조에 따라 결과 달라짐
6.2 가중치의 초깃값
6.2.1 초깃값을 0으로 하면?
가중치 감소 : 가중치 매개변수의 값이 작아지도록 학습하는 방법
가중치 값을 작게 하여 오버피팅이 일어나지 않게 함
- 가중치를 모두 0으로 하면 학습 제대로 x
- 가중치를 균일한 값으로 설정하면 안됨
오차역전파법에서 모든 가중치의 값이 똑같이 갱신되기 때문
=> 초깃값을 무작위로 설정해야 함
6.2.2 은닉층의 활성화값 분포
- 은닉층의 활성화값의 분포는 중요한 정보
- 가중치의 초깃값에 따라 은닉층 활성화값이 어떻게 변화하는지 실험
- 활성화 함수로 시그모이드 함수를 사용하는 5층 신경망에 무작위로 생성한 입력 데이터 흘림
- 각 층의 활성화값 분포를 히스토그램으로 그림
#은닉층의 활성화값 분포 실험
def sigmoid(x):
return 1/(1+np.exp(-x))
x = np.random.randn(1000, 100) #1000개의 입력 데이터 무작위로 생성
node_num = 100 #각 은닉층의 노드(뉴런) 수
hidden_layer_size = 5 #은닉층 개수
activations = {} #활성화 결과(활성화값) 저장
for i in range(hidden_layer_size):
if i !=0:
x = activations[i-1]
#w = np.random.randn(node_num, node_num)*1 #표준편차가 1인 정규분포 가중치
#w = np.random.randn(node_num, node_num)*0.01 #표준편차가 0.1인 정규분포 가중치
w = np.random.randn(node_num, node_num) / np.sqrt(node_num) #Xavier초깃값
a = np.dot(x, w)
z = sigmoid(a)
activations[i] = z
#히스토그램 그리기
for i, a in activations.items():
plt.subplot(1, len(activations), i+1)
plt.title(str(i+1) + "-layer")
if i != 0: plt.yticks([], [])
# plt.xlim(0.1, 1)
# plt.ylim(0, 7000)
plt.hist(a.flatten(), 30, range=(0,1))
plt.show()
- 표준편차1인 정규분포 가중치 - - 표준편차0.01인 정규분포 가중치 -
- 각 층의 활성화값들이 0과 1에 치우쳐 분포 0.5 부근에 집중
- 그 미분은 0에 다가가기 때문에 역전파의 기울기 값이 점점 작아짐 다수의 뉴런이 거의 같은 값을 출력
- 기울기 소실 문제 표현력 제한
=> 각 층의 활성화값은 고루 분포되어야 함
Xavier 초깃값
- 일반적인 딥러닝 프레임워크들이 표준적으로 이용
- 앞 계층의 노드가 n개라면 표준편차가 1/√n인 분포를 사용
- 넓게 분포되어 있음 -> 표현력 제한받지 않고 학습 효율적으로 가능
- tanh함수를 활성화함수로 사용하면 layer가 깊어질수록 모양 일그러지지 않음
- tanh함수는 원점(0.0)에서 대칭인 s곡선 (sigmoid는 0.05에서 대칭)
- 활성화 함수용으로는 원점에서 대칭인 함수가 바람직하다고 알려져 있음
6.2.3 ReLU를 사용할 때의 가중치 초깃값
- ReLU를 이용할 때는 He 초깃값 이용 권장
- He는 초깃값의 표준편차가 2/√n인 정규분포 사용 (음의 영역은 모두 0이기 때문에 더 넓게 분포시키기 위해)
- He 초깃값일 때만 모든 층에서 균일하게 분포
6.2.4 MNIST 데이터셋으로 본 가중치 초깃값 비교
# 0. MNIST 데이터 읽기==========
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)
train_size = x_train.shape[0]
batch_size = 128
max_iterations = 2000
# 1. 실험용 설정==========
weight_init_types = {'std=0.01': 0.01, 'Xavier': 'sigmoid', 'He': 'relu'}
optimizer = SGD(lr=0.01)
networks = {}
train_loss = {}
for key, weight_type in weight_init_types.items():
networks[key] = MultiLayerNet(input_size=784, hidden_size_list=[100, 100, 100, 100],
output_size=10, weight_init_std=weight_type)
train_loss[key] = []
# 2. 훈련 시작==========
for i in range(max_iterations):
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
for key in weight_init_types.keys():
grads = networks[key].gradient(x_batch, t_batch)
optimizer.update(networks[key].params, grads)
loss = networks[key].loss(x_batch, t_batch)
train_loss[key].append(loss)
if i % 100 == 0:
print("===========" + "iteration:" + str(i) + "===========")
for key in weight_init_types.keys():
loss = networks[key].loss(x_batch, t_batch)
print(key + ":" + str(loss))
# 3. 그래프 그리기==========
markers = {'std=0.01': 'o', 'Xavier': 's', 'He': 'D'}
x = np.arange(max_iterations)
for key in weight_init_types.keys():
plt.plot(x, smooth_curve(train_loss[key]), marker=markers[key], markevery=100, label=key)
plt.xlabel("iterations")
plt.ylabel("loss")
plt.ylim(0, 2.5)
plt.legend()
plt.show()
- 층별 뉴런 수가 100개인 5층 신경망, 활성화 함수로 ReLU사용
- std = 0.01일 때는 학습 전혀 x
- He 학습 진도 가장 빠름
6.3 배치 정규화
- 각 층이 활성화값을 적당히 퍼뜨리도록 강제 -> 배치 정규화 (Batch Normalization)
6.3.1 배치 정규화 알고리즘
: 각 층에서 활성화값이 적당히 분포되도록 조정
- 배치 정규화 계층을 활성화 함수의 앞(혹은 뒤)에 삽입
주목받는 이유
- 학습을 빨리 진행할 수 있다 : 학습 속도 개선
- 초깃값에 크게 의존하지 않음
- 오버피팅을 억제 : 드롭아웃 등의 필요성 감소
- 학습 시 미니배치를 단위로 정규화
- 평균이 0, 분산이 1이 되도록 정규화
- 엡실론 : 작은 값 (10e-7) -> 0으로 나누는 사태 예방
- 배치 정규화 계층마다 이 정규화된 데이터에 고유한 확대(γ, scale)와 이동(β, shift) 변환 수행
- 두 값은 처음에 각각 1, 0 으로 시작
- 학습하면서 적합한 값으로 조정
- 이유: 데이터를 계속 정규화 하게 되면 활성화 함수가 비선형의 역할을 상실하기 때문
- 활성화 결과로 평균이 0, 분산이 1인 값 (95%의 입력값은 x = -1.96 ~ 1.96의 값에 위치,이 때는 sigmoid가 선형)
- xi_hat이 scale과 shift를 거쳐서 sigmoid 함수의 선형이 아닌 부근에 위치하게 되면 활성화 결과가 비선형
6.3.2 배치 정규화의 효과
from common.multi_layer_net_extend import MultiLayerNetExtend
from common.optimizer import SGD, Adam
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)
# 학습 데이터를 줄임
x_train = x_train[:1000]
t_train = t_train[:1000]
max_epochs = 20
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.01
def __train(weight_init_std):
bn_network = MultiLayerNetExtend(input_size=784, hidden_size_list=[100, 100, 100, 100, 100], output_size=10,
weight_init_std=weight_init_std, use_batchnorm=True)
network = MultiLayerNetExtend(input_size=784, hidden_size_list=[100, 100, 100, 100, 100], output_size=10,
weight_init_std=weight_init_std)
optimizer = SGD(lr=learning_rate)
train_acc_list = []
bn_train_acc_list = []
iter_per_epoch = max(train_size / batch_size, 1)
epoch_cnt = 0
for i in range(1000000000):
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
for _network in (bn_network, network):
grads = _network.gradient(x_batch, t_batch)
optimizer.update(_network.params, grads)
if i % iter_per_epoch == 0:
train_acc = network.accuracy(x_train, t_train)
bn_train_acc = bn_network.accuracy(x_train, t_train)
train_acc_list.append(train_acc)
bn_train_acc_list.append(bn_train_acc)
print("epoch:" + str(epoch_cnt) + " | " + str(train_acc) + " - " + str(bn_train_acc))
epoch_cnt += 1
if epoch_cnt >= max_epochs:
break
return train_acc_list, bn_train_acc_list
# 그래프 그리기==========
weight_scale_list = np.logspace(0, -4, num=16)
x = np.arange(max_epochs)
for i, w in enumerate(weight_scale_list):
print( "============== " + str(i+1) + "/16" + " ==============")
train_acc_list, bn_train_acc_list = __train(w)
plt.subplot(4,4,i+1)
plt.title("W:" + str(w))
if i == 15:
plt.plot(x, bn_train_acc_list, label='Batch Normalization', markevery=2)
plt.plot(x, train_acc_list, linestyle = "--", label='Normal(without BatchNorm)', markevery=2)
else:
plt.plot(x, bn_train_acc_list, markevery=2)
plt.plot(x, train_acc_list, linestyle="--", markevery=2)
plt.ylim(0, 1.0)
if i % 4:
plt.yticks([])
else:
plt.ylabel("accuracy")
if i < 12:
plt.xticks([])
else:
plt.xlabel("epochs")
plt.legend(loc='lower right')
plt.show()
=> 가중치 초깃값에 크게 의존하지 않음
=> 거의 모든 경우에서 배치 정규화를 사용할 때 학습 진도가 빠름
6.4 바른 학습을 위해
6.4.1 오버피팅
주로 다음의 두 경우에 일어남
- 매개변수가 많고 표현력이 높은 모델
- 훈련 데이터가 적음
오버피팅 실험
- MNIST데이터셋 훈련 데이터 중 300개만 사용, 7층 네트워크로 복잡성 높임
- 각 층의 뉴런은 100개, 활성화 함수 ReLU
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)
# 학습 데이터를 줄임
x_train = x_train[:300]
t_train = t_train[:300]
#훈련
network = MultiLayerNet(input_size=784, hidden_size_list = [100,100,100,100,100,100], output_size = 10)
optimizer = SGD(lr=0.01) #학습률이 0.01인 SGD로 매개변수 갱신
max_epochs = 201
train_size = x_train.shape[0]
batch_size = 100
train_loss_list = []
train_acc_list = [] #에폭 단위의 정확도 저장
test_acc_list = []
iter_per_epoch = max(train_size/batch_size, 1)
epoch_cnt = 0
for i in range(1000000000):
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
grads = network.gradient(x_batch, t_batch)
optimizer.update(network.params, grads)
if i%iter_per_epoch ==0:
train_acc = network.accuracy(x_train, t_train)
test_acc = network.accuracy(x_test, t_test)
train_acc_list.append(train_acc)
test_acc_list.append(test_acc)
epoch_cnt+=1
if epoch_cnt >= max_epochs:
break
markers = {'train': 'o', 'test': 's'}
x = np.arange(max_epochs)
plt.plot(x, train_acc_list, marker='o', label='train', markevery=10)
plt.plot(x, test_acc_list, marker='s', label='test', markevery=10)
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()
- 훈련 데이터 정확도는 100 에폭을 지나는 무렵부터 거의 100%
- 시험 데이터 정확도와 큰 차이
-> 훈련 데이터에만 적응한 결과
6.4.2 가중치 감소
weight decay: 학습 과정에서 큰 가중치에 대해서는 그에 상응하는 큰 페널티를 부과하여 오버피팅을 억제하는 방법
- 손실함수에 L2 norm (1/2 * λ * W^2)를 더함
- λ 람다는 정규화의 세기를 조절하는 하이퍼파라미터
-> 훈련 데이터와 시험 데이터에 대한 정확도 차이 줄음 => 오버피팅 억제
-> 훈련 데이터에 대한 정확도가 100%에 도달하지 않음
6.4.3 드롭아웃
: 뉴런을 임의로 삭제하면서 학습하는 방법
- 훈련 때는 데이터를 흘릴 때마다 삭제할 뉴런을 무작위로 선택
- 시험 때는 모든 뉴런에 신호를 전달
- 시험 때는 각 뉴런의 출력에 훈련 때 삭제 안 한 비율을 곱하여 출력 (생략)
#드롭아웃
class Dropout:
def __init__(self, dropout_ratio = 0.5):
self.dropout_ratio = dropout_ratio
self.mask = None
def forward(self, x, train_flg=True):
if train_flg:
self.mask = np.random.rand(*x.shape) > self.dropout_ratio #x와 형상이 같은 배열을 무작위로 생성, 그 값이 dropout_ration보다 큰 원소만 True
return x*self.mask
else:
return x*(1.0-self.dropout_ratio)
def backward(self, dout):
return dout * self.mask
- 순전파 때 신호를 통과시키는 뉴런은 역전파 때도 신호를 그대로 통과시킴
- 순전파 때 통과시키지 않은 뉴런은 역전파 때도 신호 차단
- forward pass를 할 때마다 dropout되는 노드는 임의로 바뀌기 때문에 학습에 큰 영향을 미치는 노드 이외의 다른 노드들에 대해서도 학습이 더 잘 돼서 overfitting이 줄어듬.
- 훈련 데이터와 시험 데이터에 대한 정확도 차이 줄음
- 훈련 데이터에 대한 정확도 100% 아님
-> 표현력을 높이면서 오버피팅 억제 - 앙상블 학습 효과
- 앙상블 : 개별적으로 학습시킨 여러 모델의 출력을 평균 내어 추론하는 방식
- 드롭아웃 : 학습 때 뉴런을 무작위로 삭제하는 행위를 매번 다른 모델을 학습시키는 것으로 해석
6.5 적절한 하이퍼파라미터 값 찾기
6.5.1 검증 데이터
- 하이퍼파라미터의 성능을 평가할 때는 시험 데이터를 사용하면 안됨
- 하이퍼파라미터 값이 시험 데이터에 오버피팅되기 때문
- 하이퍼파라미터 전용 확인 데이터 필요 -> 검증 데이터 (validation data)
- 훈련 데이터 : 매개변수 학습
- 검증 데이터 : 하이퍼파라미터 성능 평가
- 시험 데이터 : 신경망의 범용 성능 평가
#MNIST 데이터셋에서 검증 데이터 얻기
(x_train, t_train), (x_test, t_test) = load_mnist()
#훈련 데이터 뒤섞기
x_train, t_train = shuffle_dataset(x_train, t_train)
#20%를 검증 데이터로 분할
validation_rate = 0.20
validation_num = int(x_train.shape[0]*validation_rate)
x_val = x_train[:validation_num]
t_val = t_train[:validation_num]
x_train = x_train[validation_num:]
t_train = x_train[validation_num:]
6.5.2 하이퍼파라미터 최적화
: 하이퍼파라미터의 '최적 값'이 존재하는 범위를 조금씩 줄여나감
0단계 : 대략적인 범위 설정 (로그 스케일로 지정, ex) 0.001에서 1000사이)
1단계 : 무작위로 하이퍼파라미터 값을 샘플링(추출)
2단계 : 그 값으로 정확도 평가 (에폭은 작게 설정-1회 평가에 걸리는 시간 단축 위해)
3단계 : 정확도 결과로 범위 좁히기, 반복
6.5.2 하이퍼파라미터 최적화 구현하기
#하이퍼파라미터 최적화 구현
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)
# 결과를 빠르게 얻기 위해 훈련 데이터를 줄임
x_train = x_train[:500]
t_train = t_train[:500]
# 20%를 검증 데이터로 분할
validation_rate = 0.20
validation_num = int(x_train.shape[0] * validation_rate)
x_train, t_train = shuffle_dataset(x_train, t_train)
x_val = x_train[:validation_num]
t_val = t_train[:validation_num]
x_train = x_train[validation_num:]
t_train = t_train[validation_num:]
def __train(lr, weight_decay, epocs=50):
network = MultiLayerNet(input_size=784, hidden_size_list=[100, 100, 100, 100, 100, 100],
output_size=10, weight_decay_lambda=weight_decay)
trainer = Trainer(network, x_train, t_train, x_val, t_val,
epochs=epocs, mini_batch_size=100,
optimizer='sgd', optimizer_param={'lr': lr}, verbose=False)
trainer.train()
return trainer.test_acc_list, trainer.train_acc_list
# 하이퍼파라미터 무작위 탐색======================================
optimization_trial = 100
results_val = {}
results_train = {}
for _ in range(optimization_trial):
# 탐색할 하이퍼파라미터의 범위 지정===============
weight_decay = 10 ** np.random.uniform(-8, -4) #가중치 감소 세기 계수, 범위(10^-8 ~10^-4)
lr = 10 ** np.random.uniform(-6, -2) #학습률, 범위(10^-6~10^-2)
# ================================================
val_acc_list, train_acc_list = __train(lr, weight_decay)
print("val acc:" + str(val_acc_list[-1]) + " | lr:" + str(lr) + ", weight decay:" + str(weight_decay))
key = "lr:" + str(lr) + ", weight decay:" + str(weight_decay)
results_val[key] = val_acc_list
results_train[key] = train_acc_list
# 그래프 그리기========================================================
print("=========== Hyper-Parameter Optimization Result ===========")
graph_draw_num = 20
col_num = 5
row_num = int(np.ceil(graph_draw_num / col_num))
i = 0
for key, val_acc_list in sorted(results_val.items(), key=lambda x:x[1][-1], reverse=True):
print("Best-" + str(i+1) + "(val acc:" + str(val_acc_list[-1]) + ") | " + key)
plt.subplot(row_num, col_num, i+1)
plt.title("Best-" + str(i+1))
plt.ylim(0.0, 1.0)
if i % 5: plt.yticks([])
plt.xticks([])
x = np.arange(len(val_acc_list))
plt.plot(x, val_acc_list)
plt.plot(x, results_train[key], "--")
i += 1
if i >= graph_draw_num:
break
plt.show()
- 하이퍼파라미터 검증 범위 0.001~1000 사이에서 무작위 추출 : 10**np.random.uniform(-3,3)
- 검증 데이터의 학습 추이를 정확도가 높은 순서로 나열
- Best-5정도까지 학습이 순조로움
- Best-1(val acc:0.78) | lr:0.009976648137882835, weight decay:2.8454240859987083e-07
- Best-2(val acc:0.73) | lr:0.006884034990967694, weight decay:1.1844772320662975e-06
- Best-3(val acc:0.71) | lr:0.005829457100402598, weight decay:3.3344298206917275e-07
- Best-4(val acc:0.7) | lr:0.00535950774058873, weight decay:1.505493479471236e-06
- Best-5(val acc:0.65) | lr:0.0045251758231664545, weight decay:3.4950414167758566e-08
-> 학습이 잘 진행될 때의 범위를 관찰하고 좁혀나감 -> 반복 -> 특정 단계에서 최종 하이퍼파라미터 값 하나 선택
6.6 정리
- 매개변수 갱신 방법에는 확률적 경사 하강법(SGD) 외에도 모멘텀, AdaGrad, Adam 등이 있다.
- 가중치 초깃값을 정하는 방법은 올바른 학습을 하는 데 매우 중요하다.
- Xavier 초깃값과 He 초깃값(ReLu함수)이 효과적
- 배치 정규화를 이용하면 학습을 빠르게 진행할 수 있으며, 초깃값에 영향을 덜 받게 됨
- 오버피팅을 억제하는 정규화 기술로는 가중치 감소와 드롭아웃이 있다.
- 하이퍼파라미터 값 탐색은 최적 값이 존재할 법한 범위를 점차 좁히면서 하는 것이 효과적
책 참고 : 밑바닥부터 시작하는 딥러닝 (한빛미디어)
'딥러닝 > 밑바닥부터 시작하는 딥러닝' 카테고리의 다른 글
8장 : 딥러닝 (0) | 2023.09.19 |
---|---|
7장 : 합성곱 신경망(CNN) (0) | 2023.09.17 |
5장 : 오차역전파법 (0) | 2023.09.13 |
4장 : 신경망 학습 (0) | 2023.09.06 |
3장 : 신경망 (0) | 2023.09.05 |