machine-learning - tutorial - tensorflow
ResNet: 100% de precisión durante el entrenamiento, pero 33% de precisión de predicción con los mismos datos (2)
Soy nuevo en el aprendizaje automático y el aprendizaje profundo, y con fines de aprendizaje intenté jugar con Resnet. Traté de sobreajustar datos pequeños (3 imágenes diferentes ) y ver si puedo obtener casi 0 pérdidas y 1,0 de precisión, y lo hice.
El problema es que las predicciones en las imágenes de entrenamiento (es decir, las mismas 3 imágenes utilizadas para el entrenamiento) no son correctas.
Imágenes de entrenamiento
Etiquetas de imagen
[1,0,0]
,
[0,1,0]
,
[0,0,1]
Mi código de python
#loading 3 images and resizing them
imgs = np.array([np.array(Image.open("./Images/train/" + fname)
.resize((197, 197), Image.ANTIALIAS)) for fname in
os.listdir("./Images/train/")]).reshape(-1,197,197,1)
# creating labels
y = np.array([[1,0,0],[0,1,0],[0,0,1]])
# create resnet model
model = ResNet50(input_shape=(197, 197,1),classes=3,weights=None)
# compile & fit model
model.compile(loss=''categorical_crossentropy'', optimizer=''adam'',metrics=[''acc''])
model.fit(imgs,y,epochs=5,shuffle=True)
# predict on training data
print(model.predict(imgs))
El modelo sobreajusta los datos:
3/3 [==============================] - 22s - loss: 1.3229 - acc: 0.0000e+00
Epoch 2/5
3/3 [==============================] - 0s - loss: 0.1474 - acc: 1.0000
Epoch 3/5
3/3 [==============================] - 0s - loss: 0.0057 - acc: 1.0000
Epoch 4/5
3/3 [==============================] - 0s - loss: 0.0107 - acc: 1.0000
Epoch 5/5
3/3 [==============================] - 0s - loss: 1.3815e-04 - acc: 1.0000
pero las predicciones son:
[[ 1.05677405e-08 9.99999642e-01 3.95520459e-07]
[ 1.11955103e-08 9.99999642e-01 4.14905685e-07]
[ 1.02637095e-07 9.99997497e-01 2.43751242e-06]]
lo que significa que todas las imágenes tienen
label=[0,1,0]
¿por qué? y como puede suceder eso?
Lo que sucede es básicamente que keras.fit () es decir, su
model.fit()
mientras se tiene el mejor ajuste, se pierde la precisión. Como la precisión se pierde, el ajuste de los modelos da problemas y resultados variados. Keras.fit solo tiene un buen ajuste, no la precisión requerida
Se debe a las capas de normalización por lotes.
En la fase de entrenamiento, el lote se normaliza con su media y varianza. Sin embargo, en la fase de prueba, el lote se normaliza con el promedio móvil de la media y la varianza previamente observadas.
Ahora, este es un problema cuando el número de lotes observados es pequeño (por ejemplo, 5 en su ejemplo) porque en la capa
BatchNormalization
, por defecto,
moving_mean
se inicializa en 0 y
moving_variance
se inicializa en 1.
Dado que el
momentum
predeterminado es 0,99, deberá actualizar los promedios móviles
muchas veces
antes de que converjan en la media y la varianza "real".
Es por eso que la predicción es incorrecta en la etapa inicial, pero es correcta después de 1000 épocas.
Puede verificarlo obligando a las capas de
BatchNormalization
a operar en "modo de entrenamiento".
Durante el entrenamiento, la precisión es 1 y la pérdida es cercana a cero:
model.fit(imgs,y,epochs=5,shuffle=True)
Epoch 1/5
3/3 [==============================] - 19s 6s/step - loss: 1.4624 - acc: 0.3333
Epoch 2/5
3/3 [==============================] - 0s 63ms/step - loss: 0.6051 - acc: 0.6667
Epoch 3/5
3/3 [==============================] - 0s 57ms/step - loss: 0.2168 - acc: 1.0000
Epoch 4/5
3/3 [==============================] - 0s 56ms/step - loss: 1.1921e-07 - acc: 1.0000
Epoch 5/5
3/3 [==============================] - 0s 53ms/step - loss: 1.1921e-07 - acc: 1.0000
Ahora, si evaluamos el modelo, observaremos una alta pérdida y una baja precisión porque después de 5 actualizaciones, los promedios móviles todavía están bastante cerca de los valores iniciales:
model.evaluate(imgs,y)
3/3 [==============================] - 3s 890ms/step
[10.745396614074707, 0.3333333432674408]
Sin embargo, si especificamos manualmente la variable "fase de aprendizaje" y dejamos que las capas de
BatchNormalization
usen la media y la varianza del lote "real", el resultado será el mismo que el observado en
fit()
.
sample_weights = np.ones(3)
learning_phase = 1 # 1 means "training"
ins = [imgs, y, sample_weights, learning_phase]
model.test_function(ins)
[1.192093e-07, 1.0]
También es posible verificarlo cambiando el impulso a un valor menor.
Por ejemplo, al agregar
momentum=0.01
a todas las capas de normas de lote en
ResNet50
, la predicción después de 20 épocas es:
model.predict(imgs)
array([[ 1.00000000e+00, 1.34882026e-08, 3.92139575e-22],
[ 0.00000000e+00, 1.00000000e+00, 0.00000000e+00],
[ 8.70998792e-06, 5.31159838e-10, 9.99991298e-01]], dtype=float32)