当前位置: 首页 > article >正文

量子神经网络

        感知机只是一个神经元,若有多个神经元共同作用,则构成神经网络。目前,最常见的量子神经网络模型为基于参数化量子线路的量子神经网络,该模型用参数化量子线路代替神经网络结构,使用经典优化算法更新参数化量子线路的参数。

      经典神经网络

        用一个空心圆圈表示一个神经元,每层神经元通过权重系数与下一层神经元进行全互连,神经元之间不存在同层连接,也不存在跨层连接,这种神经网络模型称为多层前馈神经网络。输入层神经元仅用于接受外界的信号,组成隐含层与输出层的神经元称为功能神经元,也就是可以接受信号并对其处理的神经元,每个功能神经元都有自己的阈值。神经网络的学习过程就是根据训练数据来调整神经元之间的权重系数以及每个功能神经元的网络。

      参数化量子线路

        参数化量子线路的一般形式,参数化量子线路通常由单量子比特旋转门和双量子比特纠缠门(受控非门、受控旋转门)按照一定的规律排列而成。其中参数化是指单量子比特旋转门或双量子比特纠缠门是含有可训练的参数的。例如R_{x}\left ( \theta \right )R_{y}\left ( \theta \right )R_{z}\left ( \theta \right )含有参数\theta

 旋转层由旋转门U0(θ0), U1(θ1), …, Um−1(θm−1)组成,纠缠层(记为Um)由CNOT门组成

纠缠层的连接方法

参数化量子线路不单独运行,需要与经典的方法相结合。

参数化量子线路所表示的函数

        参数化量子线路所表示的函数与测量算子有关,此处用Z算子。对只包含一个旋转层和一个纠缠层的单层参数化量子线路,记

经过酉变换U(θ)的量子态为

用测量算子Z测量 |\Psi (x,\theta )\rangle,测量的平均值为\langle|\Psi (x,\theta) |Z|\Psi (x,\theta )\rangle,由于

因此,可以通过测量得到0的概率算出

                        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        \langle|\Psi (x,\theta) |Z|\Psi (x,\theta )\rangle

目标函数与优化

测量得到0的概率为

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        

定义样本预测标签的计算公式为

            ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        

记样本x的真实标签为y(x),量子神经网络的目标是找到合适的参数θ和偏置b使得预测标签和真实标签尽量一致

因此优化目标为最小化损失函数

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​         ​​​​​​​        

带动小批量的随机梯度下降法

#量子神经网络
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, transpile
from qiskit_aer import Aer
import numpy as np
from qiskit.visualization import plot_histogram
from qiskit.circuit.library import UnitaryGate
from math import pi

import numpy as np

#将一个数据的四维归一化特征转化为三个特征角度
def convertDataToAngles(data):
    prob1 = data[2] ** 2 + data[3] ** 2
    prob0 = 1 - prob1
    angle1 = 2 * np.arcsin(np.sqrt(prob1))
    prob1 = data[3] ** 2 / prob1
    angle2 = 2 * np.arcsin(np.sqrt(prob1))
    prob1 = data[1] ** 2 / prob0
    angle3 = 2 * np.arcsin(np.sqrt(prob1))
    return np.array([angle1, angle2, angle3])

#使用三个特征角度在两个量子比特上编码
def encodeData(qc, qreg, angles):
    qc.ry(angles[0], qreg[1])
    qc.cry(angles[1], qreg[1], qreg[0])
    qc.x(qreg[1])
    qc.cry(angles[2], qreg[1], qreg[0])
    qc.x(qreg[1])

#定义G门
def RyGate(qc, qreg, params):
    """
    [cos(α), sin(α)]
    [-sin(α), cos(α)]
    """
    u00 = np.cos(params[0]/2)
    u01 = np.sin(params[0]/2)
    gateLabel = "Ry({})".format(
        params[0]
    )
    RyGate = UnitaryGate(np.array(
        [[u00, -u01], [u01, u00]]
    ), label=gateLabel)
    return RyGate

#由G门组成的训练层
def GLayer(qc, qreg, params):
    for i in range(2):
        qc.append(RyGate(qc, qreg, params[i]), [qreg[i]])

#由CG门组成的训练层
def CGLayer(qc, qreg, anc, params):
    for i in range(2):
        qc.append(RyGate(
            qc, qreg, params[i]
        ).control(1), [anc[0], qreg[i]])

#由CX门组成的训练层
def CXLayer(qc, qreg, order):
    if order:
        qc.cx(qreg[0], qreg[1])
    else:
        qc.cx(qreg[1], qreg[0])

#由CCX门组成的训练层
def CCXLayer(qc, qreg, anc, order):
    if order:
        qc.ccx(anc[0], qreg[0], qreg[1])
    else:
        qc.ccx(anc[0], qreg[1], qreg[0])

#由G层和CX层组成的量子神经网络
def generateU(qc, qreg, params):
    for i in range(params.shape[0]):
        GLayer(qc, qreg, params[i])
        CXLayer(qc, qreg, i % 2)

#量子神经网络训练线路
def generateCU(qc, qreg, anc, params):
    for i in range(params.shape[0]):
        CGLayer(qc, qreg, anc, params[i])
        CCXLayer(qc, qreg, anc, i % 2)

#测量预测结果的概率
def getPrediction(qc, qreg, creg, backend):
    qc.measure(qreg[0], creg[0])
    transpiled_qc = transpile(qc, backend)
    # Run the transpiled circuit
    job = backend.run(transpiled_qc, shots=1000)
    results = job.result().get_counts(qc)
    # Get and plot the results
    
    if '1' in results.keys():
        return results['1'] / 1000
    else:
        return 0

#根据预测结果的概率对其进行分类
def convertToClass(predictions):
    return (predictions >= 0.5) * 1

#计算损失函数
def cost(labels, predictions):
    loss = 0
    for label, pred in zip(labels, predictions):
        loss += (pred - label) ** 2
    return loss / 2

#求准确率
def accuracy(labels, predictions):
    acc = 0
    for label, pred in zip(labels, predictions):
        if label == pred:
            acc += 1
    return acc / labels.shape[0]

#计算神经网络向前传播的结果
def forwardPass(params, bias, angles, backend):
    qreg = QuantumRegister(2)
    anc = QuantumRegister(1)
    creg = ClassicalRegister(1)
    qc = QuantumCircuit(qreg, anc, creg)
    encodeData(qc, qreg, angles)
    generateU(qc, qreg, params)
    qc.z(qreg[0])
    pred = getPrediction(qc, qreg, creg, backend) + bias
    return pred

#求解梯度的量子线路
def computeRealExpectation(params1, params2, angles, backend):
    qreg = QuantumRegister(2)
    anc = QuantumRegister(1)
    creg = ClassicalRegister(1)
    qc = QuantumCircuit(qreg, anc, creg)
    encodeData(qc, qreg, angles)
    qc.h(anc[0])
    generateCU(qc, qreg, anc, params1)
    qc.cz(anc[0], qreg[0])
    qc.x(anc[0])
    generateCU(qc, qreg, anc, params2)
    qc.x(anc[0])
    qc.h(anc[0])
    prob = getPrediction(qc, anc, creg, backend)
    return 2 * (prob - 0.5)

#求解量子线路参数的梯度
def computeGradient(params, angles, label, bias, backend):
    prob = forwardPass(params, bias, angles, backend)
    gradients = np.zeros_like(params)
    for i in range(params.shape[0]):
        for j in range(params.shape[1]):
            newParams = np.copy(params)
            newParams[i, j, 0] += np.pi / 2
            gradients[i, j, 0] = computeRealExpectation(
                params, newParams, angles, backend
            )
            newParams[i, j, 0] -= np.pi / 2
    biasGrad = (prob + bias - label)
    return gradients * biasGrad, biasGrad

#更新量子线路的参数
def updateParams(params, prevParams, grads, learningRate, momentum,v1):
    v1=momentum*v1-learningRate*grads
    paramsNew = np.copy(params)
    paramsNew = params +v1
    return paramsNew, params,v1

#训练网络的过程
def trainNetwork(data, labels, backend):
    np.random.seed(1)
    numSamples = labels.shape[0]
    #取前75个作训练数据集,后25个作验证数据集
    numTrain = int(numSamples * 0.75)
    #将100个原始数据打乱
    ordering = np.random.permutation(range(numSamples))
    #训练数据集
    trainingData = data[ordering[:numTrain]]
    trainingData = trainingData.astype(np.float32)
    #验证数据集
    validationData = data[ordering[numTrain:]]
    validationData = validationData.astype(np.float64)
    #训练集数据标签
    trainingLabels = labels[ordering[:numTrain]]
    #验证集数据标签
    validationLabels = labels[ordering[numTrain:]]
    #确定神经网络参数个数,从而确定神经网络层数,这里为5层
    params = 2*np.random.sample((5, 2, 1))   #两个权重一个偏置
    #偏移量
    bias = 0.01
    prevParams = np.copy(params)
    prevBias = bias
    #每一次训练的数据量
    batchSize = 5
    #定义动量
    momentum = 0.9
    v1=0
    v2=0
    #学习率
    learningRate = 0.02

    #进行15次迭代
    for iteration in range(20):
    # 计算批次的起始位置
        samplePos = iteration * batchSize
    # 检查是否还有足够的样本来形成一个完整的批次
        if samplePos + batchSize <= numTrain:
        # 每一次迭代训练数据集(5个)
            batchTrainingData = trainingData[samplePos:samplePos + batchSize]
        # 每一次迭代训练数据集标签(5个)
            batchLabels = trainingLabels[samplePos:samplePos + batchSize]
        # ... 其余代码保持不变
       
        #记录此批次的梯度集
            batchGrads = np.zeros_like(params)
        #记录此批次偏移量
            batchBiasGrad = 0
        else:
        # 如果没有足够的样本,就退出循环
            break
    
        for i in range(batchSize):
            #求解梯度与偏移量
            grads, biasGrad = computeGradient(
                params, batchTrainingData[i], batchLabels[i], bias, backend
            )
            #求五次的平均梯度与平均偏移量
            batchGrads += grads / batchSize
            batchBiasGrad += biasGrad / batchSize
        #更新网络参数
        params, prevParams,v1= updateParams(
            params, prevParams, batchGrads, learningRate, momentum,v1
        )
        #更新偏移量
        temp = bias
        v2=v2*momentum-learningRate * batchBiasGrad
        bias += v2
        prevBias = temp
        trainingPreds = np.array([forwardPass(
            params, bias, angles, backend
        ) for angles in trainingData])
        #打印此批次训练的损失值
        print('Iteration {} | Loss: {}'.format(
            iteration + 1, cost(trainingLabels, trainingPreds)
        ))
    #使用验证数据集进行验证,保留量子测量结果
    validationProbs = np.array(
        [forwardPass(
            params, bias, angles, backend
        ) for angles in validationData]
    )
        
    #根据测量结果进行分类
    validationClasses = convertToClass(validationProbs)
    #求解平均准确率
    validationAcc = accuracy(validationLabels, validationClasses)
    prevalidationData=X[ordering[:numTrain]]
    intValidationLabels=[0 for i in range(len(validationLabels))]
    for i in range(len(validationLabels)):
        intValidationLabels[i]=int(validationLabels[i])
    print('Validation accuracy:', validationAcc)
    for x, y, p in zip(prevalidationData, intValidationLabels, validationClasses):
        print('Data:', x, '  Label:', y, '  Prediction:', p)
    return params,data[0]


#从附件中取数据集
data = np.genfromtxt("data3.csv", delimiter=",")
#从数据集中取特征
X = data[:, 0:4]
#对特征进行角度转换
features = np.array([convertDataToAngles(i) for i in X])
#取标签
Y = data[:, -1]
backend = Aer.get_backend('qasm_simulator')
#开始训练
params,angles=trainNetwork(features, Y, backend)

        图是参数化量子线路,对应代码的118到128行,这部分的代码由两部分组成:第一encodeData(qc.qreg.angles)将样本数据制备到量子态中,在代码的124行的定义在第23到29行。第二步用generateU,实施参数化量子线路U(\Theta ),这里U(\Theta )共有五层,generate的定义在80到83行。注意第二步使用的Ry不是系统自带的Ry而是在31到42行自定义的Ry。而求解梯度​​​​​​​ \frac{\partial \pi(\Theta ,b)}{\partial \Theta _{i}}=Re(\langle x |\frac{\partial \pi(\Theta )^{ +}}{\partial \Theta _{i}}ZU(\Theta )|x \rangle)就是求解\frac{\partial \pi(\Theta)}{\partial \Theta _{i}}ZU(\Theta )|x \rangle内积的实部,在代码的153到165行。

 

参考

1.MindSpore 


http://www.kler.cn/a/406373.html

相关文章:

  • 大数据新视界 -- 大数据大厂之 Impala 性能优化:跨数据中心环境下的挑战与对策(上)(27 / 30)
  • Parker派克防爆电机在实际应用中的安全性能如何保证?
  • 【大数据分析机器学习】分布式机器学习
  • Python创建虚拟环境报错:Error: Command......
  • 通过vite+vue3+pinia从0到1搭建一个uniapp应用
  • Linux-服务器辨别实体机OR虚拟机
  • Java 创建不可变集合
  • 浅谈丨功能安全测试,汽车的守护者
  • 40分钟学 Go 语言高并发:sync包详解(下)
  • 如何用通义灵码助力项目开发 | OceanBase obdiag 项目共建实践
  • 【大数据学习 | Spark-Core】Spark的分区器(HashPartitioner和RangePartitioner)
  • 大数据新视界 -- 大数据大厂之 Hive 数据导入:多源数据集成的策略与实战(上)(3/ 30)
  • xiaolin coding 图解网络笔记——HTTP篇
  • Antd中的布局组件
  • RecyclerView详解——(四)缓存复用机制
  • 论文阅读——Intrusion detection systems using longshort‑term memory (LSTM)
  • 儿童玩具安全检测GB6675标准详细介绍
  • PHP 8.4 重磅发布了
  • 如何创建你的第一个 Telegram 机器人:一步步教程
  • 【Python TensorFlow】进阶指南(续篇三)
  • STM32(hal库)中,为什么DMA没有MSP函数?
  • C# 中Timer的三种用法
  • 代码随想录1016-Day17
  • 【bug】python常见的错误以及解决办法
  • 大数据环境下的高效数据清洗策略
  • 【信息系统项目管理师】第2章:信息技术发展 考点梳理