量子神经网络

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

经典神经网络

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

参数化量子线路

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

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

纠缠层的连接方法

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

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

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

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

用测量算子Z测量 ,测量的平均值为,由于

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

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

目标函数与优化

测量得到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,实施参数化量子线路,这里共有五层,generate的定义在80到83行。注意第二步使用的Ry不是系统自带的Ry而是在31到42行自定义的Ry。而求解梯度​​​​​​​ 就是求解内积的实部,在代码的153到165行。

参考

1.MindSpore

相关推荐
szxinmai主板定制专家3 分钟前
【国产NI替代】基于FPGA的32通道(24bits)高精度终端采集核心板卡
大数据·人工智能·fpga开发
海棠AI实验室6 分钟前
AI的进阶之路:从机器学习到深度学习的演变(三)
人工智能·深度学习·机器学习
机器懒得学习17 分钟前
基于YOLOv5的智能水域监测系统:从目标检测到自动报告生成
人工智能·yolo·目标检测
QQ同步助手32 分钟前
如何正确使用人工智能:开启智慧学习与创新之旅
人工智能·学习·百度
AIGC大时代35 分钟前
如何使用ChatGPT辅助文献综述,以及如何进行优化?一篇说清楚
人工智能·深度学习·chatgpt·prompt·aigc
流浪的小新40 分钟前
【AI】人工智能、LLM学习资源汇总
人工智能·学习
martian6652 小时前
【人工智能数学基础篇】——深入详解多变量微积分:在机器学习模型中优化损失函数时应用
人工智能·机器学习·微积分·数学基础
人机与认知实验室3 小时前
人、机、环境中各有其神经网络系统
人工智能·深度学习·神经网络·机器学习
黑色叉腰丶大魔王3 小时前
基于 MATLAB 的图像增强技术分享
图像处理·人工智能·计算机视觉
迅易科技6 小时前
借助腾讯云质检平台的新范式,做工业制造企业质检的“AI慧眼”
人工智能·视觉检测·制造