Actualmente estoy tratando de obtener la API TF2.0 , pero cuando comparé el GradientTape con un keras regular.Model.fit noté:
Funcionó más lento (probablemente debido a la Ejecución Eager)
Convergente mucho más lento (y no estoy seguro de por qué).
+--------+--------------+--------------+------------------+
| Epoch | GradientTape | GradientTape | keras.Model.fit |
| | | shuffling | |
+--------+--------------+--------------+------------------+
| 1 | 0.905 | 0.918 | 0.8793 |
+--------+--------------+--------------+------------------+
| 2 | 0.352 | 0.634 | 0.2226 |
+--------+--------------+--------------+------------------+
| 3 | 0.285 | 0.518 | 0.1192 |
+--------+--------------+--------------+------------------+
| 4 | 0.282 | 0.458 | 0.1029 |
+--------+--------------+--------------+------------------+
| 5 | 0.275 | 0.421 | 0.0940 |
+--------+--------------+--------------+------------------+
Aquí está el ciclo de entrenamiento que utilicé con GradientTape :
optimizer = keras.optimizers.Adam()
glove_model = GloveModel(vocab_size=len(labels))
train_loss = keras.metrics.Mean(name='train_loss')
@tf.function
def train_step(examples, labels):
with tf.GradientTape() as tape:
predictions = glove_model(examples)
loss = glove_model.glove_loss(labels, predictions)
gradients = tape.gradient(loss, glove_model.trainable_variables)
optimizer.apply_gradients(zip(gradients, glove_model.trainable_variables))
train_loss(loss)
total_step = 0
for epoch in range(epochs_number):
pbar = tqdm(train_ds.enumerate(), total=int(len(index_data) / batch_size) + 1)
for ix, (examples, labels) in pbar:
train_step(examples, labels)
print(f"Epoch {epoch + 1}, Loss {train_loss.result()}")
# Reset the metrics for the next epoch
train_loss.reset_states()
Y aquí está el entrenamiento Keras.Model.fit :
glove_model.compile(optimizer, glove_model.glove_loss)
glove_model.fit(train_ds, epochs=epochs_number)
Aquí está la fuente tf.data.Dataset
train_ds = data.Dataset.from_tensor_slices(
(np.hstack([index_rows.reshape(-1, 1), index_cols.reshape(-1, 1)]), index_data)
).shuffle(100000).batch(batch_size, drop_remainder=True)
Y aquí está el modelo.
class GloveModel(keras.Model):
def __init__(self, vocab_size, dim=100, a=3/4, x_max=100):
super(GloveModel, self).__init__()
self.vocab_size = vocab_size
self.dim = dim
self.a = a
self.x_max = x_max
self.target_embedding = layers.Embedding(
input_dim=self.vocab_size, output_dim=self.dim, input_length=1, name="target_embedding"
)
self.target_bias = layers.Embedding(
input_dim=self.vocab_size, output_dim=1, input_length=1, name="target_bias"
)
self.context_embedding = layers.Embedding(
input_dim=self.vocab_size, output_dim=self.dim, input_length=1, name="context_embedding"
)
self.context_bias = layers.Embedding(
input_dim=self.vocab_size, output_dim=1, input_length=1, name="context_bias"
)
self.dot_product = layers.Dot(axes=-1, name="dot")
self.prediction = layers.Add(name="add")
self.step = 0
def call(self, inputs):
target_ix = inputs[:, 0]
context_ix = inputs[:, 1]
target_embedding = self.target_embedding(target_ix)
target_bias = self.target_bias(target_ix)
context_embedding = self.context_embedding(context_ix)
context_bias = self.context_bias(context_ix)
dot_product = self.dot_product([target_embedding, context_embedding])
prediction = self.prediction([dot_product, target_bias, context_bias])
return prediction
def glove_loss(self, y_true, y_pred):
weight = tf.math.minimum(
tf.math.pow(y_true/self.x_max, self.a), 1.0
)
loss_value = tf.math.reduce_mean(weight * tf.math.pow(y_pred - tf.math.log(y_true), 2.0))
return loss_value
Intenté múltiples configuraciones y optimizadores, pero nada parece cambiar la tasa de convergencia.
python
tensorflow
keras
tensorflow2.0
Benjamin Breton
fuente
fuente
tfds
? Tenga en cuenta que keras por.fit
defecto se baraja antes de cada época. Puede probar desactivando la combinación aleatoria en keras y comparar su tasa de convergencia.Respuestas:
Dataset.shuffle()
solo baraja cada minibatch, por lo que cada época tiene el mismo orden. Keras.fit()
usa algunas magias para barajar todo el conjunto de datos antes de cada época. Para hacer esto en TF, debe usar el conjunto de datos.repeat(epochs_number)
y.shuffle(..., reshuffle_each_iteration=True)
:Esta solución alternativa no es hermosa ni natural, por el momento puede usarla para mezclar cada época. Es un problema conocido y se solucionará, en el futuro puede usarlo en
for epoch in range(epochs_number)
lugar de hacerlo.repeat()
.fuente
El problema vino de la barajado utilizando la tf.Dataset método. Solo barajó el conjunto de datos un cubo a la vez. El uso del Keras.Model.fit arrojó mejores resultados porque probablemente agrega otro barajado.
Agregué un barajado
numpy.random.shuffle
y mejoró el rendimiento con ambos métodos de entrenamiento:La generación del conjunto de datos es ahora:
Y los resultados son:
El tipo de entrenamiento por época es aproximadamente el mismo en 2 minutos por época .
fuente