我有一个使用keras功能API构建的模型。定义之后,我使用SGD优化器对其进行编译,如下所示。
opt = tf.keras.optimizers.SGD(learning_rate=0.05, momentum=0.9, decay=1e-3,clipnorm=1)
model.compile(optimizer=opt, loss='mse')
model.fit(train_datagen, epochs=50,shuffle=True,verbose=True)
这很好,我的模型按预期收敛。
但是,当我使用TF的磁带梯度实现相同的确切功能时,我始终会得到NaN梯度,这会导致我的权重等于NaN,然后由于NaN而导致损失函数值相等。这是我使用的代码:
opt = tf.keras.optimizers.SGD(learning_rate=0.05, momentum=0.9, decay=1e-3,clipnorm=1)
loss_fn = tf.keras.losses.MeanSquaredError()
epochs = 50
for epoch in range(epochs):
batch_list = list(range(len(train_datagen)))
random.shuffle(batch_list)
running_loss = 0
for ii in batch_list:
x,y_true = train_datagen[ii]
with tf.GradientTape() as tape:
y_pred = model(x, training=True)
loss_value = loss_fn(y_true,y_pred)
grads = tape.gradient(loss_value, model.trainable_variables)
opt.apply_gradients(zip(grads, model.trainable_variables))
running_loss += loss_value
print('Epoch',epoch,'Running Loss:',running_loss.numpy()/len(batch_list))
我编写的代码是否等效于Keras model.fit()功能?出于某种原因,当我使用上面的代码时,我会不断得到NaN
的渐变,但是使用model.fit()则永远不会发生。
答案 0 :(得分:1)
我认为这是因为基于类的损失MeanSquaredError
需要进行一些额外的修改才能使其在.fit
方法之外运行。取而代之的是,使用功能强大的功能使其变得更容易。只需在训练步骤中这样称呼它即可。
with tf.GradientTape() as tape:
y_pred = model(x, training=True)
loss_value = tf.keras.losses.mean_squared_error(y_true,y_pred)