使用 Python 构建量子神经网络分类器
运行前请准备 ArcQML 源码仓库及对应示例数据。下文命令和 examples/ 路径均以该仓库为基准;本文展示关键代码片段,完整程序位于文中标注的示例路径。
本教程使用 ArcQML Python API 对德国信用数据集进行二分类,对应 Rust QNN 教程和 benchmarks/qnn 的任务结构。完整程序位于 examples/python/qnn_german_credit.py。
任务结构
- 从
examples/data/german_credit.csv读取 1000 个样本。 - 选择 benchmark 使用的 10 个离散特征。
- 将每列缩放到
[π/2, 3π/2]。 - 使用
RX(x) → RZ(x)将特征编码到 10 量子比特乘积态。 - 使用每层 37 参数、52 个门的 QNN ansatz。
- 读取
Z(q5)期望值作为 logit。 - 使用 BCE-with-logits、batch 伴随反传和 Adam 训练。
- 报告验证准确率、ROC-AUC 和 PR-AUC。
教程默认 1 层、5 个 epoch;benchmark 会测试更深线路。
数据预处理
features, labels = load_data(path=DATA_PATH)
rng = np.random.default_rng(seed=4)
indices = rng.permutation(len(features))
train, validation, test = indices[:800], indices[800:900], indices[900:]
每列使用:
原始 Creditability=0 被作为正类 1,表示信用不良。
特征编码
每个局部量子态为:
程序直接计算这些局部态的张量积,并生成 C 连续数组:
states = np.ones((len(features), 1), dtype=np.complex128)
for qubit in range(QUBITS - 1, -1, -1):
angles = features[:, qubit]
local_states = np.column_stack(
(
np.exp(-0.5j * angles) * np.cos(0.5 * angles),
-1j * np.exp(0.5j * angles) * np.sin(0.5 * angles),
)
)
states = np.einsum("bi,bj->bij", states, local_states).reshape(len(features), -1)
这样每个样本拥有不同初态,而整个 batch 共用同一组可训练 ansatz 参数。
构造线路和可观测量
circuit = arcqml.Circuit(num_qubits=QUBITS)
append_ansatz_layer(
circuit=circuit,
values=rng.standard_normal(PARAMETERS_PER_LAYER),
)
observable = arcqml.PauliSum.z(
num_qubits=QUBITS,
qubit=5,
coefficient=1.0,
)
append_ansatz_layer 的完整 37 参数线路见示例源码。增加到 L 层后,线路具有 37L 个独立可训练参数。
Batch 训练
simulator = arcqml.BatchStateVectorSimulator.from_amplitudes(
num_qubits=QUBITS,
amplitudes=np.ascontiguousarray(states[batch_indices]),
)
logits = simulator.run(circuit=circuit, observable=observable)
targets = arcqml.tensor(np.ascontiguousarray(labels[batch_indices]))
loss = arcqml.binary_cross_entropy_with_logits(
logits=logits,
targets=targets,
)
loss.backward()
optimizer.step(circuit=circuit)
optimizer.zero_grad(circuit=circuit)
logits 的 shape 为 [batch_size]。backward() 通过 BCE 节点把每个样本的梯度传给 batch 量子节点,再由伴随算法累计线路参数梯度。
验证和测试使用:
with arcqml.no_grad():
scores = simulator.run(
circuit=circuit,
observable=observable,
).numpy()
分类时以 logit >= 0 为正类。ROC-AUC 与 PR-AUC 直接使用连续分数,不依赖分类阈值。
运行
maturin develop --release
python examples/python/qnn_german_credit.py
输出形式:
samples: train=800, validation=100, test=100
qubits=10, layers=1, parameters=37
epoch 01/5: train_loss=..., validation_loss=..., validation_accuracy=...%
...
test ROC-AUC=..., PR-AUC=...