Keras의 배치 정규화 계층은 PlatoBlockchain Data Intelligence가 손상되었습니다. 수직 검색. 일체 포함.

Keras의 배치 정규화 계층이 손상되었습니다.

업데이트 : 불행히도 일괄 정규화 레이어의 동작을 변경 한 Keras에 대한 Pull-Request가 허용되지 않았습니다. 자세한 내용을 읽을 수 있습니다 여기에서 지금 확인해 보세요.. 커스텀 구현을 망칠 정도로 용감한 사람들을 위해 코드를 찾을 수 있습니다. 내 지점. 그것을 유지하고 최신 안정 버전의 Keras와 병합 할 수 있습니다 (2.1.6, 2.2.22.2.4) 사용하지만 약속은 없습니다.

딥 러닝에서 일하는 대부분의 사람들은 케 라스. 그렇지 않은 사람들에게는 TensorFlow, Theano 및 CNTK와 같은 기본 딥 러닝 프레임 워크를 추상화하고 A를 제공하는 훌륭한 라이브러리입니다 고급 API ANN 훈련을 위해. 사용하기 쉽고 빠른 프로토 타이핑이 가능하며 친절한 활동적인 커뮤니티가 있습니다. 나는 그것을 많이 사용하고 꽤 오랫동안 프로젝트에 기여했으며 딥 러닝에 종사하고 싶은 사람에게 그것을 추천합니다.

Keras가 내 인생을 더 쉽게 만들었음에도 불구하고 Batch Normalization 레이어의 이상한 동작으로 인해 여러 번 물 렸습니다. 기본 동작은 시간이 지남에 따라 변경되었지만 여전히 많은 사용자에게 문제를 일으키고 결과적으로 몇 가지 관련이 있습니다. 미결 문제 Github에서. 이 블로그 게시물에서 Keras의 BatchNormalization 레이어가 Transfer Learning에서 잘 작동하지 않는 이유를 작성하려고합니다. 문제를 해결하는 코드를 제공하고 결과에 대한 예제를 제공합니다. 패치.

아래 하위 섹션에서는 딥 러닝에서 전송 학습이 사용되는 방법, 배치 정규화 계층, 학습 단계의 작동 방식 및 Keras가 시간이 지남에 따라 BN 동작을 변경 한 방법에 대해 소개합니다. 이미 알고 있다면 섹션 2로 바로 넘어갈 수 있습니다.

1.1 딥 러닝에는 전이 학습 사용이 중요합니다.

과거에 딥 러닝이 비판 된 이유 중 하나는 너무 많은 데이터가 필요하기 때문입니다. 항상 그런 것은 아닙니다. 이 한계를 해결하기위한 몇 가지 기술이 있으며 그 중 하나는 전이 학습입니다.

Computer Vision 응용 프로그램에서 작업 중이고 Cats and Dogs를 구별하는 분류기를 작성하려고한다고 가정하십시오. 실제로 모델을 훈련시키기 위해 수백만 개의 고양이 / 개 이미지가 필요하지 않습니다. 대신 사전 훈련 된 분류기를 사용하고 적은 데이터로 상위 컨볼 루션을 미세 조정할 수 있습니다. 사전 훈련 된 모델이 이미지에 적합했기 때문에 하단 컨볼 루션은 선, 가장자리 및 기타 유용한 패턴과 같은 기능을 인식하여 가중치를 우수한 초기화 값으로 사용하거나 데이터로 네트워크를 부분적으로 재교육 할 수 있음을 의미합니다 .
Keras의 배치 정규화 계층은 PlatoBlockchain Data Intelligence가 손상되었습니다. 수직 검색. 일체 포함.
Keras는 사전 훈련 된 여러 모델과 모델 미세 조정 방법에 대한 사용하기 쉬운 예제를 제공합니다. 자세한 내용은 선적 서류 비치.

1.2 배치 정규화 계층이란 무엇입니까?

Batch Normalization 레이어는 2014 년 Ioffe와 Szegedy에 의해 도입되었습니다. 이전 레이어의 출력을 표준화하여 소실 그라디언트 문제를 해결하고 필요한 반복 횟수를 줄여 훈련 속도를 높이고 더 깊은 신경망 훈련을 가능하게합니다. 그것이 어떻게 작동하는지 정확하게 설명하는 것은이 게시물의 범위를 벗어나지 만 원본 종이. 지나치게 단순화 된 설명은 입력의 평균을 빼고 표준 편차로 나누어 입력의 크기를 조정한다는 것입니다. 필요한 경우 변환을 취소하는 방법도 배울 수 있습니다.
Keras의 배치 정규화 계층은 PlatoBlockchain Data Intelligence가 손상되었습니다. 수직 검색. 일체 포함.

1.3 Keras의 learning_phase는 무엇입니까?

일부 레이어는 훈련 및 추론 모드에서 다르게 작동합니다. 가장 눈에 띄는 예로는 배치 정규화 및 드롭 아웃 레이어가 있습니다. BN의 경우 훈련 과정에서 미니 배치의 평균과 분산을 사용하여 입력을 다시 조정합니다. 반면 추론 중에는 훈련 중에 추정 된 이동 평균과 분산을 사용합니다.

Keras는 내장 된 메커니즘이 있기 때문에 실행할 모드를 알고 있습니다. 학습 _ 단계. 학습 단계는 네트워크가 훈련 모드인지 테스트 모드인지를 제어합니다. 사용자가 수동으로 설정하지 않은 경우 fit () 동안 네트워크는 learning_phase = 1 (train mode)로 실행됩니다. 예측을 생성하는 동안 (예를 들어 우리가 predict () 및 eva () 메서드를 호출 할 때 또는 fit ()의 유효성 검사 단계에서) 네트워크는 learning_phase = 0 (테스트 모드)으로 실행됩니다. 권장되지는 않지만 사용자가 learning_phase를 특정 값으로 정적으로 변경할 수도 있지만 이는 그래프에 모델이나 텐서를 추가하기 전에 발생해야합니다. learning_phase가 정적으로 설정되면 Keras는 사용자가 선택한 모드로 잠 깁니다.

1.4 Keras는 시간이 지남에 따라 배치 정규화를 어떻게 구현 했습니까?

Keras는 배치 정규화의 동작을 여러 번 변경했지만 가장 최근의 중요한 업데이트는 Keras 2.1.3에서 발생했습니다. v2.1.3 이전에 BN 레이어가 고정되었을 때 (트레이닝 가능 = False) 배치 통계를 계속 업데이트하여 사용자에게 엄청난 두통을 일으켰습니다.

이것은 단지 이상한 정책이 아니라 실제로 잘못되었습니다. 컨볼 루션 사이에 BN 레이어가 있다고 상상해보십시오. 레이어가 고정되어 있으면 변경이 발생하지 않습니다. 가중치를 부분적으로 업데이트하고 다음 레이어도 동결되면 미니 배치 통계의 업데이트에 조정할 기회를 얻지 못해 오류가 더 커집니다. 고맙게도 버전 2.1.3부터 ​​BN 레이어가 고정되면 더 이상 통계가 업데이트되지 않습니다. 그러나 이것으로 충분합니까? Transfer Learning을 사용하는 경우는 아닙니다.

아래에서는 문제가 무엇인지 정확하게 설명하고 문제를 해결하기위한 기술적 구현을 ​​스케치합니다. 또한 전후의 모델 정확도에 미치는 영향을 보여주는 몇 가지 예를 제공합니다. 패치 적용됩니다.

2.1 문제에 대한 기술적 설명

Keras의 현재 구현의 문제점은 BN 레이어가 고정 될 때 훈련 중에 미니 배치 통계를 계속 사용한다는 것입니다. 나는 BN이 얼어 붙었을 때 더 나은 접근법은 훈련 중에 배운 이동 평균과 분산을 사용하는 것이라고 생각합니다. 왜? 레이어가 고정 될 때 미니 배치 통계가 업데이트되지 않아야하는 것과 같은 이유로 다음 레이어가 제대로 훈련되지 않아 결과가 나빠질 수 있습니다.

Computer Vision 모델을 구축하고 있지만 데이터가 충분하지 않다고 가정하면 사전 훈련 된 Keras CNN 중 하나를 사용하여 미세 조정하기로 결정합니다. 불행히도 그렇게하면 BN 레이어 내에서 새 데이터 세트의 평균 및 분산이 원래 데이터 세트의 평균 및 분산과 유사하다는 보장이 없습니다. 현재 교육 과정에서 네트워크는 항상 BN 레이어가 고정되어 있는지 여부에 관계없이 미니 배치 통계를 사용합니다. 또한 추론 중에는 이전에 학습 한 고정 BN 레이어 통계를 사용합니다. 결과적으로 상단 레이어를 미세 조정하면 가중치가 평균 레이어 / 평균에 맞게 조정됩니다. 데이터 세트. 그럼에도 불구하고 추론하는 동안 규모가 조정 된 데이터를받습니다. 다르게 의 평균 / 분산이 실물 데이터 세트가 사용됩니다.
Keras의 배치 정규화 계층은 PlatoBlockchain Data Intelligence가 손상되었습니다. 수직 검색. 일체 포함.
위의 데모 목적으로 단순하고 비현실적인 아키텍처를 제공합니다. Convolution k + 1에서 네트워크 상단까지 (오른쪽)까지 모델을 미세 조정하고 하단 (왼쪽)을 고정 상태로 유지한다고 가정합니다. 훈련하는 동안 1에서 k까지의 모든 BN 레이어는 훈련 데이터의 평균 / 분산을 사용합니다. 각 BN의 평균과 분산이 사전 훈련 과정에서 배운 것과 유사하지 않으면 냉동 ReLU에 부정적인 영향을 미칩니다. 또한 나머지 네트워크 (CONV k + 1 이상)는 추론 중에 수신되는 것과 비교하여 다른 스케일을 가진 입력으로 훈련됩니다. 훈련하는 동안 네트워크가 이러한 변화에 적응할 수 있지만, 예측 모드로 전환하는 순간 Keras는 다른 표준화 통계를 사용하여 다음 계층의 입력을 신속하게 분배하여 결과가 좋지 않습니다.

2.2 영향을 받는지 어떻게 알 수 있습니까?

이를 감지하는 한 가지 방법은 Keras의 학습 단계를 정적으로 1 (트레인 모드) 및 0 (테스트 모드)으로 설정하고 각 경우에 모델을 평가하는 것입니다. 동일한 데이터 세트에서 정확도에 큰 차이가있는 경우 문제의 영향을받습니다. learning_phase 메커니즘이 Keras에서 구현되는 방식으로 인해 일반적으로 엉망이되지 않는 것이 좋습니다. learning_phase의 변경 사항은 이미 컴파일되어 사용 된 모델에는 영향을 미치지 않습니다. 다음 하위 섹션의 예제에서 볼 수 있듯이이를 수행하는 가장 좋은 방법은 그래프에서 텐서가 정의되기 전에 클린 세션으로 시작하고 learning_phase를 변경하는 것입니다.

이진 분류기로 작업하는 동안 문제를 감지하는 또 다른 방법은 정확도와 AUC를 확인하는 것입니다. 정확도가 50 %에 가깝지만 AUC가 1에 가까우면 (동일한 데이터 세트에서 기차 / 테스트 모드 간 차이가 관찰되는 경우) BN 통계로 인해 확률이 범위를 벗어난 것일 수 있습니다. 마찬가지로 회귀 분석을 위해 MSE와 Spearman의 상관 관계를 사용하여이를 탐지 할 수 있습니다.

2.3 어떻게 고칠 수 있습니까?

얼어 붙은 BN 레이어가 실제로 그렇게하면 문제가 해결 될 수 있다고 생각합니다. 테스트 모드에서 영구적으로 잠겨 있습니다. 구현 측면에서 학습 가능한 플래그는 계산 그래프의 일부 여야하고 BN의 동작은 learning_phase뿐만 아니라 학습 가능한 속성의 값에도 의존해야합니다. 당신은 내 구현의 세부 사항을 찾을 수 있습니다 깃허브.

위 수정을 적용하면 BN 레이어가 고정되면 더 이상 미니 배치 통계를 사용하지 않고 대신 훈련 중에 배운 것을 사용합니다. 결과적으로 훈련 모드와 테스트 모드간에 차이가 없어 정확도가 향상됩니다. 분명히 BN 레이어가 고정되지 않은 경우 훈련 중에 미니 배치 통계를 계속 사용합니다.

2.4 패치의 영향 평가

최근에 위의 구현을 작성했지만 그 배경에 대한 아이디어는 동일한 효과를 갖는 다양한 해결 방법을 사용하여 실제 문제에 대해 철저히 테스트되었습니다. 예를 들어, 훈련 모드와 테스트 모드의 불일치는 네트워크를 두 부분으로 분리하고 (냉동 및 고정 해제) 캐시 된 훈련을 수행하여 (동결 된 모델을 통해 데이터를 한 번 전달한 후 고정 된 네트워크를 교육하기 위해 사용) 방지 할 수 있습니다. 그럼에도 불구하고,“이전에 해본 신뢰”는 일반적으로 중요하지 않으므로 아래에서는 실제로 새로운 구현의 영향을 보여주는 몇 가지 예를 제공합니다.

실험에 대한 몇 가지 중요한 사항은 다음과 같습니다.

  1. 의도적으로 모델을 과적 합하기 위해 소량의 데이터를 사용하고 동일한 데이터 세트에서 모델을 훈련하고 검증 할 것입니다. 그렇게함으로써 기차 / 검증 데이터 세트에서 거의 완벽한 정확도와 동일한 성능을 기대합니다.
  2. 유효성 검사 중에 동일한 데이터 세트에서 정확도가 현저히 떨어지면 현재 BN 정책이 추론 중 모델의 성능에 부정적인 영향을 미침을 분명히 알 수 있습니다.
  3. 모든 사전 처리는 Generators 외부에서 수행됩니다. 이것은 v2.1.5에 도입 된 버그를 해결하기 위해 수행됩니다 (현재 v2.1.6 및 최신 마스터에서 수정되었습니다).
  4. 우리는 Keras가 평가하는 동안 다른 학습 단계를 사용하도록 강요 할 것입니다. 보고 된 정확도의 차이를 발견하면 현재 BN 정책의 영향을받습니다.

실험 코드는 다음과 같습니다.

import numpy as np
from keras.datasets import cifar10
from scipy.misc import imresize

from keras.preprocessing.image import ImageDataGenerator
from keras.applications.resnet50 import ResNet50, preprocess_input
from keras.models import Model, load_model
from keras.layers import Dense, Flatten
from keras import backend as K


seed = 42
epochs = 10
records_per_class = 100

# We take only 2 classes from CIFAR10 and a very small sample to intentionally overfit the model.
# We will also use the same data for train/test and expect that Keras will give the same accuracy.
(x, y), _ = cifar10.load_data()

def filter_resize(category):
   # We do the preprocessing here instead in the Generator to get around a bug on Keras 2.1.5.
   return [preprocess_input(imresize(img, (224,224)).astype('float')) for img in x[y.flatten()==category][:records_per_class]]

x = np.stack(filter_resize(3)+filter_resize(5))
records_per_class = x.shape[0] // 2
y = np.array([[1,0]]*records_per_class + [[0,1]]*records_per_class)


# We will use a pre-trained model and finetune the top layers.
np.random.seed(seed)
base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
l = Flatten()(base_model.output)
predictions = Dense(2, activation='softmax')(l)
model = Model(inputs=base_model.input, outputs=predictions)

for layer in model.layers[:140]:
   layer.trainable = False

for layer in model.layers[140:]:
   layer.trainable = True

model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit_generator(ImageDataGenerator().flow(x, y, seed=42), epochs=epochs, validation_data=ImageDataGenerator().flow(x, y, seed=42))

# Store the model on disk
model.save('tmp.h5')


# In every test we will clear the session and reload the model to force Learning_Phase values to change.
print('DYNAMIC LEARNING_PHASE')
K.clear_session()
model = load_model('tmp.h5')
# This accuracy should match exactly the one of the validation set on the last iteration.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))


print('STATIC LEARNING_PHASE = 0')
K.clear_session()
K.set_learning_phase(0)
model = load_model('tmp.h5')
# Again the accuracy should match the above.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))


print('STATIC LEARNING_PHASE = 1')
K.clear_session()
K.set_learning_phase(1)
model = load_model('tmp.h5')
# The accuracy will be close to the one of the training set on the last iteration.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))

Keras v2.1.5의 결과를 확인하십시오.

Epoch 1/10
1/7 [===>..........................] - ETA: 25s - loss: 0.8751 - acc: 0.5312
2/7 [=======>......................] - ETA: 11s - loss: 0.8594 - acc: 0.4531
3/7 [===========>..................] - ETA: 7s - loss: 0.8398 - acc: 0.4688 
4/7 [================>.............] - ETA: 4s - loss: 0.8467 - acc: 0.4844
5/7 [====================>.........] - ETA: 2s - loss: 0.7904 - acc: 0.5437
6/7 [========================>.....] - ETA: 1s - loss: 0.7593 - acc: 0.5625
7/7 [==============================] - 12s 2s/step - loss: 0.7536 - acc: 0.5744 - val_loss: 0.6526 - val_acc: 0.6650

Epoch 2/10
1/7 [===>..........................] - ETA: 4s - loss: 0.3881 - acc: 0.8125
2/7 [=======>......................] - ETA: 3s - loss: 0.3945 - acc: 0.7812
3/7 [===========>..................] - ETA: 2s - loss: 0.3956 - acc: 0.8229
4/7 [================>.............] - ETA: 1s - loss: 0.4223 - acc: 0.8047
5/7 [====================>.........] - ETA: 1s - loss: 0.4483 - acc: 0.7812
6/7 [========================>.....] - ETA: 0s - loss: 0.4325 - acc: 0.7917
7/7 [==============================] - 8s 1s/step - loss: 0.4095 - acc: 0.8089 - val_loss: 0.4722 - val_acc: 0.7700

Epoch 3/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2246 - acc: 0.9375
2/7 [=======>......................] - ETA: 3s - loss: 0.2167 - acc: 0.9375
3/7 [===========>..................] - ETA: 2s - loss: 0.2260 - acc: 0.9479
4/7 [================>.............] - ETA: 2s - loss: 0.2179 - acc: 0.9375
5/7 [====================>.........] - ETA: 1s - loss: 0.2356 - acc: 0.9313
6/7 [========================>.....] - ETA: 0s - loss: 0.2392 - acc: 0.9427
7/7 [==============================] - 8s 1s/step - loss: 0.2288 - acc: 0.9456 - val_loss: 0.4282 - val_acc: 0.7800

Epoch 4/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2183 - acc: 0.9688
2/7 [=======>......................] - ETA: 3s - loss: 0.1899 - acc: 0.9844
3/7 [===========>..................] - ETA: 2s - loss: 0.1887 - acc: 0.9792
4/7 [================>.............] - ETA: 1s - loss: 0.1995 - acc: 0.9531
5/7 [====================>.........] - ETA: 1s - loss: 0.1932 - acc: 0.9625
6/7 [========================>.....] - ETA: 0s - loss: 0.1819 - acc: 0.9688
7/7 [==============================] - 8s 1s/step - loss: 0.1743 - acc: 0.9747 - val_loss: 0.3778 - val_acc: 0.8400

Epoch 5/10
1/7 [===>..........................] - ETA: 3s - loss: 0.0973 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0828 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0851 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0897 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0928 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0936 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.1337 - acc: 0.9838 - val_loss: 0.3916 - val_acc: 0.8100

Epoch 6/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0747 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0852 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0812 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0831 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0779 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0766 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.0813 - acc: 1.0000 - val_loss: 0.3637 - val_acc: 0.8550

Epoch 7/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2478 - acc: 0.8750
2/7 [=======>......................] - ETA: 2s - loss: 0.1966 - acc: 0.9375
3/7 [===========>..................] - ETA: 2s - loss: 0.1528 - acc: 0.9583
4/7 [================>.............] - ETA: 1s - loss: 0.1300 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.1193 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.1196 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.1084 - acc: 0.9838 - val_loss: 0.3546 - val_acc: 0.8600

Epoch 8/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0539 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0900 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0815 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0740 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0700 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0701 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.0695 - acc: 1.0000 - val_loss: 0.3269 - val_acc: 0.8600

Epoch 9/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0306 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0377 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0898 - acc: 0.9583
4/7 [================>.............] - ETA: 1s - loss: 0.0773 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.0742 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.0708 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.0659 - acc: 0.9838 - val_loss: 0.3604 - val_acc: 0.8600

Epoch 10/10
1/7 [===>..........................] - ETA: 3s - loss: 0.0354 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0381 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0354 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0828 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.0791 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.0794 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.0704 - acc: 0.9838 - val_loss: 0.3615 - val_acc: 0.8600

DYNAMIC LEARNING_PHASE
[0.3614931714534759, 0.86]

STATIC LEARNING_PHASE = 0
[0.3614931714534759, 0.86]

STATIC LEARNING_PHASE = 1
[0.025861846953630446, 1.0]

위에서 볼 수 있듯이 훈련하는 동안 모델은 데이터를 매우 잘 학습하고 훈련 세트에서 거의 완벽한 정확도를 달성합니다. 반복이 끝날 때마다 동일한 데이터 세트에서 모델을 평가하는 동안 손실과 정확도에 큰 차이가 있습니다. 우리는 이것을 얻지 않아야합니다. 우리는 의도적으로 특정 데이터 세트에 대한 모델을 과적 합했으며 훈련 / 검증 데이터 세트는 동일합니다.

훈련이 완료된 후 3 가지 learning_phase 구성 (동적, 정적 = 0 (테스트 모드) 및 정적 = 1 (훈련 모드))을 사용하여 모델을 평가합니다. 우리가 볼 수 있듯이 처음 두 구성은 손실 및 정확도 측면에서 동일한 결과를 제공하며 그 값은 마지막 반복에서 검증 세트에보고 된 모델의 정확도와 일치합니다. 그럼에도 불구하고 일단 트레이닝 모드로 전환하면 엄청난 차이 (개선)가 관찰됩니다. 왜 그럴까요? 앞서 말했듯이 네트워크의 가중치는 훈련 데이터의 평균 / 분산으로 스케일링 된 데이터를 수신 할 것으로 예상하여 조정됩니다. 불행히도 이러한 통계는 BN 계층에 저장된 통계와 다릅니다. BN 레이어가 고정 되었기 때문에 이러한 통계는 업데이트되지 않았습니다. BN 통계 값 간의 이러한 불일치는 추론 중 정확도 저하로 이어집니다.

일단 적용하면 어떻게되는지 보자 패치:

Epoch 1/10
1/7 [===>..........................] - ETA: 26s - loss: 0.9992 - acc: 0.4375
2/7 [=======>......................] - ETA: 12s - loss: 1.0534 - acc: 0.4375
3/7 [===========>..................] - ETA: 7s - loss: 1.0592 - acc: 0.4479 
4/7 [================>.............] - ETA: 4s - loss: 0.9618 - acc: 0.5000
5/7 [====================>.........] - ETA: 2s - loss: 0.8933 - acc: 0.5250
6/7 [========================>.....] - ETA: 1s - loss: 0.8638 - acc: 0.5417
7/7 [==============================] - 13s 2s/step - loss: 0.8357 - acc: 0.5570 - val_loss: 0.2414 - val_acc: 0.9450

Epoch 2/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2331 - acc: 0.9688
2/7 [=======>......................] - ETA: 2s - loss: 0.3308 - acc: 0.8594
3/7 [===========>..................] - ETA: 2s - loss: 0.3986 - acc: 0.8125
4/7 [================>.............] - ETA: 1s - loss: 0.3721 - acc: 0.8281
5/7 [====================>.........] - ETA: 1s - loss: 0.3449 - acc: 0.8438
6/7 [========================>.....] - ETA: 0s - loss: 0.3168 - acc: 0.8646
7/7 [==============================] - 9s 1s/step - loss: 0.3165 - acc: 0.8633 - val_loss: 0.1167 - val_acc: 0.9950

Epoch 3/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2457 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.2592 - acc: 0.9688
3/7 [===========>..................] - ETA: 2s - loss: 0.2173 - acc: 0.9688
4/7 [================>.............] - ETA: 1s - loss: 0.2122 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.2003 - acc: 0.9688
6/7 [========================>.....] - ETA: 0s - loss: 0.1896 - acc: 0.9740
7/7 [==============================] - 9s 1s/step - loss: 0.1835 - acc: 0.9773 - val_loss: 0.0678 - val_acc: 1.0000

Epoch 4/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2051 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.1652 - acc: 0.9844
3/7 [===========>..................] - ETA: 2s - loss: 0.1423 - acc: 0.9896
4/7 [================>.............] - ETA: 1s - loss: 0.1289 - acc: 0.9922
5/7 [====================>.........] - ETA: 1s - loss: 0.1225 - acc: 0.9938
6/7 [========================>.....] - ETA: 0s - loss: 0.1149 - acc: 0.9948
7/7 [==============================] - 9s 1s/step - loss: 0.1060 - acc: 0.9955 - val_loss: 0.0455 - val_acc: 1.0000

Epoch 5/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0769 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0846 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0797 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0736 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0914 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0858 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0808 - acc: 1.0000 - val_loss: 0.0346 - val_acc: 1.0000

Epoch 6/10
1/7 [===>..........................] - ETA: 1s - loss: 0.1267 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.1039 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0893 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0780 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0758 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0789 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0738 - acc: 1.0000 - val_loss: 0.0248 - val_acc: 1.0000

Epoch 7/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0344 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0385 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0467 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0445 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0446 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0429 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0421 - acc: 1.0000 - val_loss: 0.0202 - val_acc: 1.0000

Epoch 8/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0319 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0300 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0320 - acc: 1.0000
4/7 [================>.............] - ETA: 2s - loss: 0.0307 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0303 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0291 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0358 - acc: 1.0000 - val_loss: 0.0167 - val_acc: 1.0000

Epoch 9/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0246 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0255 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0258 - acc: 1.0000
4/7 [================>.............] - ETA: 2s - loss: 0.0250 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0252 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0260 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0327 - acc: 1.0000 - val_loss: 0.0143 - val_acc: 1.0000

Epoch 10/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0251 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0228 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0217 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0249 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0244 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0239 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0290 - acc: 1.0000 - val_loss: 0.0127 - val_acc: 1.0000

DYNAMIC LEARNING_PHASE
[0.012697912137955427, 1.0]

STATIC LEARNING_PHASE = 0
[0.012697912137955427, 1.0]

STATIC LEARNING_PHASE = 1
[0.01744014158844948, 1.0]

우선, 우리는 네트워크가 상당히 빠르게 수렴하고 완벽한 정확도를 달성한다는 것을 관찰합니다. 또한 다른 learning_phase 값 사이를 전환 할 때 정확도 측면에서 더 이상 불일치가 없음을 알 수 있습니다.

2.5 패치는 실제 데이터 셋에서 어떻게 수행됩니까?

그렇다면 패치가보다 현실적인 실험에서 어떻게 수행됩니까? Keras의 사전 훈련 된 ResNet50 (원래 imagenet에 적합)을 사용하고 최상위 분류 레이어를 제거하고 패치 유무에 관계없이 미세 조정하고 결과를 비교해 봅시다. 데이터의 경우 CIFAR10 (Keras에서 제공하는 표준 기차 / 테스트 분할)을 사용하고 이미지를 224 × 224로 크기 조정하여 ResNet50의 입력 크기와 호환되도록합니다.

RSMprop를 사용하여 최상위 분류 레이어를 학습하기 위해 10 개의 에포크를 수행 한 다음 SGD (lr = 5e-139, momentum = 1)를 사용하여 4 번째 레이어 이후의 모든 것을 미세 조정하기 위해 0.9 개의 에포크를 수행합니다. 패치가 없으면 모델이 87.44 %의 정확도를 달성합니다. 패치를 사용하면 거의 92.36 포인트 높은 5 %의 정확도를 얻을 수 있습니다.

2.6 Dropout과 같은 다른 레이어에도 동일한 수정을 적용해야합니까?

배치 정규화는 트레인과 테스트 모드간에 다르게 작동하는 유일한 레이어가 아닙니다. 드롭 아웃과 그 변형도 동일한 효과를 갖습니다. 이 모든 계층에 동일한 정책을 적용해야합니까? 나는 (나는 이것에 대한 당신의 생각을 듣고 싶지만) 믿지 않습니다. 그 이유는 Dropout이 과적 합을 피하기 위해 사용되기 때문에 훈련 중에 예측 모드에 영구적으로 고정하면 목적이 무효화 될 수 있기 때문입니다. 어떻게 생각해?

나는이 불일치가 Keras에서 해결되어야한다고 믿습니다. 이 문제로 인해 실제 응용 프로그램에서 훨씬 더 심오한 효과 (100 %에서 50 % 정확도까지)를 보았습니다. 나는 보낼 계획 이미 보냈습니다 PR 수정 사항이있는 Keras에게 알려 주시면 감사하겠습니다.

이 블로그 게시물이 마음에 드 셨다면 잠시 시간을내어 Facebook이나 Twitter에서 공유하십시오. 🙂

타임 스탬프 :

더보기 데이텀 박스