Demo 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}")
运行结果¶

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