ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于量子核的SVM手写体识别:从量子特征映射到QSVC调参实战

基于量子核的SVM手写体识别:从量子特征映射到QSVC调参实战 简介量子加速支持向量机实现手写体识别属于图文与代码一体化的毕设级资料包适合人工智能、计算机等专业学生完成课程设计、毕业设计或入门量子机器学习。压缩包共21个文件约3.4MB包含Python源码、Jupyter Notebook演示、量子线路文档、PNG结果图像与PDF说明另有README与LICENSE可清晰了解项目结构并对照运行。目前已有136人学习下载。资源以Quantum-SVM-MINIST为主线既有PDF文档讲解量子SVM原理也有Python脚本与Notebook展示量子核函数实现思路数字样本图像和演示图可辅助验证识别效果适宜作为立项演示或算法复现基础。所有代码均经测试运行成功若遇环境问题还可联系作者远程教学作为快速上手的参考。1. 基于量子加速的SVM手写体识别是什么拿MNIST当量子机器学习的试验田把 SVM 和量子计算放进同一个项目里很多人第一反应是噱头。但基于量子加速的 SVM 手写体识别恰恰是量子机器学习里最容易落地、也最能讲清楚原理的入门场景样本仍然是 MNIST 手写数字模型仍然是支持向量机唯一的变化是把核函数这一层搬到了量子态上——用少量量子比特把数据编码进高维希尔伯特空间再用量子电路的保真度来估计样本之间的内积。这个方向适合两类人一类是拿它当课设或毕设选题想同时吃透 SVM 和量子计算基础的学生另一类是想评估量子核方法到底比经典核方法强在哪的工程师。接下来按原理—落地—调参—排错—验证的顺序展开所有代码都在本地量子模拟器上直接跑通。2. 从经典SVM到量子核SVM的核函数是怎么被量子化重写的2.1 经典SVM的核技巧到底在算什么SVM 的原始形式是找一个超平面把两类样本分开并让间隔最大。遇到线性不可分的数据标准做法是引入核函数 K(xᵢ, xⱼ) φ(xᵢ)ᵀφ(xⱼ)把样本映射到更高维的特征空间再求间隔。你不需要真的算出 φ(x)只需要知道两个样本映射之后的内积这就是核技巧。手写体识别里MNIST 的原始像素向量是 784 维直接用线性 SVM 效果一般换 RBF 核之后精度能上 96% 以上原因就是 RBF 核隐式地把样本映射到了无穷维空间。但经典核函数有个隐含限制核函数的形式是人定的。RBF、多项式、拉普拉斯核都是先验地假设某种相似性度量。如果数据的真实结构不在这个假设里核函数就帮不上忙。量子核方法的思路不一样它用量子特征映射把数据编码成量子态然后核函数定义为两个量子态之间的内积——这个特征空间由量子电路的演化结构决定理论上可以触达经典计算机难表达的高维相关结构。对 SVM 来说你不需要改变学习算法本身只需要换一个核。2.2 量子特征映射把经典数据编码进量子态量子核方法的第一步是把经典样本 x 编码为量子态。常见做法是用 qiskit 的 ZZFeatureMap它的电路结构可以拆成三段理解第一段每个量子比特都过一层 H 门让比特处于叠加态第二段对每一对量子比特施加由数据点角度控制的 ZZ 相互作用门编码特征两两之间的乘积关系第三段再施加单比特旋转门编码单维特征。把这三段重复 reps 次就得到一个带深度可调的特征映射电路 U_φ(x)。角度参数一般取 x 的某种线性变换。qiskit 里默认把 feature 缩放到 [0, 2π) 区间但实际使用中通常不直接缩放到满量程而是乘一个系数比如 angle π * x 或 arcsin(x)把数据压缩到旋转门能稳定表达的区间。ZZFeatureMap 里reps这个参数控制电路深度entanglement控制 ZZ 门连接方式linear只连相邻比特full全连接。对 4 比特编码 4 维特征来说我用linear比较多电路浅模拟器跑得快精度和full差距不大。2.3 量子核估计用电路保真度代替内积给定两个样本 xᵢ、xⱼ量子核 K(xᵢ, xⱼ) 的估计方式是先用量子特征映射电路分别制备两个量子态 |φ(xᵢ)⟩ 和 |φ(xⱼ)⟩然后把 U_φ(xᵢ) 的共轭转置作用在 U_φ(xⱼ) 产生的量子态上最后测量全零态的概率这个概率就是两个量子态的保真度写出来就是K(xᵢ, xⱼ) |⟨φ(xᵢ)|φ(xⱼ)⟩|²这个值落在 [0, 1] 区间天然是一个合法的相似度度量而且它由量子电路的演化决定不是人为指定的多项式或高斯函数。在 qiskit 里FidelityQuantumKernel封装了这段逻辑不需要手写控制反转电路你只需要给它一个特征映射它内部会逐个样本对地构造量子电路并采样估计保真度。这里有一个必须提前建立的认知在经典模拟器上这个量子加速不会体现在运行时间上反而会更慢。真正的潜在优势在电路结构对特征空间的表达能力而不是模拟器上的执行速度。后面第 5 章会专门展开这一点。3. 用Python落地量子SVM手写体识别从MNIST到量子核的最小跑通流程3.1 环境搭建与库版本对齐量子 SVM 项目最烦的不是算法是版本。qiskit 生态这几年 API 变动很大建议直接建一个干净的虚拟环境按下面的组合装python -m venv qsvm_env source qsvm_env/bin/activate pip install qiskit0.46 qiskit-machine-learning0.7.2 scikit-learn1.3.2 numpy matplotlibqiskit-machine-learning里的量子核和 QSVC 接口从 0.7.x 开始稳定早期版本里QSVM那个类在 0.7 已经标记为 deprecated新的 sklearn 风格接口是QSVC用法跟SVC几乎一样。如果你在网上搜到旧教程还在用from qiskit.aqua.algorithms import QSVM那是 qiskit 0.2x 时代的写法直接装不上的不用浪费时间。装完可以先跑一个最小测试确认量子核能正确计算import numpy as np from qiskit.circuit.library import ZZFeatureMap from qiskit_machine_learning.kernels import FidelityQuantumKernel X np.random.rand(4, 2) # 4个样本, 2维特征 feature_map ZZFeatureMap(feature_dimension2, reps1) kernel FidelityQuantumKernel(feature_mapfeature_map) K kernel.evaluate(X) print(K.shape) # 期望 (4, 4) print(np.round(K, 4))这段的作用是确认FidelityQuantumKernel在当前环境能正常调用。feature_dimension必须和输入特征维度一致evaluate(X)返回对称矩阵对角线理论上接近 1.0因为样本和自身的保真度最高。如果这步报错绝大多数是qiskit和qiskit-machine-learning版本错配重新对一遍版本号最省时间。3.2 数据准备MNIST子集采样与降维MNIST 原始是 784 维而量子核模拟器能撑住的量子比特数非常有限。我一般控制在 26 个量子比特也就是把特征降维到 26 维。这里必须做个取舍降维会丢掉信息但维度越高模拟器计算核矩阵的时间膨胀得越厉害。一个 200 样本的核矩阵在 4 量子比特、reps2 的参数下模拟器计算要几分钟到十几分钟升到 6 比特时间直接翻几倍。from sklearn.datasets import fetch_openml from sklearn.model_selection import train_test_split from sklearn.decomposition import PCA from sklearn.preprocessing import MinMaxScaler # 1. 取0和1两类二分类先说清楚 X_full, y_full fetch_openml(mnist_784, version1, return_X_yTrue, as_frameFalse, parserpandas) binary_mask (y_full 0) | (y_full 1) X_bin, y_bin X_full[binary_mask], y_full[binary_mask].astype(int) # 2. 每类抽样60个模拟器跑起来才现实 sample_0 np.where(y_bin 0)[0][:60] sample_1 np.where(y_bin 1)[0][:60] idx np.concatenate([sample_0, sample_1]) X_sub, y_sub X_bin[idx], y_bin[idx] # 3. PCA降维 归一化 pca PCA(n_components4) X_pca pca.fit_transform(X_sub) X_norm MinMaxScaler(feature_range(0, 1)).fit_transform(X_pca) X_train, X_test, y_train, y_test train_test_split( X_norm, y_sub, test_size0.3, random_state42, stratifyy_sub) print(X_train.shape, X_test.shape)fetch_openml拿到的 MNIST 标签是字符串必须转成整型这一步漏了后面报错会很奇怪。PCA 降到 4 维是为了匹配后面ZZFeatureMap(feature_dimension4)的量子比特数。MinMaxScaler把各维度压到 [0,1] 再喂给特征映射比直接用 PCA 输出更稳因为角度编码对输入幅度敏感。注意一个细节0 和 1 这两个数字的像素分布差异本身就很大二分类精度容易做高这符合先跑通再说的目标。但如果你最后想在 39 上做会发现模拟器规模撑不住多分类这是量子模拟的现实约束。3.3 量子核矩阵计算与QSVC训练数据准备好后建立量子核并训练QSVC。这里是整个流程最耗时的部分建议先把reps设为 1跑通再加深。from qiskit.circuit.library import ZZFeatureMap from qiskit_machine_learning.kernels import FidelityQuantumKernel from qiskit_machine_learning.algorithms import QSVC feature_map ZZFeatureMap(feature_dimension4, reps1, entanglementlinear) quantum_kernel FidelityQuantumKernel(feature_mapfeature_map) qsvc QSVC(quantum_kernelquantum_kernel, C1.0) qsvc.fit(X_train, y_train) qsvc_score qsvc.score(X_test, y_test) print(fQSVC accuracy: {qsvc_score:.4f})FidelityQuantumKernel默认用ComputeUncompute方法估计保真度内部会自动做电路反转和测量。QSVC继承了 sklearn 的BaseEstimator所以fit/score的用法和SVC一致。训练过程中qiskit 会把核矩阵的计算结果缓存到pairwise_kernel_matrix如果你在同一个 kernel 对象上再训练一次不会重新计算核矩阵这个缓存机制在调参时能省不少时间。这里容易忽略的一点是QSVC.fit内部会调用量子核逐对计算样本数是 N就要跑 N(N-1)/2 次量子电路求保真度。120 个训练样本就是 7140 次电路求值模拟器上每次电路求值又要叠加态演化和采样所以这一行的实际耗时以分钟为单位是正常的不用怀疑代码卡死了。3.4 模型评估与决策边界可视化二分类场景下我想让结果更直观一点会把测试集的预测结果画出来顺便把支持向量在特征空间里的位置标出来。import matplotlib.pyplot as plt import numpy as np y_pred qsvc.predict(X_test) correct_idx np.where(y_pred y_test)[0] wrong_idx np.where(y_pred ! y_test)[0] plt.figure(figsize(8, 6)) plt.scatter(X_test[correct_idx, 0], X_test[correct_idx, 1], cy_test[correct_idx], cmapcoolwarm, markero, labelcorrect) plt.scatter(X_test[wrong_idx, 0], X_test[wrong_idx, 1], cgray, markerx, labelwrong, s80) plt.xlabel(PC1) plt.ylabel(PC2) plt.legend() plt.title(QSVM on MNIST 0-vs-1) plt.show()如果 PCA 把语义信息压缩进了前两维PC1/PC2 的散点图里两类会明显分离分错的点通常落在两类交界处或 PCA 压缩后的重叠区。看过这张图再回头看精度数字你会对量子核到底学到了什么更有体感。很多项目文档里贴的图片介绍就是这么生成的——把原始样本、降维后分布、核矩阵热力图放一起这本身就是高分项目汇报里最重要的可视化材料。4. 量子SVM在MNIST上的参数调优特征映射、量子比特数和惩罚系数4.1 特征映射选型ZZFeatureMap 是默认起点但不是唯一答案量子核的性能很大程度取决于特征映射结构。qiskit 提供ZZFeatureMap和PauliFeatureMap两类常用选择我用下来的经验是PauliFeatureMap更通用但参数更多调起来费劲ZZFeatureMap直接捕获特征两两交互和 MNIST 这类像素值有局部相关性的数据匹配度更高。from qiskit.circuit.library import PauliFeatureMap # 对比: PauliFeatureMap 允许自定义 pauli 组合 fm_zz ZZFeatureMap(feature_dimension4, reps2, entanglementlinear) fm_pauli PauliFeatureMap(feature_dimension4, reps2, paulis[Z, ZZ], entanglementlinear)paulis[Z, ZZ]的PauliFeatureMap其实和ZZFeatureMap的表达能力非常接近区别是你可以追加 ZZZ 这类三体项来编码三元交互。但三体项会让电路深度显著增加模拟器开销暴涨对 MNIST 这种本身像素值特征的人来说收益未必抵得上成本。我的建议是先用ZZFeatureMap把基线跑出来再试PauliFeatureMap加一项 ZZZ用第 6 章的对比方法判断有没有实质提升别一上来就追求复杂电路。4.2 量子比特数和reps深度和表达能力的权衡量子比特数应该等于特征维度MNIST 降维到几维就用几个比特。这里有几组实测经验值参数组合训练样本单次核矩阵耗时典型精度0-vs-12 比特, reps160约 30 秒97% 左右4 比特, reps1120约 3 分钟98%99%4 比特, reps2120约 8 分钟99% 左右6 比特, reps2120约 20 分钟以上可能反降reps增大意味着特征映射电路的表达复杂度上升但对核矩阵的影响并不是单调的。reps 太大编码角度在深电路里产生复杂的干涉样本间的保真度趋于随机核矩阵失去判别力精度反而掉下来。这个现象类似经典核里的过拟合只不过这里过拟合的是特征映射本身。选参数的顺序我一般是这样先固定 reps1 跑一遍确认精度然后加到 reps2 对比核矩阵热力图变化如果精度增益不到 1 个百分点就停在 reps1。因为每加一层 reps模拟器耗时是成倍涨的。4.3 惩罚系数C和核带宽被很多人忽略的两个旋钮QSVC里的C和经典 SVM 语义完全一致控制误分类惩罚强度。MNIST 0-vs-1 线性可分度高C 小一点0.11.0反而好太大容易把边界推向个别离群点。核函数的尺度由特征映射里的角度缩放系数控制但FidelityQuantumKernel默认不暴露这个系数需要你自己在喂数据时处理。常见做法是在数据预处理阶段给归一化后的特征乘一个缩放因子 β再传入量子核。这个 β 的作用类似 RBF 核里的 gamma控制角度旋转的幅度beta 0.8 X_scaled X_norm * beta kernel_beta FidelityQuantumKernel(feature_mapZZFeatureMap(feature_dimension4, reps1)) K_beta kernel_beta.evaluate(X_scaled)β 太小角度旋转不足所有样本的量子态差异小核矩阵各项都接近 1SVM 失去判别力β 太大角度旋转过度保真度快速衰减到接近 0核矩阵变得和随机噪声一样。理想的 β 让核矩阵的对角项接近 1、非对角项呈现清晰的分块结构。我通常会试 β 在 [0.5, 1.5] 里的几个值每次重新评估测试集精度选最高的。这个调参过程的成本比调reps低得多因为不需要改电路深度核矩阵计算时间基本不变。5. 量子SVM落地避坑我在手写体识别上踩过的6个坑5.1 现象训练集超过 200 个样本核矩阵算到天荒地老原因量子核矩阵要逐对样本计算保真度每个样本对都是一次完整电路采样复杂度是 O(N²) 乘以每次电路模拟的开销。200 个样本就是约 2 万次电路求值本地模拟器上跑几小时很正常。解决训练集控制在 60150 个样本把FidelityQuantumKernel的evaluate结果缓存到本地文件优先降低 reps 而不是降低样本数因为样本数减少对精度的影响通常比降低 reps 更明显。量子设备上的真实运行并不受这个限制但模拟器必须尊重这个规模约束。5.2 现象evaluate返回的核矩阵有负特征值QSVC 训练时报警原因量子核矩阵是通过有限次数采样的保真度估计构造的统计涨落让矩阵偏离严格正定。这是采样噪声不是 bug。解决对核矩阵做正则化处理加一个小的对角扰动。qiskit 内部处理了一部分但自己拿到矩阵做调试时用K np.eye(K.shape[0]) * 1e-6能缓解绝大多数数值问题。更彻底的做法是提高采样的shots数让保真度估计更精确代价是耗时增加。5.3 现象模拟器上 99% 的精度换到真实量子硬件上掉到 80% 以下原因真实硬件有门噪声、测量噪声和退相干保真度估计被噪声污染模拟器是零噪声的理想环境精度是上限值。解决跑真机前先做噪声感知验证用带噪声的模拟器比如 qiskit 的 noise model对同样的流程测一遍区分有多少精度损失来自算法本身、多少来自噪声。真机上还需要选entanglement映射到硬件拓扑上全连接的full映射到稀疏拓扑时电路会被大量 SWAP 门撑爆所以真机实验务必用linear或直接检查硬件的耦合图再定。5.4 现象PCA 降到 4 维后0-vs-1 分类精度还行换 3-vs-9 精度直线下滑原因3 和 9 的像素结构相近PCA 是线性降维区分这类相似数字需要的高阶特征被 PCA 丢弃了。量子特征映射只拿 4 个编码角度信息量根本不够。解决换非线性降维方式比如用 t-SNE 或 UMAP 降到 4 维再喂给量子核或者直接挑 8 类、把任务组建成多组二分类每组用不同的降维。从我试过的结果看UMAP 保住的局部结构比 PCA 更适合喂量子特征映射但 UMAP 本身有随机性每次跑要固定随机种子。5.5 现象经典 RBF-SVM 用同样训练集跑了 99%量子核 SVM 只有 97%被吊打原因MNIST 的 0-vs-1 二分类对经典核来说太简单了RBF 核在这个低维子空间上已经完全够用。量子核的优势场景是高维相关结构和经典核难以表达的数据分布而不是这种简单可分任务。解决不要单纯用 MNIST 二分类去论证量子 SVM 强于经典 SVM。改成多分类、降维到 4 维的困难类别对、或者加入人工构造的非线性特征让经典 RBF 核先暴露局限再对比量子核。这个做法也是项目汇报里最容易被导师追问的地方提前准备对比数据比临时补实验靠谱得多。5.6 现象核矩阵热力图看起来有分块结构但精度就是上不去原因保真度估计的采样噪声让小块之间的边界模糊SVM 的决策边界被噪声带偏或者 β 缩放不合适核矩阵动态范围不够SVM 对数值尺度敏感。解决先画核矩阵热力图检查两类之间是否呈现明显的深色对角块 浅色非对角块没有分块就调 β有分块但精度低就提升shots到 8192 以上再跑一遍。热力图是量子核调试里最快的信息来源不要跳过这步直接调 C 和 reps否则纯属盲调。6. 最后一步用对比实验验证量子SVM的价值而不是只看精度6.1 用同一套训练集跑三个基线精度数字单独看没意义量子 SVM 的价值必须放到对比里才立得住。我在交付项目时一定会跑三组线性 SVM、RBF-SVM、量子核 SVM全部用相同的训练/测试切分然后记录精度、支持向量数、训练耗时三列数据。如果量子核在 MNIST 二分类上输了 RBF不要焦虑把对比表原样写进文档用水分析解释为什么这个任务对量子核不友好。6.2 可视化量子核矩阵验证特征映射是否在认真工作核矩阵热力图是判断量子核有没有学到结构的标准手段import seaborn as sns K_test quantum_kernel.evaluate(X_test) plt.figure(figsize(6, 5)) sns.heatmap(K_test, cmapviridis, xticklabelsFalse, yticklabelsFalse) plt.title(Quantum Kernel Matrix on Test Set) plt.show()理想的热力图应该出现两个对角块同一类样本对内的核值高跨类样本对的核值低。如果热力图一片均匀或者棋盘状混乱说明特征映射或 β 没调对先回去改参数而不是继续调 SVM 的 C。6.3 一个值得保持的习惯跑量子 SVM 项目我慢慢养成一个习惯每改一个参数立刻把核矩阵导出一份存成.npy用文件名记录当时的特征映射、reps、β 和精度。因为量子核矩阵重算一次太贵了几小时模拟器跑出来的矩阵删了再想复现就得重新排队。这个文件就是你的后悔药后面写文档、画对比图、应付导师追问全都从这些缓存矩阵里取数。希望这个方向能帮你把 SVM 和量子计算这两块真正串起来就算最后发现量子核在这个任务上没赢过 RBF你也比大多数人更清楚输在哪——这本身就是做这个项目最值钱的收获。本文还有配套的精品资源点击获取
返回列表