Ich versuche gerade, die TF2.0- API zu bekommen, aber als ich das GradientTape mit einem normalen keras.Model.fit verglich , bemerkte ich:
Es lief langsamer (wahrscheinlich aufgrund der eifrigen Ausführung)
Es konvergierte viel langsamer (und ich bin mir nicht sicher warum).
+--------+--------------+--------------+------------------+
| 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 |
+--------+--------------+--------------+------------------+
Hier ist die Trainingsschleife, die ich mit dem GradientTape verwendet habe :
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()
Und hier ist das Keras.Model.fit- Training:
glove_model.compile(optimizer, glove_model.glove_loss)
glove_model.fit(train_ds, epochs=epochs_number)
Hier ist die Quelle 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)
Und hier ist das Modell.
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
Ich habe mehrere Konfigurationen und Optimierer ausprobiert, aber nichts scheint die Konvergenzrate zu ändern.
python
tensorflow
keras
tensorflow2.0
Benjamin Breton
quelle
quelle
tfds
? Beachten Sie, dass Keras.fit
standardmäßig vor jeder Epoche gemischt werden. Sie können testen, indem Sie das Mischen in Keras deaktivieren und deren Konvergenzrate vergleichen.Antworten:
Dataset.shuffle()
mische nur jedes Minibatch, damit jede Epoche die gleiche Reihenfolge hat. Keras.fit()
verwendet einige magische Methoden, um den gesamten Datensatz vor jeder Epoche zu mischen. Um dies in TF zu tun, müssen Sie Dataset verwenden.repeat(epochs_number)
und.shuffle(..., reshuffle_each_iteration=True)
:Diese Problemumgehung ist weder schön noch natürlich. Im Moment können Sie sie verwenden, um jede Epoche zu mischen. Es ist ein bekanntes Problem und wird behoben. Sie können es in Zukunft
for epoch in range(epochs_number)
anstelle von verwenden.repeat()
.quelle
Das Problem ergab sich aus dem Mischen mit der Methode tf.Dataset . Es wurde jeweils nur ein Bucket durch den Datensatz gemischt. Die Verwendung von Keras.Model.fit führte zu besseren Ergebnissen, da wahrscheinlich ein weiteres Mischen hinzugefügt wird .
Ich habe ein Mischen mit hinzugefügt
numpy.random.shuffle
und es hat die Leistung mit beiden Trainingsmethoden verbessert:Die Generierung des Datensatzes ist jetzt:
Und die Ergebnisse sind:
Der Trainingstyp pro Epoche ist mit 2 Minuten pro Epoche ungefähr gleich .
quelle