《昇思25天学习打卡营第15天|通过量子神经网络对鸢尾花进行分类》

概述

量子神经网络是一类将人工神经网络与量子计算相结合的算法。在经典神经网络中,人们以类似人脑神经系统的网状结构作为计算模型,对特定问题进行预测,并根据真实结果对神经元的参数进行优化,反复迭代直到模型能较为准确的预测结果。而在量子线路中,我们同样可以搭建出类似的网状结构,并将其中一些含参数的门作为神经元,然后我们可以测量出相关哈密顿量的期望值作为损失函数,对门参数进行优化,直到找出最优参数。这样,我们就训练出了一个量子神经网络。量子并行性或量子纠缠有可能为量子神经网络带来额外的优势,但目前还没有证据表明量子神经网络相比经典神经网络具有优越性。一个典型的量子神经网络包含 Encoder(编码层)和 Ansatz(训练层),Encoder 可以将经典数据编码到量子态中,常见的编码方式有振幅编码、相位编码和IQP编码等。Ansatz可以根据输入给出预测结果,常见的 Ansatz 有 Hardware Efficient AnsatzStrongly Entangling Ansatz 等。

在之前的案例中,我们介绍了什么是变分量子线路,并通过一个简单的例子体验了如何搭建量子神经网络来解决一个小问题。在本文档中,我们将体验升级,将会介绍如何通过搭建量子神经网络来解决经典机器学习中的问题。我们选取的问题是:监督学习中的鸢尾花分类问题。

问题描述:鸢尾花(iris)数据集是经典机器学习中常用的数据集,该数据集总共包含150个样本(分为3种不同的亚属:山鸢尾(setosa)、杂色鸢尾(versicolor)和维吉尼亚鸢尾(virginica),每个亚属各有50个样本),每个样本包含4个特征,分别为花萼长度(sepal length)、花萼宽度(sepal width)和花瓣长度(petal length)、花瓣宽度(petal width)。

我们选取前100个样本(山鸢尾(setosa)和杂色鸢尾(versicolor)),并随机抽取80个样本作为训练集,通过搭建量子神经网络对量子分类器(Ansatz)进行训练,学习完成后,对剩余的20个样本进行分类测试,期望预测的准确率尽可能高。

思路:我们需要将100个样本进行划分,分成80个训练样本和20个测试样本,根据训练样本的经典数据计算搭建Encoder所需的参数,然后,搭建Encoder,将训练样本的经典数据编码到量子态上,接着,搭建Ansatz,通过搭建的量子神经网络层和MindSpore的算子对Ansatz中的参数进行训练,进而得到最终的分类器,最后,对剩余的20个测试样本进行分类测试,得到预测的准确率。

环境准备

首先,我们需要导入鸢尾花的数据集,而在导入该数据集前,我们需要使用sklearn库中的datasets模块,因此读者需要检查是否安装了sklearn库,可执行如下代码进行安装。

pip show scikit-learn

若无报错,则表明已安装。简单说明一下,sklearn是scikit-learn的简称,是一个基于Python的第三方模块。sklearn库集成了一些常用的机器学习方法,在进行机器学习任务时,并不需要实现算法,只需要简单的调用sklearn库中提供的模块就能完成大多数的机器学习任务。

若未安装sklearn库,则可通过运行如下代码来安装。

pip install scikit-learn

从上述打印可以看到,该数据集共有150个样本,每个样本均有4个特征,分别为花萼长度(sepal length)、花萼宽度(sepal width)和花瓣长度(petal length)、花瓣宽度(petal width)。同时样本包含3种不同的亚属:山鸢尾(setosa)、杂色鸢尾(versicolor)和维吉尼亚鸢尾(virginica),每个样本有对应的分类编号,0表示样本属于setosa,1表示样本属于versicolor,2表示样本属于virginica,因此有一个由150个数字组成的数组来表示样本的亚属类型。

由于我们只选取前100个样本,因此执行如下命令。

从上述打印可以看到,此时的数据集X中只有100个样本,每个样本依然有4个特征,仍为花萼长度(sepal length)、花萼宽度(sepal width)和花瓣长度(petal length)、花瓣宽度(petal width)。此时只有2种不同的亚属:山鸢尾(setosa)和杂色鸢尾(versicolor),并且每一个样本有对应的分类编号,0表示它属于setosa,1表示它属于versicolor,因此有一个由100个数字组成的数组来表示样本的亚属类型。

数据图像化

为了更加直观地了解这100个样本组成的数据集,我们画出所有样本不同特征之间组成的散点图,执行命令。

从上述呈现的图像可以看到,红色的点表示标签为“0”的样本,绿色的点表示标签为“1”的样本,另外,我们发现,这两类样本的不同特征还是比较容易区分的。

数据预处理

接下来,我们需要计算生成搭建Encoder时所要用到的参数,然后将数据集划分为训练集和测试集,执行如下命令。

从上述打印可以看到,此时的数据集X中仍有100个样本,但此时每个样本却有7个特征,前4个特征值就是原来的特征值,后3个特征值就是通过上述预处理计算得到的特征值,其具体计算公式如下:

𝑋𝑗𝑖+4=𝑋𝑗𝑖∗𝑋𝑗𝑖+1,𝑖=0,1,2,𝑗=1,2,...,100.𝑋𝑖+4𝑗=𝑋𝑖𝑗∗𝑋𝑖+1𝑗,𝑖=0,1,2,𝑗=1,2,...,100.

最后,我们将此时的数据集分为训练集和测试集,执行如下命令。

从上述打印可以看到,此时的训练集有80个样本,测试集有20个样本,每个样本均有7个特征。

说明:

(1)append主要用于为原始数组添加一些值,一般格式如下:np.append(arr, values, axis=None),arr是需要被添加值的数组,values就是添加到数组arr中的值,axis表示沿着哪个方向;

(2)shuffle=True表示将数据集打乱,每次都会以不同的顺序返回, shuffle就是为了避免数据投入的顺序对网络训练造成影响。增加随机性,提高网络的泛化性能,避免因为有规律的数据出现,导致权重更新时的梯度过于极端,避免最终模型过拟合或欠拟合。

(3)train_test_split是交叉验证中常用的函数,主要用于是从样本中随机地按比例选取训练数据集和测试数据集,一般格式如下: X_train, X_test, y_train, y_test = train_test_split(X, y, test_size, random_state, shuffle=True),其中test_size表示测试样本的比例,random_state表示产生随机数的种子,shuffle=True表示将数据集打乱。

搭建Encoder

根据图示的量子线路图,我们可以在MindSpore Quantum中搭建Encoder,将经典数据编码到量子态上。

encoder classification of iris by qnn

在这里,我们采用的编码方式是IQP编码(Instantaneous Quantum Polynomial encoding),一般来说Encoder的编码方式不固定,可根据问题需要选择不同的编码方式,有时也会根据最后的性能对Encoder进行调整。

从对Encoder的Summary中可以看到,该量子线路由17个量子门组成,其中有7个含参量子门且参数为𝛼0,𝛼1,...,𝛼6𝛼0,𝛼1,...,𝛼6,该量子线路调控的量子比特数为4。

说明:

UN模块用于将量子门映射到不同的目标量子比特和控制量子比特,一般格式如下:mindquantum.circuit.UN(gate, maps_obj, maps_ctrl=None),括号中的gate是我们需要执行的量子门,maps_obj是需要执行该量子门的目标量子比特,maps_ctrl是控制量子比特,若为None即无控制量子位。若每个量子比特位执行同一个非参数量子门,则可以直接写出UN(gate, N)N表示量子比特个数。

搭建Ansatz

根据图示的量子线路图,我们可以在MindSpore Quantum中搭建Ansatz。

ansatz classification of iris by qnn

与Encoder一样,Ansatz的编码方式也不固定,我们可以尝试不同的编码方式来测试最后的结果。

在这里,我们采用的是 HardwareEfficientAnsatz,即上述量子线路图所示的编码方式。

从对Ansatz的Summary中可以看到,该量子线路由25个量子门组成,其中有16个含参量子门且参数为d2_n3_0, d1_n1_0, d0_n2_0, d1_n0_0, d3_n2_0, d2_n2_0, d0_n1_0, d3_n1_0, d2_n0_0, d3_n0_0...,该量子线路调控的量子比特数为4。

说明:

HardwareEfficientAnsatz是一种容易在量子芯片上实现的Ansatz,其量子线路图由红色虚线框内的量子门组成,一般格式如下:mindquantum.ansatz.HardwareEfficientAnsatz(n_qubits, single_rot_gate_seq, entangle_gate=X, entangle_mapping="linear", depth=1),括号中的 n_qubits 表示ansatz需要作用的量子比特总数,single_rot_gate_seq 表示一开始每一位量子比特执行的参数门,同时后面需要执行的参数门也固定了,只是参数不同,entangle_gate=X 表示执行的纠缠门为X,entangle_mapping="linear" 表示纠缠门将作用于每对相邻量子比特,depth 表示黑色虚线框内的量子门需要重复的次数。

那么完整的量子线路就是Encoder加上Ansatz。这里我们调用量子线路的 as_encoder 将量子线路中的所有参数设置为编码参数,调用 as_ansatz 将量子线路中的所有参数设置为待训练参数。

从对完整的量子线路的Summary中可以看到,该量子线路由42个量子门组成,其中有23个含参量子门且参数为𝛼0,𝛼1,...,𝛼6𝛼0,𝛼1,...,𝛼6和d2_n3_0, d1_n1_0, d0_n2_0, d1_n0_0, d3_n2_0, d2_n2_0, d0_n1_0, d3_n1_0, d2_n0_0, d3_n0_0...,该量子线路调控的量子比特数为4。

构建哈密顿量

我们分别对第2位和第3位量子比特执行泡利Z算符测量,构建对应的哈密顿量

从上述打印可以看到,此时构建的哈密顿量有2个,分别为对第2位和第3位量子比特执行泡利Z算符,且将系数都设为1。通过泡利Z算符测量,我们可以得到2个哈密顿量测量值,若第1个测量值更大,则会将此样本归类到标签为“0”的类,同理,若第2个测量值更大,则会将此样本归类到标签为“1”的类。通过神经网络的训练,期望训练样本中标签为“0”的样本的第1个测量值更大,而标签为“1”的样本的第2个测量值更大,最后应用此模型来预测新样本的分类。

搭建量子神经网络

从上述打印可以看到,我们已经成功搭建了量子机器学习层,其可以无缝地跟MindSpore中其它的算子构成一张更大的机器学习网络。

说明:

MindSpore是一个全场景深度学习框架,旨在实现易开发、高效执行、全场景统一部署三大目标,提供支持异构加速的张量可微编程能力,支持云、服务器、边和端多种硬件平台.

训练

接下来,我们需要定义损失函数,设定需要优化的参数,然后将搭建好的量子机器学习层和MindSpore的算子组合,构成一张更大的机器学习网络,最后对该模型进行训练。

可以看到,20次迭代后,损失值不断下降并趋于稳定,最后收敛于约0.395。

说明:

(1)nn.SoftmaxCrossEntropyWithLogits 可以计算数据和标签之间的softmax交叉熵。使用交叉熵损失测量输入(使用softmax函数计算)的概率和目标之间的分布误差,其中类是互斥的(只有一个类是正的),一般格式如下:mindspore.nn.SoftmaxCrossEntropyWithLogits(sparse=False, reduction="none")sparse=False 表示指定标签是否使用稀疏格式,默认值: Falsereduction="none"表示适用于损失的减少类型。可选值为"mean""sum""none"。如果为"none",则不执行减少,默认值:"none"

(2)Adam 模块通过自适应矩估计算法更新梯度,可以优化Ansazt中的参数,输入的是神经网络中可训练的参数;一般格式如下:nn.Adam(net.trainable_params(), learning_rate=0.1),学习率可以自己调节;

(3)mindspore.train.Model 是用于训练或测试的高级 API,模型将层分组到具有训练和推理特征的对象中,一般格式如下:mindspore.train.Model(network, loss_fn=None, optimizer=None, metrics=None, eval_network=None, eval_indexes=None, amp_level="O0", acc_level="O0"),其中 network 就是我们要训练的网络即 Quantumnetloss_fn 即目标函数,在这里就是定义的loss函数;optimizer 即优化器,用于更新权重,在这里就是定义的opti;metrics 就是模型在训练和测试期间需要评估的字典或一组度量,在这里就是评估准确率;

(4)Accuracy 用于计算分类和多标签数据的准确率,一般格式如下:mindspore.train.Accuracy(eval_type="classification"),用于分类(单标签)和多标签(多标签分类)的数据集上计算准确率的度量,默认值:"classification"

(5)NumpySlicesDataset 使用给定的数据切片创建数据集,主要用于将Python数据加载到数据集中,一般格式如下:mindspore.dataset.NumpySlicesDataset(data, column_names=None, num_samples=None, num_parallel_workers=1, shuffle=None, sampler=None, num_shards=None, shard_id=None)

(6)Callback 用于构建回调类的抽象基类,回调是上下文管理器,在传递到模型时将输入和输出。你可以使用此机制自动初始化和释放资源。回调函数将执行当前步骤或数据轮回中的一些操作;

(7)LossMonitor 主要用于监控训练中的损失,如果损失是NAN或INF,它将终止训练,一般格式如下:mindspore.train.LossMonitor(per_print_times=1)per_print_times=1表示每秒钟打印一次损失,默认值:1

(8)train 方法用于训练模型,其中迭代由Python前端控制;当设置PyNative模式或CPU时,训练过程将在数据集不接收的情况下执行,一般格式如下:train(epoch, train_dataset, callbacks=None, dataset_sink_mode=True, sink_size=-1),其中epoch表示在数据上的总迭代次数;train_dataset就是我们定义的train_loadercallbacks就是我们需要回调的损失值和准确率;dataset_sink_mode表示确定是否通过数据集通道传递数据,文档中为False

训练过程中的准确率

我们已经看到损失值趋于稳定,那么我们还可以将模型在训练过程中的预测的准确率呈现出来,执行代码。

从上述打印的图像可以看到,在大约50步后,预测的准确率收敛于1,也就是说预测的准确率已经可以达到100%。

预测

最后,我们测试一下训练好的模型,将其应用在测试集上。

可以看到,预测分类结果和实际分类结果完全一致,模型预测的准确率达到了100%。

至此,我们体验了如何通过搭建量子神经网络来解决经典机器学习中的经典问题——鸢尾花分类问题。相信大家也对使用MindSpore Quantum有了更进一步的了解!期待大家挖掘更多的问题,充分发挥MindSpore Quantum强大的功能!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值