Congelar o modelo e treiná-lo

Sep 17 2020

Estou usando o Keras Tensorflow no Colab. Eu ajusto um modelo e o salvo. Então eu carrego e verifico o desempenho e é claro que deve ser o mesmo. Então eu congelo e coloco novamente. Eu esperaria que depois o modelo tivesse o mesmo desempenho. É claro que durante o "treinamento", devido às diferenças de tamanho do lote, pode haver diferenças na precisão. Mas depois ao verificar com model.evaluate não esperaria diferenças, pois os pesos não podem ser alterados, pois o modelo estava congelado. No entanto, esse não é o caso.

Meu código:

import csv
import tensorflow as tf
import tensorflow_datasets as tfds
import numpy as np
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences

(train_x, train_labels), (test_x, test_labels) = tf.keras.datasets.imdb.load_data(num_words=10000)

x_train_padded = pad_sequences(train_x, maxlen=500)
x_test_padded = pad_sequences(test_x, maxlen=500)

model = tf.keras.Sequential([
    tf.keras.layers.Embedding(10000, 128, input_length=500),
    tf.keras.layers.Conv1D(128, 5, activation='relu'),
    tf.keras.layers.GlobalAveragePooling1D(),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(1)
])

model.compile(loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),optimizer='adam', metrics=[tf.metrics.BinaryAccuracy(threshold=0.0, name='accuracy')])

history = model.fit(x=x_train_padded,
                      y=train_labels,
                      validation_data=(x_test_padded , test_labels),
                      epochs=4, batch_size=128)

dá a saída:

Eu salvo o modelo:

model.save('test.h5')

e carregue-o de volta:

modelloaded=tf.keras.models.load_model('test.h5')

e verifique o desempenho:

modelloaded.evaluate(x_test_padded , test_labels)

claro que ainda o mesmo:

Agora eu defino o modelo como não treinável:

modelloaded.trainable=False

e realmente:

modelloaded.summary()

mostra que todos os parâmetros não são treináveis:

Agora eu ajustei novamente, usando apenas uma época:

history = modelloaded.fit(x=x_train_padded,
                      y=train_labels,
                      validation_data=(x_test_padded , test_labels),
                      epochs=1, batch_size=128)

Eu entendo que embora os pesos não sejam treináveis, a precisão muda, pois isso depende do tamanho do lote.

No entanto, quando eu verifico o modelo posteriormente com:

modelloaded.evaluate(x_test_padded , test_labels)

Eu posso ver que o modelo foi alterado? A perda e a precisão são diferentes. Não entendo por que, esperava os mesmos números. Como o modelo não pode ser treinado. Não importa se eu o chamo com tamanhos de lote diferentes:

modelloaded.evaluate(x_test_padded , test_labels, batch_size=16)

Os números são sempre iguais, porém diferentes daqueles anteriores ao ajuste do modelo.

Editar:

Tentei o seguinte:

modelloaded=tf.keras.models.load_model('test.h5')
modelloaded.trainable=False

for layer in modelloaded.layers:
  layer.trainable=False

history = modelloaded.fit(x=x_train_padded,
                          y=train_labels,
                          validation_data=(x_test_padded , test_labels),
                          epochs=1, batch_size=128)

modelloaded.evaluate(x_test_padded, test_labels)

No entanto, ainda assim, os pesos são ajustados (eu verifiquei isso comparando print(modelloaded.trainable_variables)antes e depois) e a saída de modelloaded.evaluate fornece resultados ligeiramente diferentes, onde eu não esperaria nenhuma mudança. Como os pesos do modelo não deveriam ter mudado. Mas eles fizeram, como posso ver ao verificar print(modelloaded.trainable_variables).

Respostas

YannickFunk Sep 17 2020 at 03:41

Este parece ser um problema maior que é discutido aqui . Definir todas as camadas explicitamente não treináveis ​​deve funcionar:

for layer in modelloaded.layers:
        layer.trainable = False
BertHobe Sep 18 2020 at 15:23

Meu erro foi não compilar o modelo novamente depois de defini-lo como não treinável.

dtlam26 Sep 18 2020 at 15:32

Você tem que compilar o modelo antes de ajustá-lo novamente, ou a função de ajuste levará sua última configuração de compilação ...