keras model.fit()和TF tape.gradient()提供不同的结果

时间:2020-08-08 04:29:52

标签: python tensorflow keras deep-learning

我有一个使用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()则永远不会发生。

1 个答案:

答案 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)