'Use only 2 out of 3 item yielded by generation to train a model
I have generator that returns batches of 3 different tensors of shape s1, s2, and s3.
def generator(path):
....
return x, t, y
train_gen = generator(path_train)
val_gen = generator(path_val)
test_gen = generator(path_test)
I need the t tensor that will be used in a final model that I am working on.
To make sure I an not using the wrong tensors at the wrong locations, I used a toy TensorFlow model that was build to take x as input and y as output. Please note that my generator is return (x, t, y) in that order and my model runs with x as input and y as output.
I first ran the training of the model using model.fit() without changing any thing and to my surprise, it trained and learned without throwing any error on output mismatch.
How is this possible? Why is it still able to train and learn since it expect only (x, y) from the generator and I am providing (x, t, y) instead?
In an attempt ensure that it is using the correct tensors, I tried to modify the model.fit() class in the following manner and is unsure if it is the right way.
import tensorflow as tf
class AdaptFit(tf.keras.Model):
def __init__(self, model): super(AdaptFit, self).__init__() self.model = model def train_step(self, data): # Unpack the data. Its structure depends on your model and # on what you pass to `fit()`. x, _, y = data with tf.GradientTape() as tape: y_pred = self(x, training=True) # Forward pass # Compute the loss value # (the loss function is configured in `compile()`) loss = self.compiled_loss(y, y_pred, regularization_losses=self.losses) # Compute gradients trainable_vars = self.trainable_variables gradients = tape.gradient(loss, trainable_vars) # Update weights self.optimizer.apply_gradients(zip(gradients, trainable_vars)) # Update metrics (includes the metric that tracks the loss) self.compiled_metrics.update_state(y, y_pred) # Return a dict mapping metric names to current value return {m.name: m.result() for m in self.metrics} def test_step(self, data): # Unpack the data x, _, y = data # Compute predictions y_pred = self(x, training=False) # Updates the metrics tracking the loss self.compiled_loss(y, y_pred, regularization_losses=self.losses) # Update the metrics. self.compiled_metrics.update_state(y, y_pred) # Return a dict mapping metric names to current value. # Note that it will include the loss (tracked in self.metrics). return {m.name: m.result() for m in self.metrics} def call(self, inputs, *args, **kwargs): return self.model(inputs)
then here is what I did to the model to change how it trains
def model (n):
inputs = tf.keras.layers.Input(shape=(3,))
outputs = tf.keras.layers.Dense(n)(inputs)
model = tf.keras.models.Model(inputs=inputs, outputs=outputs)
return AdaptFit(model)
n_neurons = 4
mymodel = model(n_neurons)
mymodel.compile(optimizer="Adam", loss="mse", metrics=["mae"])
history = mymodel.fit(train_gen, epochs=50, validation_data= val_gen)
mymodel.compile(optimizer="Adam", loss="mse", metrics=["mae"])
history = mymodel.fit(train_gen, epochs=50, validation_data= val_gen)
Is this the correct way to go about this?
Solution 1:[1]
fit() supports various ways of feeding data, for example x could be a list of tensors, check the api docs .
and you unpack the data as x, t, y in train_step() so the code works.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | alionkun |
