恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
量子LSTM实战:从Jupyter Notebook到可训练模型
首页
资讯中心
/
量子LSTM实战:从Jupyter Notebook到可训练模型
量子LSTM实战:从Jupyter Notebook到可训练模型
发布时间:2026/10/21 11:58:45
简介这份资源是量子LSTM的入门示例工程面向具备Python与深度学习基础、希望了解量子机器学习实现方式的学习者与研究者帮助读者在PyTorch经典LSTM与量子LSTM之间建立直观对比。压缩包共10个文件以py脚本、png训练曲线图、txt依赖清单为主另含一份ipynb交互式笔记本与md说明文档整体约84KB体积轻便便于快速上手。资源围绕词性标注任务展开提供经典LSTM与量子LSTM两条训练路径并附训练历史与损失对比图方便读者观察两者在收敛速度与精度上的差异。依赖清单区分了不同量子计算后端便于按需安装环境。目前已有423人学习下载适合作为量子机器学习方向的练手项目帮助读者理解量子线路与循环网络结合的基本思路并在此基础上开展自己的实验与调参。1. 量子LSTM示例一个能跑起来的Jupyter Notebook项目第一次看到“量子LSTM”这个词我下意识觉得是论文里的概念图直到把这份 Jupyter Notebook 拉下来跑通才发现它其实是一个能直接上手改的工程示例。项目把量子计算里常用的变分线路和经典 LSTM 单元拼在一起用 Notebook 的形式把数据准备、模型定义、训练循环、结果可视化全流程摊开给你看。适合两类人一类是想把量子层塞进现有深度学习流程的算法工程师另一类是想找个能跑通的量子机器学习 Demo 来改的学生或研究者。整个项目不依赖真实量子硬件本地模拟器就能跑对刚接触量子机器学习的人来说门槛压得比较低。2. 环境准备与依赖安装从零把 Notebook 跑起来2.1 依赖清单与版本选择这个项目本质是一个 Jupyter Notebook核心依赖分三块量子计算框架、经典深度学习框架、以及 Notebook 运行环境。常见做法是用qiskit或pennylane做量子线路模拟用torch或tensorflow做经典 LSTM 部分。我一般会先建一个干净的虚拟环境避免和系统里已有的包打架。# 创建虚拟环境Python 版本建议 3.9 到 3.11 python -m venv qlstm_env source qlstm_env/bin/activate # Windows 用 qlstm_env\Scripts\activate # 安装核心依赖版本按项目实际 import 调整 pip install jupyter notebook pip install qiskit0.45.0 pip install torch2.1.0 pip install numpy pandas matplotlib scikit-learn这里把qiskit和torch的版本写死是有原因的量子模拟器和自动微分框架之间的接口在不同版本里变动不小版本对不上很容易在反向传播时报维度错误。如果你用的是pennylane那经典框架可以换成torch或tensorflowpennylane对两者的自动微分支持都比较成熟。提示如果安装qiskit时编译报错先升级pip和setuptools再单独装qiskit-aer模拟器后端。2.2 启动 Notebook 与首次运行检查依赖装完后在项目根目录启动 Jupyterjupyter notebook浏览器打开后找到主 Notebook 文件从上到下依次执行单元格。第一次运行建议不要直接“全部运行”而是逐块执行观察每个单元格的输出。重点看三个地方量子线路的绘制输出是否正常、模型参数量是否打印出来、训练损失是否在下降。# 检查量子模拟器是否可用 from qiskit import Aer simulator Aer.get_backend(aer_simulator) print(simulator)如果这一步能打印出模拟器对象说明量子计算环境没问题。如果报No module named qiskit_aer说明模拟器后端没装补一句pip install qiskit-aer即可。这个检查步骤很多人会跳过结果跑到训练阶段才发现量子层根本没执行白白浪费调试时间。3. 核心模块拆解量子层与LSTM怎么拼在一起3.1 量子线路定义与参数化项目里最核心的部分是量子层的定义。它用变分量子线路VQC作为可训练层线路里的旋转门角度就是需要优化的参数。下面是一个典型的参数化量子线路写法from qiskit import QuantumCircuit, ParameterVector from qiskit.circuit import Parameter def create_quantum_circuit(n_qubits, n_layers): 创建参数化量子线路 n_qubits: 量子比特数对应特征维度 n_layers: 变分层数层数越多表达能力越强 params ParameterVector(θ, n_qubits * n_layers * 2) qc QuantumCircuit(n_qubits) param_idx 0 for layer in range(n_layers): # 旋转层每个量子比特上加RY和RZ门 for qubit in range(n_qubits): qc.ry(params[param_idx], qubit) param_idx 1 qc.rz(params[param_idx], qubit) param_idx 1 # 纠缠层用CNOT门制造量子比特间的关联 for qubit in range(n_qubits - 1): qc.cx(qubit, qubit 1) return qc, params这段代码的逻辑是每一层先对每个量子比特做独立的旋转操作再用 CNOT 门把相邻量子比特纠缠起来。旋转门负责引入可训练参数纠缠门负责让量子比特之间产生关联这样线路才能表达复杂的函数关系。n_qubits通常等于输入特征的维度n_layers控制模型容量层数太少欠拟合层数太多在模拟器上跑得慢且容易过拟合。参数说明ParameterVector创建的是一个符号向量实际训练时会被替换成具体数值。param_idx用来按顺序取参数保证每个门拿到不同的角度。如果你把n_qubits设成 4、n_layers设成 2那总参数量就是 4×2×216 个。3.2 量子层与LSTM的拼接方式量子层本身不处理时序信息所以项目把它嵌在 LSTM 的输入或输出端。常见做法有两种一种是把量子层放在 LSTM 前面做特征变换另一种是放在 LSTM 后面做输出映射。下面这种是放在输入端的写法import torch import torch.nn as nn from qiskit import QuantumCircuit from qiskit.circuit import ParameterVector class QuantumLayer(nn.Module): def __init__(self, n_qubits, n_layers): super().__init__() self.n_qubits n_qubits self.qc, self.params create_quantum_circuit(n_qubits, n_layers) # 把量子参数注册为PyTorch可训练参数 self.theta nn.Parameter(torch.randn(len(self.params))) def forward(self, x): # x shape: (batch, n_qubits) # 这里用模拟器逐样本计算期望值 # 实际项目中会做批量化或使用torch接口 return self._run_circuit(x) def _run_circuit(self, x): # 绑定输入和参数执行线路取Z方向期望值 # 具体实现依赖qiskit的backend.run pass class QLSTM(nn.Module): def __init__(self, input_dim, hidden_dim, n_qubits, n_layers): super().__init__() self.quantum QuantumLayer(n_qubits, n_layers) self.lstm nn.LSTM(input_dim, hidden_dim, batch_firstTrue) self.fc nn.Linear(hidden_dim, 1) def forward(self, x): # x shape: (batch, seq_len, input_dim) q_out self.quantum(x) # 量子特征变换 lstm_out, _ self.lstm(q_out) return self.fc(lstm_out[:, -1, :])这段代码的关键在于QuantumLayer把量子线路的参数包装成了nn.Parameter这样 PyTorch 的优化器就能更新它们。forward里先跑量子线路拿到期望值再送进 LSTM 做时序建模最后全连接层输出预测。实际项目中量子线路的执行通常会用qiskit的TorchConnector或者pennylane的qml.qnn.TorchLayer来打通自动微分手写_run_circuit容易在梯度回传时翻车。注意量子模拟器不支持批量并行时训练会非常慢。常见做法是把 batch size 设小一点或者用qiskit的StatevectorSampler做向量化。3.3 训练循环与损失函数训练部分和普通 PyTorch 项目差别不大核心是优化器要同时更新量子参数和经典参数model QLSTM(input_dim4, hidden_dim16, n_qubits4, n_layers2) optimizer torch.optim.Adam(model.parameters(), lr0.01) criterion nn.MSELoss() for epoch in range(50): model.train() optimizer.zero_grad() output model(train_x) loss criterion(output, train_y) loss.backward() # 梯度会回传到量子参数 optimizer.step() if epoch % 10 0: print(fEpoch {epoch}, Loss: {loss.item():.4f})这里model.parameters()会自动包含量子层里的theta所以不需要单独写量子优化器。loss.backward()能不能成功回传到量子参数取决于量子层是否用了支持自动微分的接口。如果用的是手写的模拟器调用梯度会在量子层断掉训练就变成了只更新 LSTM 部分量子层等于随机初始化后固定不动这是新手最容易踩的坑。4. 避坑与常见问题跑不通时先查这几处4.1 量子模拟器报错“backend not found”现象执行量子线路时抛出QiskitBackendNotFoundError或类似提示。原因通常是qiskit-aer没装或者Aer.get_backend的参数名写错。解决方法是先pip install qiskit-aer然后确认后端名称是aer_simulator而不是statevector_simulator后者在新版里已经改名。4.2 梯度回传失败导致量子层不更新现象训练损失下降很慢打印量子层参数发现数值几乎没变。原因是量子线路的执行没有接入自动微分图梯度在量子层断开了。解决方法是改用qiskit的TorchConnector或pennylane的TorchLayer它们会把量子线路包装成 PyTorch 可微分模块。如果坚持手写需要自己实现参数偏移规则parameter-shift rule来计算梯度。4.3 Notebook 单元格执行顺序混乱现象单独运行某个单元格时报NameError提示变量未定义。原因是 Jupyter 的变量作用域依赖执行顺序跳着执行会导致前面的变量没初始化。解决方法是每次修改代码后从第一个单元格重新执行一遍或者用Kernel - Restart Run All。这个坑几乎每个用 Notebook 做项目的人都踩过血泪经验就是别偷懒。4.4 训练集和测试集划分不合理现象模型在训练集上损失很低但测试集上表现很差。原因是数据量小的时候随机划分可能导致分布偏移。解决方法是固定随机种子并且用train_test_split的stratify参数保持类别比例。如果数据本身有时序依赖不能随机打乱要按时间顺序切分。4.5 量子比特数设置过大导致内存溢出现象把n_qubits调到 10 以上后模拟器直接卡死或报内存错误。原因是量子态向量的大小是 2 的 n 次方10 个量子比特就是 1024 维15 个就是 32768 维内存消耗指数级增长。解决方法是在模拟器上把量子比特数控制在 8 以内超过这个规模需要考虑用真实量子硬件或张量网络模拟器。5. 二次开发与改造思路从示例到自己的项目5.1 替换数据集与调整输入维度这个示例默认用的可能是随机生成的数据或某个小型公开数据集。要改成自己的数据第一步是确认输入特征维度然后同步修改n_qubits和 LSTM 的input_dim。比如你的数据每个时间步有 6 个特征那就把n_qubits设成 6input_dim也设成 6。如果特征维度不是 2 的幂可以补零或者用主成分分析降到合适维度。# 假设你的数据是 (样本数, 时间步, 特征数) import numpy as np data np.load(your_data.npy) n_features data.shape[2] n_qubits n_features # 量子比特数等于特征数改造时注意量子线路的输入需要归一化到旋转门能接受的范围通常是[-π, π]。常见做法是用MinMaxScaler把数据缩放到这个区间否则旋转门的角度会周期性重复导致信息丢失。5.2 换用量子框架或经典框架项目用的是qiskittorch的组合但你可以换成pennylanetensorflow。pennylane的优势是它对自动微分的支持更统一量子层和经典层的拼接更顺滑。下面是一个pennylane版本的量子层import pennylane as qml from pennylane import numpy as pnp n_qubits 4 dev qml.device(default.qubit, wiresn_qubits) qml.qnode(dev, interfacetorch) def quantum_circuit(inputs, weights): qml.templates.AngleEmbedding(inputs, wiresrange(n_qubits)) qml.templates.StronglyEntanglingLayers(weights, wiresrange(n_qubits)) return [qml.expval(qml.PauliZ(i)) for i in range(n_qubits)] weight_shapes {weights: (2, n_qubits, 3)} qlayer qml.qnn.TorchLayer(quantum_circuit, weight_shapes)这段代码用AngleEmbedding把经典数据编码到量子态用StronglyEntanglingLayers做可训练变换最后取每个量子比特的 Z 方向期望值作为输出。TorchLayer会自动处理梯度和参数注册比手写省事很多。换框架时主要改量子层的定义LSTM 和训练循环基本不用动。5.3 验证改造是否成功的三个检查点改完代码后别急着跑完整训练。先做三个快速验证第一打印模型参数量确认量子参数和经典参数都在model.parameters()里第二用一个 batch 的数据做前向传播看输出形状是否符合预期第三执行一次loss.backward()检查量子参数的.grad是否非空。这三个检查点过了再跑完整训练基本不会出大问题。# 检查点示例 model QLSTM(input_dim4, hidden_dim16, n_qubits4, n_layers2) print(f总参数量: {sum(p.numel() for p in model.parameters())}) dummy_x torch.randn(2, 10, 4) # batch2, seq_len10, features4 dummy_y torch.randn(2, 1) out model(dummy_x) print(f输出形状: {out.shape}) loss nn.MSELoss()(out, dummy_y) loss.backward() for name, param in model.named_parameters(): if theta in name: print(f量子参数梯度非空: {param.grad is not None})从那以后我每次改量子层结构都强制走一遍这三个检查点确认梯度链路没断再开训练。希望这个示例能帮你把量子 LSTM 从 Notebook 跑到自己的项目里。本文还有配套的精品资源点击获取