You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在非tf.Variable的Tensor上应用Keras Adam优化器?

问题

我理解优化器需要ID来跟踪所需信息,比如变量的上一次梯度等,但能否给特定的tf.Tensor使用优化器?

示例代码如下:

a = tf.convert_to_tensor([1.])
with tf.GradientTape() as tape:
    tape.watch(a)
    loss = a**2

grad = tape.gradient(loss, a)
print(grad)

# <tf.Tensor: shape=(1,), dtype=float32, numpy=array([2.], dtype=float32)>

我们可以计算该Tensor的梯度,但无法用此梯度做任何优化操作,因为它不是tf.Variable,执行以下代码会报错:

K.optimizers.Adam().apply_gradients(zip(grad, a))

报错信息:

AttributeError: 'tensorflow.python.framework.ops.EagerTensor' object has no attribute '_unique_id'

优化器本质类似w = w - stepsize * grad的更新逻辑,我们已有w(即该Tensor)和grad,为何不能在优化器中执行此操作?有没有办法无需将其转为tf.Variable,就能对该Tensor应用Adam论文中的更新公式?

回答

为什么不能直接用tf.Tensor调用优化器

TensorFlow的优化器(比如Adam)依赖变量的可追踪状态实现复杂更新逻辑——以Adam为例,它需要维护每个参数的一阶矩(动量)和二阶矩(自适应学习率)的累积值,这些状态需要和参数绑定并持久化。而tf.Tensor是无状态的临时张量,没有唯一ID和内置状态存储机制,优化器无法定位、追踪和维护这些额外的累积参数,这就是报错_unique_id缺失的核心原因。

虽然从数学上看w = w - stepsize * grad是简单更新,但Adam这类自适应优化器的逻辑远不止于此,它需要持续维护每个参数的历史状态,无状态的Tensor无法承载这些信息。

无需转tf.Variable的解决办法

如果不想将Tensor转为tf.Variable,可以手动实现Adam的更新逻辑,自行维护所需的状态张量:

import tensorflow as tf

# 初始目标张量
a = tf.convert_to_tensor([1.], dtype=tf.float32)
# Adam需要维护的状态参数
m = tf.zeros_like(a)  # 一阶矩累积
v = tf.zeros_like(a)  # 二阶矩累积
beta1 = 0.9
beta2 = 0.999
epsilon = 1e-8
learning_rate = 0.001
t = 0  # 迭代时间步

# 计算梯度
with tf.GradientTape() as tape:
    tape.watch(a)
    loss = a ** 2
grad = tape.gradient(loss, a)

# 手动执行Adam更新流程
t += 1
# 更新一阶矩和二阶矩
m = beta1 * m + (1 - beta1) * grad
v = beta2 * v + (1 - beta2) * tf.square(grad)
# 偏差修正(抵消初始值为0带来的偏差)
m_hat = m / (1 - tf.pow(beta1, t))
v_hat = v / (1 - tf.pow(beta2, t))
# 更新目标张量
a = a - learning_rate * m_hat / (tf.sqrt(v_hat) + epsilon)

print(a)  # 输出更新后的张量

这种方式完全避开tf.Variable,但需要自行管理Adam的所有状态变量(m、v、时间步t),适合需要完全控制更新逻辑的场景。

内容的提问来源于stack exchange,提问作者Alberto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 20:15:32