TensorFlow 2.11.0中Adam优化器报无get_updates属性错误求助
问题排查与解决方案
错误原因分析
AttributeError: 'Adam' object has no attribute 'get_updates' 并非单纯版本不匹配问题,而是自定义损失/指标的写法不符合TensorFlow 2.x规范:
- TensorFlow 2.x的
tf.keras.optimizers.Adam确实没有get_updates方法(该方法属于旧版独立Keras的优化器),如果你的自定义损失/指标函数内部直接调用了这个方法,就会触发错误。 - 你的编译代码中,
metrics列表里的calculate_kl_loss(self)是直接调用函数并传入实例,这不符合要求——metrics需要传入的是可调用的函数对象,而非函数执行后的结果。
具体修复步骤
1. 修正VAE损失的处理方式(推荐方案)
VAE的KL散度损失通常通过add_loss方法添加到模型中,而非作为metrics传入,更符合tf.keras的设计逻辑:
class VAE(tf.keras.Model): def __init__(self, latent_dim): super(VAE, self).__init__() self.latent_dim = latent_dim self.encoder = self.build_encoder() self.decoder = self.build_decoder() def build_encoder(self): # 示例编码器结构,可根据你的任务调整 inputs = tf.keras.Input(shape=(28,28,1)) x = tf.keras.layers.Flatten()(inputs) x = tf.keras.layers.Dense(256, activation='relu')(x) z_mean = tf.keras.layers.Dense(self.latent_dim)(x) z_log_var = tf.keras.layers.Dense(self.latent_dim)(x) z = self.sampling(z_mean, z_log_var) return tf.keras.Model(inputs, [z_mean, z_log_var, z]) def sampling(self, z_mean, z_log_var): epsilon = tf.random.normal(shape=tf.shape(z_mean)) return z_mean + tf.exp(0.5 * z_log_var) * epsilon def build_decoder(self): # 示例解码器结构,可根据你的任务调整 latent_inputs = tf.keras.Input(shape=(self.latent_dim,)) x = tf.keras.layers.Dense(256, activation='relu')(latent_inputs) x = tf.keras.layers.Dense(784, activation='sigmoid')(x) outputs = tf.keras.layers.Reshape((28,28,1))(x) return tf.keras.Model(latent_inputs, outputs) def call(self, inputs): z_mean, z_log_var, z = self.encoder(inputs) reconstruction = self.decoder(z) # 计算KL损失并添加到模型 kl_loss = -0.5 * tf.reduce_mean(1 + z_log_var - tf.square(z_mean) - tf.exp(z_log_var)) self.add_loss(kl_loss) return reconstruction
2. 修正compile方法
此时compile方法只需指定重建损失,KL损失会自动被模型纳入总损失计算:
def compile(self, learning_rate=0.0001): optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate) # 用MSE或交叉熵作为重建损失,根据你的任务选择 self.compile(optimizer=optimizer, loss=tf.keras.losses.MSE) # 如果需要监控重建损失,可添加对应metrics # self.compile(optimizer=optimizer, loss=tf.keras.losses.MSE, metrics=[tf.keras.losses.MSE])
3. 检查自定义损失函数(若需保留)
如果坚持使用自定义的_calculate_combined_loss,确保它的签名符合tf.keras损失函数要求,且内部没有调用optimizer.get_updates:
def _calculate_combined_loss(self, y_true, y_pred): # 计算重建损失 recon_loss = tf.keras.losses.MSE(y_true, y_pred) recon_loss = tf.reduce_mean(recon_loss) # 获取KL损失(需确保模型中已计算并存储) kl_loss = self.kl_loss # 假设你在call方法中把kl_loss存在实例变量里 return recon_loss + kl_loss
同时,metrics列表要传入函数对象,而非调用后的结果:
# 错误写法:calculate_kl_loss(self) # 正确写法:传入函数(若该函数不需要实例参数,需调整实现) self.model.compile(optimizer=optimizer, loss=self._calculate_combined_loss, metrics=[_calculate_reconstruction_loss, calculate_kl_loss])
额外注意事项
- 避免在自定义损失/指标中直接操作优化器,tf.keras会自动处理梯度更新流程。
- TensorFlow 2.x中,
tf.keras和独立keras的API存在差异,确保全程使用tf.keras下的类和方法,避免混用。
内容的提问来源于stack exchange,提问作者user19826638
相关产品推荐
相关产品推荐

