量子神经网络

news2024/11/26 16:12:29

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

      经典神经网络

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

      参数化量子线路

        参数化量子线路的一般形式,参数化量子线路通常由单量子比特旋转门和双量子比特纠缠门(受控非门、受控旋转门)按照一定的规律排列而成。其中参数化是指单量子比特旋转门或双量子比特纠缠门是含有可训练的参数的。例如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.coloradmin.cn/o/2247929.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

非交换几何与黎曼ζ函数:数学中的一场革命性对话

非交换几何与黎曼ζ函数&#xff1a;数学中的一场革命性对话 非交换几何&#xff08;Noncommutative Geometry, NCG&#xff09;是数学的一个分支领域&#xff0c;它将经典的几何概念扩展到非交换代数的框架中。非交换代数是一种结合代数&#xff0c;其中乘积不是交换性的&…

VUE3项目 关于金额:分转化为元 ;元转化为分;

1.在components 文件夹下新建moneyHandle.ts 文件 2.ts文件中写如下代码&#xff08;保留两位小数&#xff09; //分转化为元 - 正则解决精度 export const regFenToYuan (fen:any) >{var num fen;numfen*0.01;num;var reg num.indexOf(.) >-1 ? /(\d{1,3})(?(?:…

从0开始学习Linux——搭建自己的专属Linux系统

温馨提示本篇文章字数超过5000字&#xff01; 往期目录&#xff1a; 1、从0开始学习Linux——Linux简介&安装https://blog.csdn.net/diamond_5446/article/details/141190487 上一个章节我们简单了解了Linux&#xff0c;并且安装好了虚拟机以及下载好了Centos镜像&#…

《硬件架构的艺术》笔记(五):低功耗设计

介绍 能量以热量形式消耗&#xff0c;温度升高芯片失效率也会增加&#xff0c;增加散热片或风扇会增加整体重量和成本&#xff0c;在SoC级别对功耗进行控制就可以减少甚至可能消除掉这些开支&#xff0c;产品也更小更便宜更可靠。本章描述了减少动态功耗和静态功耗的各种技术。…

浅谈网络 | 传输层之TCP协议

目录 TCP 包头格式TCP 的三次握手TCP 的四次挥手TCP 的可靠性与"靠谱"的哲学TCP流量控制TCP拥塞控制 上一章我们提到&#xff0c;UDP 就像我们小时候一样简单天真&#xff0c;它相信“网之初&#xff0c;性本善&#xff0c;不丢包&#xff0c;不乱序”&#xff0c;因…

华为无线AC+AP组网实际应用小结

之前公司都是使用的H3C的交换机、防火墙以及无线AC和AP的&#xff0c;最近优化下无线网络&#xff0c;说新的设备用华为的&#xff0c;然后我是直到要部署的当天才知道用华为设备的&#xff0c;就很无语了&#xff0c;一点准备没有&#xff0c;以下为这次的实际操作记录吧&…

七、SElinux

一、SElinux简介 SELinux是Security-Enhanced Linux的缩写&#xff0c;意思是安全强化的linuxSELinux 主要由美国国家安全局(NSA)开发&#xff0c;当初开发的目的是为了避免资源的误用传统的访问控制在我们开启权限后&#xff0c;系统进程可以直接访问当我们对权限设置不严谨时…

Paddle Inference部署推理(一)

一&#xff1a;Paddle Inference推理 简介 Paddle Inference 是飞桨的原生推理库&#xff0c;提供服务器端的高性能推理能力。由于 Paddle Inference 能力直接基于飞桨的训练算子&#xff0c;因此它支持飞桨训练出的所有模型的推理。 Paddle Inference 功能特性丰富&#xff…

【数据分享】2001-2023年我国30米分辨率冬小麦种植分布栅格数据(免费获取)

小麦、玉米、水稻等各类农作物的种植分布数据在农业、环境、国土等很多专业都经常用到&#xff01; 本次给大家分享的是我国2001-2023年逐年的30米分辨率冬小麦种植分布栅格数据&#xff01;数据格式为TIFF格式&#xff0c;数据坐标为GCS_WGS_1984。该数据包括我国11个省份的冬…

类和对象plus版

一.类的定义 1.1类定义的格式 图中class为关键字&#xff0c;Stack为类的名字&#xff0c;用{}框住类的主体&#xff0c;类定义完后&#xff1b;不能省略。 为了区分成员变量&#xff0c;一般习惯在成员变量前面或后面加一个特殊标识&#xff0c;_或者m_ 1.2访问限定符 c采用…

jquery-picture-cut 任意文件上传(CVE-2018-9208)

目录 1、漏洞描述 2、访问ip&#xff1a;port 3、一句话木马&#xff1a;exploit.php 4、上传一句话木马 5、中国蚁剑连接成功 6、拿到flag 1、漏洞描述 jQuery是一个快速、简洁的JavaScript框架&#xff0c;是继Prototype之后又一个优秀的JavaScript代码库&#xff08;框…

【Spring Boot】# 使用@Scheduled注解无法执行定时任务

1. 前言 在 Spring Boot中&#xff0c;使用Scheduled注解来定义定时任务时&#xff0c;定时任务不执行&#xff1b;或未在规定时间执行。 import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component;Component public c…

LM2904运算放大器的应用:测电池电压

在电子设备的广泛应用中&#xff0c;电池作为便携设备的能量来源&#xff0c;其电压监测显得尤为关键。LM2904作为一款低功耗、高增益带宽积和高共模抑制比的双运算放大器&#xff0c;非常适用于电池电压的测量与监测。本文详细介绍了LM2904在电池电压测量方面的应用&#xff0…

电子学习中的关键游戏化元素

游戏化彻底改变了电子学习领域&#xff0c;提供了一种使学习具有吸引力、互动性和有效性的方法。通过将类似游戏的功能集成到教育平台中&#xff0c;教育工作者可以增强动力&#xff0c;提高知识记忆&#xff0c;并创造动态的学习体验。游戏化的关键要素为设计与学习者产生共鸣…

【网络通信】数据集合集!

本文将为您介绍经典、热门的数据集&#xff0c;希望对您在选择适合的数据集时有所帮助。 1 RITA 更新时间&#xff1a;2024-11-22 访问地址: GitHub 描述&#xff1a; RITA 是一个用于网络流量分析的开源框架。 该框架以 TSV 或 JSON 格式提取 Zeek 日志&#xff0c;目前支…

竞赛经验:关于不记得字母表,如何知道字母顺序qwq

利用ASCII码算出码值再转成字符即可 #include <bits/stdc.h> using namespace std;int main() {for(int i 1; i < 30; i){cout << char(ai) << ;} }结果&#xff1a; ps:大意了&#xff0c;本想用电脑目录&#xff0c;但没考虑到会有文件不存在导致缺…

GitLab指定用户分配合并权限

进入项目 -》 Project Settings Repository -》展开 Protected branches -》 添加要保护的分支&#xff0c;设置角色 管理用户角色权限 查看到不同用户的角色&#xff0c;一般设置Developer只有Merger Request权限&#xff0c;Maintainer还有Merge审批权限 GitLab 中的权限…

C语言菜鸟入门·关键字·union的用法

目录 1. 简介 2. 访问成员 2.1 声明 2.2 赋值 3. 共用体的大小 4. 与typedef联合使用 5. 更多关键字 1. 简介 共用体&#xff08;union&#xff09;是一种数据结构&#xff0c;它允许在同一内存位置存储不同的数据类型&#xff0c;但每次只能存储其中一种类型的…

[C++]了解内置类型升级

内置类型升级 1.调用模板T时&#xff0c;为什么可以使用T()类型的匿名对象来传参2.内置类型被升级成为类后的使用事项 1.调用模板T时&#xff0c;为什么可以使用T()类型的匿名对象来传参 当我们在定义或声明一个函数时&#xff0c;如果想使用模板T类型的默认构造&#xff08;例…

JavaScript的基础数据类型

一、JavaScript中的数组 定义 数组是一种特殊的对象&#xff0c;用于存储多个值。在JavaScript中&#xff0c;数组可以包含不同的数据类型&#xff0c;如数字、字符串、对象、甚至其他数组。数组的创建有两种常见方式&#xff1a; 字面量表示法&#xff1a;let fruits [apple…