量子神经网络¶
本课知识点
经典神经网络的组件与损失函数——能列出经典神经元的组件并说明各自的作用,解释缺少非线性时多层网络为何退化为单层。
前馈与反向传播——能说明前馈是函数的逐层复合,并解释反向传播如何用链式法则计算梯度、支撑梯度下降。
含参数旋转门——能写出 \(R_x(\theta)\)、\(R_y(\theta)\)、\(R_z(\theta)\) 的矩阵形式,并说明旋转角 \(\theta\) 为何能充当可学习参数。
含参数量子电路的三段结构——能按"数据编码—模型电路—测量"三段构造一个 QNN 电路,并解释硬件高效型拟设中旋转层与纠缠层的分工。
量子神经网络的前馈过程——能按五个步骤复述 QNN 的一次前馈,并写出输出期望值 \(y_{\mathrm{pred}}=\langle0|U^\dagger(x,\theta)MU(x,\theta)|0\rangle\)。
参数平移法则——能用两次电路求值按参数平移公式计算解析梯度,并解释该梯度为何精确而非数值近似。
用 PennyLane 训练 QNN——能把设备、QNode、损失函数、优化器与训练循环组装成可运行的 PennyLane 程序,并验证输出能够拟合 \(\sin(x)\)。
量子-经典混合模型——能描述"经典预处理—量子层—经典后处理"的架构,并比较端到端训练中反向传播与参数平移法则的分工。
1. 经典神经网络核心概念复习¶
在我们构建量子版本之前,先快速回顾一下经典神经网络的运作方式。
1.1 组件:参数、算符与损失函数¶
一个最简单的经典神经元可以被看作一个数学函数 \(y = f(wx + b)\)。它由以下组件构成:
输入 (input) \(x\):喂给网络的数据。
参数 (parameter) \(w, b\):网络的"知识",即权重 (weight) \(w\) 和偏置 (bias) \(b\)。它们是可学习的。
线性算符 \(wx + b\):对输入进行线性变换。
非线性算符(激活函数 activation function)\(f\):如 Sigmoid、ReLU。这是网络能学习复杂模式的关键。没有非线性,多层网络也只相当于一个单层网络,因为线性变换的复合仍是线性变换。
输出 (output) \(y\):网络的预测值。
损失函数 (loss function):如均方误差 \(L = (y_{\mathrm{true}} - y_{\mathrm{pred}})^2\),它衡量预测的好坏。我们的目标就是最小化损失函数。
1.2 前馈与反向传播¶
前馈网络 (Feedforward):数据从输入层开始,逐层向前传递,经过一系列线性和非线性变换,最终在输出层得到结果。这个过程就是一系列函数的复合调用。
反向传播 (Backpropagation):为了最小化损失,我们需要知道应该如何调整参数 \(w\) 和 \(b\)。反向传播本质上是利用链式法则 (chain rule) 高效计算损失函数 \(L\) 对每一个参数的梯度 (gradient),即 \(\partial L/\partial w\) 和 \(\partial L/\partial b\)。随后,我们使用梯度下降 (gradient descent) 等优化算法,沿梯度的反方向微调参数,从而降低损失。
2. 量子神经网络 (Quantum Neural Network, QNN)¶
现在,让我们用量子力学的语言来"翻译"经典神经网络的每一个组件。
核心类比
经典比特 → 量子比特 (Qubit)
经典逻辑门 → 量子逻辑门 (Quantum Gate)
可学习的参数 \(w, b\) → 可学习的旋转门角度 \(\theta\)
线性+非线性函数 \(f(wx+b)\) → 含参数的量子电路 \(U(\theta)\)
网络的输出 \(y_{\mathrm{pred}}\) → 可观测量 \(M\) 的期望值
2.1 含参数量子逻辑门¶
我们之前学过的 \(X\)、\(Z\)、\(H\) 门都是固定的。现在,我们引入可以旋转任意角度的门,这些角度就是我们要学习的参数 \(\theta\)。三个最基本的旋转门 (rotation gate) 的定义为
它们分别绕布洛赫球的 X、Y、Z 轴旋转 \(\theta\) 角(这些矩阵形式的完整推导见附录1《含参量子门与矩阵欧拉公式》)。这些门的旋转角度 \(\theta\) 就是我们的"旋钮",是 QNN 中可以被优化的参数。
2.2 构建含参数量子电路 (PQC)¶
一个量子神经网络,在结构上就是一个由三部分组成的量子电路:
数据编码 (Data Encoding):将经典数据 \(x\) 编码到量子态中。例如,可以用一个旋转门将数据作为角度编码进去:\(|\psi_{in}\rangle = R_y(x)|0\rangle\)。
模型电路 (Model Circuit / Ansatz):这就是网络的主体,由一系列固定的门(如 CNOT)和含参数的旋转门 \(R(\theta)\) 组成。这部分电路的结构被称为拟设 (Ansatz)。
测量 (Measurement):在电路的最后,我们选择一个或多个可观测量(如 \(Z_0\)、\(Z_1\)、\(Z_0Z_1\)),并计算其期望值 (expectation value)。这个期望值就是 QNN 的输出。
一个典型的"硬件高效型"(Hardware-efficient) Ansatz 结构如下:
它由重复的"旋转层"和"纠缠层"构成。
旋转层:对每个量子比特应用可学习的旋转门 \(R_x(\theta_1), R_y(\theta_2), R_z(\theta_3)\)。
纠缠层:用一系列 CNOT 门将量子比特纠缠起来。
2.3 量子神经网络的前馈过程¶
QNN 完成一次前馈(即一次函数求值)的流程如下:
准备初态:通常是 \(|00\dots0\rangle\)。
编码输入 \(x\):通过 \(R(x)\) 等门将数据加载到量子态中。
执行模型电路 \(U(\theta)\):将当前的一组参数 \(\theta\) 应用到电路的旋转门上,让量子态进行演化。
计算期望值:测量某个可观测量 \(M\),得到输出 \(y_{\mathrm{pred}} = \langle\psi_{out}| M |\psi_{out}\rangle = \langle0| U^\dagger(x, \theta) M U(x, \theta) |0\rangle\)。
计算损失:使用经典计算机,根据预测值 \(y_{\mathrm{pred}}\) 和真实值 \(y_{\mathrm{true}}\) 计算损失 \(L\)。
2.4 量子神经网络的梯度计算:参数平移法则¶
接下来是最关键的问题:我们如何计算梯度 \(\partial L/\partial\theta\) 来更新参数?难道要像经典反向传播那样复杂吗?
答案是:不需要。量子力学为我们提供了一个优雅得多的方法——参数平移法则 (Parameter-Shift Rule, PSR)。
对于一个由旋转门 \(U = e^{-i\theta G/2}\)(其中 \(G\) 是泡利矩阵 \(X\)、\(Y\) 或 \(Z\))产生的参数 \(\theta\),其最终期望值 \(\langle M \rangle\) 对该参数的梯度可以被精确地计算:
这个公式的含义是:要计算第 \(k\) 个参数 \(\theta_k\) 的梯度,我们只需要运行完全相同的量子电路两次:
第一次,将参数 \(\theta_k\) 增加 \(\pi/2\)(即 90 度),得到期望值 \(\langle M \rangle_{\theta_k + \pi/2}\)。
第二次,将参数 \(\theta_k\) 减少 \(\pi/2\),得到期望值 \(\langle M \rangle_{\theta_k - \pi/2}\)。
将两个结果相减再除以 2,就得到了解析梯度 (analytical gradient),而不是数值近似。得到 \(\partial\langle M\rangle/\partial\theta_k\) 之后,再对输出的映射使用一次链式法则,就能得到损失函数的梯度 \(\partial L/\partial\theta_k\)。
这个强大的法则是变分量子算法(包括 QNN)能够有效训练的核心:它意味着我们可以直接利用量子计算机本身来计算梯度。该法则的完整证明、它的数值验证,以及它对哪些参数化门成立,都在附录2《参数平移法则》中详细讨论。
3. PennyLane 实战:搭建你的第一个 QNN¶
PennyLane 是一个专为量子机器学习设计的 Python 库。它将量子电路的搭建、自动微分(内部使用参数平移法则)与经典机器学习框架(如 PyTorch、TensorFlow)无缝集成。
我们的任务是构建一个简单的 QNN,学习一个一维函数 \(y = \sin(x)\)。步骤如下:
定义量子设备:我们使用模拟器。
构建 QNN 电路 (QNode):编码层用
RY(x)门编码输入;模型层添加若干带参数params的旋转门和 CNOT 门;测量层返回第一个量子比特的PauliZ期望值。定义损失函数:使用均方误差。
选择优化器:使用
AdamOptimizer。训练循环:多次迭代,计算梯度并更新参数。
3.1 训练一个独立的 QNN:拟合 \(\sin(x)\)¶
将上述步骤翻译成代码,我们得到下面的完整程序(可直接运行):
import pennylane as qml
from pennylane import numpy as np # 使用 PennyLane 自带的 numpy,以支持自动微分
# 1. 定义量子设备:使用 2 个量子比特的默认模拟器
dev = qml.device("default.qubit", wires=2)
# 2. 构建 QNN 电路 (QNode)
# @qml.qnode(...) 是一个装饰器,它将一个 Python 函数转换成可在设备上运行的量子电路
@qml.qnode(dev)
def quantum_neural_net(params, x):
"""一个简单的量子神经网络"""
# --- 编码层:将经典数据 x 编码到第 0 个量子比特上 ---
qml.RY(x, wires=0)
# --- 模型层 (Ansatz):由可学习的参数 params 控制 ---
qml.RX(params[0], wires=0)
qml.RY(params[1], wires=0)
qml.CNOT(wires=[0, 1])
qml.RX(params[2], wires=1)
qml.RY(params[3], wires=1)
# --- 测量层:返回第 0 个量子比特上 Z 算符的期望值作为输出 ---
return qml.expval(qml.PauliZ(0))
# 3. 定义损失函数
def square_loss(labels, predictions):
"""计算均方误差"""
return np.mean((labels - predictions) ** 2)
# --- 准备数据和参数 ---
# 生成一些 sin(x) 的数据
X_train = np.linspace(0, 2 * np.pi, 20)
Y_train = np.sin(X_train)
# 随机初始化 QNN 的参数
num_params = 4
params = np.random.uniform(0, 2 * np.pi, num_params, requires_grad=True)
# 4. 选择优化器
opt = qml.AdamOptimizer(stepsize=0.1)
# 5. 训练循环
epochs = 50
for i in range(epochs):
# 定义一个只接受参数并返回损失的函数,这是优化器需要的格式
def cost_fn(p):
predictions = np.array([quantum_neural_net(p, x) for x in X_train])
return square_loss(Y_train, predictions)
# 优化器会自动计算梯度(使用参数平移法则)并更新参数
params, cost = opt.step_and_cost(cost_fn, params)
if (i + 1) % 10 == 0:
print(f"Epoch {i+1:2d}: Cost = {cost:.6f}")
print("\n训练完成! 最终参数:", params)
# --- 测试和可视化 ---
import matplotlib.pyplot as plt
X_test = np.linspace(0, 2 * np.pi, 100)
predictions_test = [quantum_neural_net(params, x) for x in X_test]
plt.plot(X_train, Y_train, 'bo', label="Training data")
plt.plot(X_test, predictions_test, 'r-', label="QNN predictions")
plt.legend()
plt.show()
运行这段代码时,你会看到损失值随迭代逐渐减小,并且在多数随机初始化下,QNN 的预测曲线能够很好地拟合 \(\sin(x)\)。这并非偶然:示例文档《量子神经网络:示例》中给出了该电路输出的解析表达式 \(f(x) = -\sin(\theta_1)\sin x + \cos(\theta_0)\cos(\theta_1)\cos x\),取 \(\theta_1 = 3\pi/2\) 时它与 \(\sin(x)\) 严格相等,因此损失为零的全局最优解确实存在。
3.2 增强QNN:作为"即插即用"模块的混合模型¶
我们刚刚学会了如何使用参数平移法则(PSR)来获取量子电路的梯度。这个发现的意义远不止于训练一个独立的 QNN:它意味着,一个含参数的量子电路(PQC)现在可以被看作是一个完全可微的黑盒。
既然它是可微的,我们是否可以将它像乐高积木一样,插入到已经非常成熟的经典深度学习模型中呢?
答案是肯定的!这就是量子-经典混合模型 (Quantum-Classical Hybrid Model) 的核心思想,也是一种强大的"即插即用" (Plug-and-Play) 策略。
混合模型的架构¶
一个典型的混合模型(例如用于图像分类)的流程如下:
经典预处理层 (Classical Pre-processing):
一个大的输入(如一张 28x28 的图片)首先通过几层经典的 CNN。
CNN 的作用是将图片降维,提取出关键的特征,输出一个小的特征向量(例如,一个长度为 4 或 8 的向量)。
量子层 (Quantum Layer):
从经典层输出的特征向量被用作量子电路的输入。通常,这些特征值会作为旋转门的角度,将信息编码到量子态中。
这个量子电路(PQC)本身也包含可学习的参数 \(\theta\)。
电路演化后,测量一个或多个可观测量,其期望值作为该量子层的输出。
经典后处理层 (Classical Post-processing):
从量子层输出的期望值(现在是普通的经典数值)可以被送入一个或多个经典的神经元(全连接层),进行最终的分类或回归。
端到端的训练:无缝的梯度流¶
混合模型最美妙的地方在于,整个系统是端到端可训练的。当计算损失函数关于所有参数的梯度时:
对于经典层的参数,梯度通过反向传播计算。
当梯度流"到达"量子层时,框架(如 PennyLane)会自动切换到参数平移法则来计算损失关于量子参数 \(\theta\) 的梯度。
更进一步,框架还能计算出损失关于输入到量子层的数据的梯度,并将这个梯度继续向前传播给更早的经典层。
这意味着,我们可以像训练一个纯经典网络一样,调用 loss.backward() 和 optimizer.step(),整个混合模型的参数(包括经典的权重和量子的旋转角)都会被自动、协同地优化。
以 PennyLane 和 PyTorch 为例¶
PennyLane 与 PyTorch、TensorFlow 等主流框架的集成让这种"即插即用"变得异常简单:我们可以将一个 QNode 包装成一个标准的 PyTorch 层。
让我们修改一下之前的代码,构建一个简单的混合模型。我们的任务是:用一个经典线性层对数据进行预处理,然后送入 QNN。
import torch
import pennylane as qml
from pennylane import numpy as np
# --- 1. 定义量子设备和 QNode(结构相同) ---
dev = qml.device("default.qubit", wires=2)
@qml.qnode(dev)
def quantum_circuit(params, x):
# 编码层:x 是长度为 4 的特征向量;按批输入时形状为 (batch, 4),
# 因此用 x[:, 0]、x[:, 1] 取出特征,PennyLane 会自动按批广播
qml.RY(x[:, 0], wires=0)
qml.RY(x[:, 1], wires=1)
# 模型层:可学习的参数 params
qml.CNOT(wires=[0, 1])
qml.RX(params[0], wires=0)
qml.RY(params[1], wires=1)
# 测量层:测量一个关联算符
return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
# --- 2. 构建混合模型 ---
# a. 定义经典部分:一个从 1 维输入到 4 维输出的线性层
classical_layer = torch.nn.Linear(1, 4)
# b. 将 QNode 包装成一个 PyTorch 层
# weight_shapes 定义了 QNode 中可学习参数的形状
weight_shapes = {"params": (2,)}
quantum_layer = qml.qnn.TorchLayer(quantum_circuit, weight_shapes)
# c. 使用 torch.nn.Sequential 将它们"即插即用"地连接起来
hybrid_model = torch.nn.Sequential(
classical_layer,
quantum_layer
)
# --- 3. 训练循环(标准的 PyTorch 流程) ---
# 准备数据
X_train = torch.linspace(0, 2 * np.pi, 20).reshape(-1, 1)
Y_train = torch.sin(X_train)
# 定义优化器,它会同时看到经典和量子的参数!
opt = torch.optim.Adam(hybrid_model.parameters(), lr=0.1)
loss_fn = torch.nn.MSELoss()
epochs = 50
for i in range(epochs):
opt.zero_grad() # 清空梯度
predictions = hybrid_model(X_train).reshape(-1) # 前向传播
loss = loss_fn(predictions, Y_train.reshape(-1)) # 计算损失
loss.backward() # 反向传播(PyTorch 和 PennyLane 在此协同工作)
opt.step() # 更新所有参数
if (i + 1) % 10 == 0:
print(f"Epoch {i+1:2d}: Loss = {loss.item():.6f}")
# --- 4. 可视化结果 ---
import matplotlib.pyplot as plt
X_test = torch.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
predictions_test = hybrid_model(X_test).detach().numpy() # 使用 detach() 来切断梯度追踪
plt.plot(X_train.numpy(), Y_train.numpy(), 'bo', label="Training data")
plt.plot(X_test.numpy(), predictions_test, 'r-', label="Hybrid QNN predictions")
plt.legend()
plt.show()
在这个例子中,qml.qnn.TorchLayer 就是那个"适配器",它让量子电路完美地融入了 PyTorch 的生态系统:训练流程与纯经典模型的训练流程几乎完全一样,充分体现了"即插即用"的便利性。
总结:混合模型的潜力¶
发挥各自优势:结合了经典网络强大的特征提取能力和量子电路潜在的更强表达能力。
适应 NISQ 硬件:使得在小规模、含噪声的量子设备上解决有意义的现实问题成为可能。
灵活性:可以方便地将量子层插入到任何经典深度学习架构的任何位置,为模型设计提供了巨大的灵活性。
活跃的研究方向:探索何种问题、何种架构最能从这种混合模式中获益,是当前量子机器学习领域最前沿的研究方向之一。
本课总结¶
QNN 的核心思想是用含参数的量子电路来替代经典神经网络的层。
旋转门的角度 \(\theta\) 是 QNN 的可学习参数。
QNN 的输出是某个可观测量 \(M\) 的期望值,它是一个关于 \(\theta\) 的连续、可微函数。
我们可以使用高效的参数平移法则来精确计算梯度,从而利用经典优化算法(如梯度下降)来训练 QNN。
PennyLane 等框架极大地简化了 QNN 的构建和训练过程,让我们能专注于模型设计本身。
在下一节课,我们将探讨更复杂的 QNN 结构、不同的数据编码方法,以及 QNN 在分类、强化学习等领域的潜在应用。
练习题¶
练习 1【经典神经网络的组件与损失函数】(→ 1.1 节)
列出经典神经元 \(y = f(wx + b)\) 的各组件,并分别说明权重 \(w\)、偏置 \(b\)、激活函数 \(f\) 与损失函数的作用。
设两个线性层依次为 \(y_1 = W_1 x + b_1\)、\(y_2 = W_2 y_1 + b_2\)(都不带激活函数)。写出复合后等价的单层权重与偏置,并据此说明"没有非线性,多层网络只相当于一个单层网络"。
提示:把 \(y_1\) 代入 \(y_2\) 展开为 \(x\) 的表达式,再按矩阵乘法合并同类项。
练习 2【前馈与反向传播】(→ 1.2 节)
设损失 \(L = (y_{\mathrm{true}} - y_{\mathrm{pred}})^2\)。写出 \(\partial L/\partial y_{\mathrm{pred}}\),并计算 \(y_{\mathrm{true}} = 1\)、\(y_{\mathrm{pred}} = 0.6\) 时的值。
对 \(y = f(wx + b)\),用链式法则把 \(\partial L/\partial w\) 用 \(\partial L/\partial y\)、\(f'(wx+b)\) 与 \(x\) 表示出来,并说明梯度下降为何沿该梯度的反方向更新 \(w\)。
提示:把 \(L\) 看作 \(y\) 的函数、\(y\) 看作 \(w\) 的函数,逐环节求导后相乘。
练习 3【含参数旋转门】(→ 2.1 节)
写出 \(R_y(\theta)\) 的矩阵形式,代入 \(\theta = \pi\) 计算 \(R_y(\pi)|0\rangle\),并指出结果对应布洛赫球上的哪个位置。
写出 \(R_z(\pi)\) 的矩阵(利用 \(e^{\pm i\pi/2} = \pm i\)),并验证它的两个列向量构成标准正交基(从而 \(R_z(\pi)\) 是幺正矩阵)。
提示:两列分别是 \((-i, 0)^{\mathsf T}\) 与 \((0, i)^{\mathsf T}\),逐对计算内积即可。
练习 4【含参数量子电路的三段结构】(→ 2.2 节)
按"数据编码—模型电路—测量"三段写出 QNN 电路的组成,并为每一段举一个正文中的具体实现(如用 \(R_y(x)|0\rangle\) 编码数据)。
硬件高效型拟设由旋转层与纠缠层交替构成。解释两层的分工,并证明:只含单量子比特旋转门(不含任何 CNOT)的电路无法把乘积态 \(|00\rangle\) 变成纠缠态。
提示:单比特门作用后两比特态始终保持 \(|\psi_1\rangle\otimes|\psi_2\rangle\) 的乘积形式,对层数作归纳。
练习 5【量子神经网络的前馈过程】(→ 2.3 节)
按顺序列出 QNN 一次前馈的五个步骤。
设 \(|\psi_{out}\rangle = U(x,\theta)|0\rangle\),从期望值定义 \(y_{\mathrm{pred}} = \langle\psi_{out}|M|\psi_{out}\rangle\) 出发,推导 \(y_{\mathrm{pred}} = \langle0|U^\dagger(x,\theta)MU(x,\theta)|0\rangle\),并说明为什么 \(y_{\mathrm{pred}}\) 是关于 \(\theta\) 连续可微的函数。
提示:左矢是右矢的共轭转置,即 \((U|\psi\rangle)^\dagger = \langle\psi|U^\dagger\);矩阵元是 \(\cos\)、\(\sin\) 的有限组合。
练习 6【参数平移法则】(→ 2.4 节)
写出参数平移公式,并说明求一个参数 \(\theta_k\) 的梯度需要运行电路几次、每次把该参数设成多少。
设某电路的输出为 \(f(\theta) = \cos\theta\)(可由旋转门产生)。用参数平移公式计算 \(\frac{1}{2}\big[f(\theta + \pi/2) - f(\theta - \pi/2)\big]\),并验证结果等于 \(\frac{d}{d\theta}\cos\theta\)。
提示:\(\cos(\theta + \pi/2) = -\sin\theta\),\(\cos(\theta - \pi/2) = \sin\theta\)。
练习 7【用 PennyLane 训练 QNN】(→ 3.1 节)
指出正文中训练脚本里"定义设备、构建 QNode、定义损失、选择优化器、训练循环"五步分别对应的代码段,并解释
@qml.qnode(dev)装饰器的作用。正文给出该电路输出的解析表达式 \(f(x) = -\sin(\theta_1)\sin x + \cos(\theta_0)\cos(\theta_1)\cos x\)。取 \(\theta_1 = 3\pi/2\),化简 \(f(x)\),并说明此时训练集上的均方误差是多少。
修改代码:多次改变初始参数重新训练,观察是否每次都能完美拟合 \(\sin(x)\),并结合正文"在多数随机初始化下"的表述解释你的观察。
提示:\(\sin(3\pi/2) = -1\),\(\cos(3\pi/2) = 0\)。
练习 8【量子-经典混合模型】(→ 3.2 节)
按顺序描述混合模型"经典预处理—量子层—经典后处理"三段的流程,并指出每段分别在经典设备还是量子设备上执行。
在端到端训练中,比较经典层参数与量子层参数各自使用的梯度计算方式(反向传播 vs. 参数平移法则),并说明
qml.qnn.TorchLayer在两者之间扮演的"适配器"角色。阅读混合模型代码,解释为什么
torch.optim.Adam(hybrid_model.parameters(), lr=0.1)能同时更新经典线性层与量子电路的参数。
提示:经典层的梯度要"穿过"量子层继续回传,因此损失关于量子层输入也必须是可微的。
