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

TensorFlow Quantum量子神经网络输入参数训练异常问题咨询

问题分析与解决方案

嘿,我一眼就看出你卡在哪了——直接把TensorFlow张量作为Cirq门的参数传入电路,这会彻底切断TensorFlow自动求导的追踪链路,量子神经网络自然就没法训练了。

为啥普通参数能正常训练?

你正常训练的代码里,theta_g是普通的Python数值,生成的电路参数都是固定死的数值,这时候判别器的可训练参数是自身PQC层里的theta符号参数,TFQ能完美追踪这个参数的梯度,训练自然顺顺当当。

为啥用tf.constant就不行?

当你把theta_g定义成tf.constant,还把它和其他张量运算的结果直接传给Cirq门的参数时,Cirq根本识别不了TF张量里的梯度信息,tfq.convert_to_tensor转出来的电路张量会丢掉所有梯度追踪的线索,整个网络的梯度传不下去,训练当然就卡壳了。

给你改好的正确实现方式

要让输入电路的参数能被训练,你得用sympy符号来定义电路里的可训练参数,然后把这些参数的TF变量值和电路分开传给TFQ的层,保证梯度能被正确追踪。下面是调整后的代码:

生成带可训练参数的输入电路

# 把theta_g改成TF变量(要训练的参数必须是Variable,不能是constant)
theta_g = tf.Variable([1.0], trainable=True)
blob_size = abs(1 - 4) / 5
spread_x = np.random.uniform(-blob_size, blob_size)
spread_y = np.random.uniform(-blob_size, blob_size)

# 把随机值转成TF张量(保持运算在TF图内)
spread_x_tf = tf.constant(spread_x, dtype=tf.float32)
spread_y_tf = tf.constant(spread_y, dtype=tf.float32)

# 用sympy符号定义电路的参数,这是TFQ能追踪梯度的关键
angle_sym = sympy.Symbol('angle')
x_sym = sympy.Symbol('x')

qubit = cirq.GridQubit(0, 0)
# 创建带符号参数的电路,不用硬塞数值进去
cir = cirq.Circuit(
    cirq.ry(-angle_sym)(qubit),
    cirq.rx(-x_sym)(qubit)
)

# 计算参数的实际值(TF运算,保留梯度追踪)
angle_val = theta_g + spread_y_tf
# 把电路转成TFQ能处理的张量
cir_tensor = tfq.convert_to_tensor([cir])
# 准备参数输入:把符号对应的数值拼起来
params = tf.concat([angle_val, [spread_x_tf]], axis=0)

调整判别器以支持带参数的输入电路

如果你的目标是让theta_g作为生成器的可训练参数,同时让判别器能处理这种带参数的输入电路,得改一改判别器的结构,让它同时接收电路张量和参数张量:

def discriminator():
    # 判别器自己的可训练参数
    theta_d = sympy.Symbol('theta_d')
    # 和输入电路对应的符号参数
    angle_sym = sympy.Symbol('angle')
    x_sym = sympy.Symbol('x')
    
    # 先拼上输入电路的结构,再加上判别器的量子层
    input_circuit = cirq.Circuit(
        cirq.ry(-angle_sym)(qubit),
        cirq.rx(-x_sym)(qubit)
    )
    q_model = input_circuit + cirq.Circuit(cirq.ry(theta_d)(qubit))
    
    # 输入变成两个:电路张量 + 参数张量
    q_data_input = tf.keras.Input(shape=(), dtype=tf.dtypes.string)
    params_input = tf.keras.Input(shape=(2,), dtype=tf.float32)
    
    # PQC层要同时接收电路和参数
    expectation = tfq.layers.PQC(q_model, cirq.Z(qubit))
    expectation_output = expectation([q_data_input, params_input])
    
    classifier = tf.keras.layers.Dense(1, activation=tf.keras.activations.sigmoid)
    classifier_output = classifier(expectation_output)
    
    model = tf.keras.Model(inputs=[q_data_input, params_input], outputs=classifier_output)
    return model

使用修改后的判别器

discriminator_net = discriminator()
# 同时传入电路张量和参数张量
output = discriminator_net([cir_tensor, params])

几个关键提醒

  • Cirq门参数优先用sympy符号:TFQ的梯度追踪全靠符号参数和TF变量绑定,直接塞TF张量等于自断后路。
  • 可训练参数必须是tf.Variable:要是某个参数需要被训练,一定要定义成tf.Variable,tf.constant是固定值,没法被优化。
  • 电路和参数要分开传:带可训练参数的电路,不能把参数直接嵌进电路里,得把电路张量和参数张量分别作为输入传给模型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 07:07:29