Demo 2:参数平移梯度

第 2 章 量子神经网络 · 本章演示 · 代码演示总索引

可视化:双图:曲线+误差柱 —— 解析 / 平移 / 有限差分梯度对比

对应教程:第 2 章 量子神经网络 中相关小节 · 依赖安装:pip install "unified-quantum[visualization,simulation]"

实现要点

核心:参数平移法则。对单参数线路 RY(θ)|0⟩ 后测 ⟨Z⟩, 解析梯度 = -sin(θ) 参数平移估计 = [f(θ + π/2) - f(θ - π/2)] / 2 = -sin(θ) 有限差分估计 = [f(θ + ε) - f(θ - ε)] / (2ε) 三者应当一致;本 demo 在多个 θ 值上验证该恒等式并绘图。

完整源码

demos/ch02-qnn/02_parameter_shift.py
  1"""
  2ch02-qnn demo 2: parameter-shift rule
  3
  4对应教程:chenzhaoyun.com/quantum-tutorial/ch02-quantum-nn/parameter-shift-appendix.html
  5核心:参数平移法则。对单参数线路 RY(θ)|0⟩ 后测 ⟨Z⟩,
  6       解析梯度 = -sin(θ)
  7       参数平移估计 = [f(θ + π/2) - f(θ - π/2)] / 2 = -sin(θ)
  8       有限差分估计 = [f(θ + ε) - f(θ - ε)] / (2ε)
  9三者应当一致;本 demo 在多个 θ 值上验证该恒等式并绘图。
 10
 11依赖:pip install unified-quantum[visualization]
 12运行:python demos/ch02-qnn/02_parameter_shift.py
 13"""
 14from __future__ import annotations
 15
 16from pathlib import Path
 17
 18import matplotlib
 19matplotlib.use("Agg")
 20import matplotlib.pyplot as plt
 21import numpy as np
 22
 23from uniqc import Circuit, submit_task, wait_for_result
 24
 25OUT = Path(__file__).parent
 26
 27SHOTS = 4000
 28SHIFT = np.pi / 2.0   # 参数平移法则的标准步长
 29EPS = 1e-3            # 有限差分步长
 30
 31
 32def expectation_of_ry(theta: float, shots: int = SHOTS) -> float:
 33    """对线路 RY(θ)|0⟩ 测 ⟨Z⟩ = cos(θ)。"""
 34    c = Circuit()
 35    c.ry(0, float(theta))
 36    c.measure(0)
 37    r = wait_for_result(submit_task(c, backend="dummy:local:simulator", shots=shots))
 38    p = r.probabilities
 39    return float(p.get("0", 0.0) - p.get("1", 0.0))
 40
 41
 42# === 1. 在一组 θ 上同时算三种梯度 ===
 43thetas = np.linspace(0.1, 2 * np.pi - 0.1, 12)
 44analytic_grad = np.zeros_like(thetas)
 45param_shift_grad = np.zeros_like(thetas)
 46finite_diff_grad = np.zeros_like(thetas)
 47
 48for i, theta in enumerate(thetas):
 49    f_plus = expectation_of_ry(theta + SHIFT)
 50    f_minus = expectation_of_ry(theta - SHIFT)
 51    f_eps = expectation_of_ry(theta + EPS)
 52    f_meps = expectation_of_ry(theta - EPS)
 53
 54    analytic_grad[i] = -np.sin(theta)
 55    param_shift_grad[i] = (f_plus - f_minus) / 2.0
 56    finite_diff_grad[i] = (f_eps - f_meps) / (2.0 * EPS)
 57
 58abs_err_shift = np.abs(param_shift_grad - analytic_grad)
 59abs_err_fd = np.abs(finite_diff_grad - analytic_grad)
 60
 61# === 2. 绘图:理论曲线 vs 两种数值梯度 ===
 62fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12.0, 4.8))
 63
 64# 左图:梯度值对比
 65ax1.plot(thetas, analytic_grad, color="#1f77b4", lw=2.2, label=r"analytic $-\sin\theta$")
 66ax1.plot(thetas, param_shift_grad, "o", color="#2ca02c", ms=7, label="parameter shift (step π/2)")
 67ax1.plot(thetas, finite_diff_grad, "x", color="#d62728", ms=8, mew=2, label=f"finite diff (ε={EPS:g})")
 68ax1.axhline(0.0, color="#888", lw=0.7, ls="--")
 69ax1.set_xlabel(r"$\theta$ (rad)")
 70ax1.set_ylabel(r"$\partial \langle Z\rangle / \partial\theta$")
 71ax1.set_title("Gradient estimators on $R_Y(\\theta)|0\\rangle$")
 72ax1.set_xticks(np.linspace(0, 2 * np.pi, 5))
 73ax1.set_xticklabels([r"$0$", r"$\pi/2$", r"$\pi$", r"$3\pi/2$", r"$2\pi$"])
 74ax1.set_ylim(-1.2, 1.2)
 75ax1.grid(alpha=0.3)
 76ax1.legend(loc="upper right", fontsize=9)
 77
 78# 右图:误差柱状图
 79x_idx = np.arange(len(thetas))
 80width = 0.38
 81ax2.bar(x_idx - width / 2, abs_err_shift, width=width, color="#2ca02c", alpha=0.85,
 82        label="|param-shift error|")
 83ax2.bar(x_idx + width / 2, abs_err_fd, width=width, color="#d62728", alpha=0.85,
 84        label="|finite-diff error|")
 85ax2.set_xticks(x_idx)
 86ax2.set_xticklabels([f"{t:.2f}" for t in thetas], rotation=45, fontsize=8)
 87ax2.set_xlabel(r"$\theta$ (rad)")
 88ax2.set_ylabel("absolute error vs $-\\sin\\theta$")
 89ax2.set_title("Estimator accuracy")
 90ax2.set_yscale("log")
 91ax2.grid(axis="y", alpha=0.3, which="both")
 92ax2.legend(loc="upper left", fontsize=9)
 93
 94plt.suptitle("ch02-qnn demo 2: parameter-shift rule vs finite-difference gradient", y=1.02)
 95plt.tight_layout()
 96out_path = OUT / "02_parameter_shift.png"
 97plt.savefig(out_path, dpi=120, bbox_inches="tight")
 98plt.close()
 99
100# === 3. stdout 关键统计 ===
101print("ch02-qnn-demo-2: parameter-shift rule")
102print(f"  samples: {len(thetas)}, shots per evaluation: {SHOTS}")
103print(f"  shift size: π/2, finite-difference ε: {EPS}")
104print(f"  max |param-shift error|    = {abs_err_shift.max():.4f}")
105print(f"  max |finite-diff error|    = {abs_err_fd.max():.4f}")
106print(f"  mean |param-shift error|   = {abs_err_shift.mean():.4f}")
107print(f"  mean |finite-diff error|   = {abs_err_fd.mean():.4f}")
108print(f"  evaluations on quantum HW: {3 * len(thetas)} circuits submitted")
109print(f"  PNG -> {out_path}")

运行结果

Demo 2:参数平移梯度

运行方式

# 仓库根目录执行;输出 PNG 到 demos/ch02-qnn/02_parameter_shift.png,关键统计到 stdout
.venv/bin/python3 demos/ch02-qnn/02_parameter_shift.py

← 本章演示 · ↑ 代码演示总索引 · ⌂ 教程门户