• IBM Qiskit量子机器学习速成(一)


    声明:本篇笔记基于IBM Qiskit量子机器学习教程的第一节,中文版译文详见:https://blog.csdn.net/qq_33943772/article/details/129860346?spm=1001.2014.3001.5501

    概述

    首先导入关键的包

    from qiskit import QuantumCircuit
    from qiskit.utils import algorithm_globals
    from qiskit.circuit import Parameter, ParameterVector
    from qiskit.quantum_info import SparsePauliOp
    from qiskit_machine_learning.neural_networks import EstimatorQNN, SamplerQNN
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    尤其注意qiskit_machine_learning包需要额外安装(如果你是Anaconda用户,特别注意需要先激活相应虚拟环境),参考指令如下

    pip install qiskit_machine_learning
    
    • 1

    另外,由于接下来的程序中涉及随机数,我们需要指定全局的随机数种子:

    # qiskit_machine_learning需要另外安装
    algorithm_globals.random_seed = 42
    
    • 1
    • 2

    我们知道,机器学习的本质是确定问题本身的结构后对某些参数进行学习。例如,我们对人的身高和体重之间的关系很感兴趣,我们先假设二者之间存在线性关系 y = k x + b y=kx+b y=kx+b,也就是确定了二者之间的结构,从而对参数 k , b k,b k,b进行学习。而学习过程本身就是对参数的调节,使模型最大程度上符合问题的描述。

    一般而言,参数化的量子电路分为三个部分:

    • 数据加载:input
    • 数据处理:weight
    • 测量结果

    搭建神经网络

    一般而言,我们会用到两种量子神经网络,分别是EstimatorQNN和SamplerQNN。顾名思义,EstimatorQNN是用来“估计”某个算符的期望值的,而SamplerQNN是用来计算量子态的。

    例如,我们想估算某个力学量(比如说哈密顿量 H ^ \hat H H^)的期望值,我们就可以构建一个包含该哈密顿量 H ^ \hat H H^的EstimatorQNN。

    当我们对量子态的分布更感兴趣时,也就是,我们更感兴趣初始态经过电路的操作后会变成哪几种量子态(最简单的情形是加一个哈达玛门,从而结果是 ∣ 0 > + ∣ 1 > 2 \dfrac{\left|0\right>+\left|1\right>}{\sqrt 2} 2 0+1)。

    但是需要注意,在机器学习中,问题必须带有参数!我们可以这样理解SamplerQNN:通过调整电路中的某些参数,使得某些量子态的分布达到极大或极小。

    EstimatorQNN的创建

    EstimatorQNN创建时只需要以下几个部分:

    • 一个已经写好的参数化电路
    • 力学观测量(可选,如果不特别说明的话,其实计算的就是单位矩阵的期望值)
    • 输入参数(input_params)
    • 权重参数(weight_params)

    例如,我们可以通过以下方式创建参数(或参数向量)和参数化电路

    params1 = [Parameter("input1"), Parameter("weight1")]
    qc1 = QuantumCircuit(1)
    qc1.h(0)
    qc1.ry(params1[0], 0)
    qc1.rx(params1[1], 0)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    随后,通过泡利矩阵构造力学量(或可观测量)

    observable1 = SparsePauliOp.from_list([("Y" * qc1.num_qubits, 1)])
    
    • 1

    组合以上部分,直接写入参数,即可得到一个EstimatorQNN

    estimator_qnn = EstimatorQNN(
        circuit=qc1,
        observables=observable1,
        input_params=[params1[0]],
        weight_params=[params1[1]]
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    SamplerQNN的创建

    SamplerQNN创建时只需要以下几个参数:

    • 一个已经写好的参数化电路
    • 输入参数(input_params)
    • 权重参数(weight_params)

    可以看出,SamplerQNN也需要参数化电路(毕竟机器学习就是调节参数),它直接从末态读取结果(二进制字符串或非负整数)。不同的是,SamplerQNN提供interpret方法,你可以重写这个方法,来对结果进行解释。例如,QAOA中将结果解释为划分的区域。但是一旦外部重写interpret方法,必须显式指定
    output_shape,因为Qiskit无法自动推断结果。

    首先,声明输入和权重参数,并创建参数化电路。

    inputs2 = ParameterVector("input", 2)
    weights2 = ParameterVector("weight", 4)
    
    qc2 = QuantumCircuit(2)
    qc2.ry(inputs2[0], 0)
    qc2.ry(inputs2[1], 1)
    qc2.cx(0, 1)
    qc2.ry(weights2[0], 0)
    qc2.ry(weights2[1], 1)
    qc2.cx(0, 1)
    qc2.ry(weights2[2], 0)
    qc2.ry(weights2[3], 1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    进而创建SamplerQNN:

    sampler_qnn = SamplerQNN(circuit=qc2,
                             input_params=inputs2,
                             weight_params=weights2)
    
    • 1
    • 2
    • 3

    前向传播神经网络(运行神经网络)

    神经网络示意图

    当我们搭建好神经网络后,就需要执行神经网络了。一般来说,我们首先需要给定输入值和权重的初始值(注意,关键在于权重)。随后我们就可以获得运行的结果了。前向传播神经网络需要使用神经网络对象的forward方法

    初始化参数

    出于演示的目的,我们此处随机地设定输入值和权重值。

    estimator_qnn_input = algorithm_globals.random.random(estimator_qnn.num_inputs)
    estimator_qnn_weights = algorithm_globals.random.random(estimator_qnn.num_weights)
    sampler_qnn_input = algorithm_globals.random.random(sampler_qnn.num_inputs)
    sampler_qnn_weights = algorithm_globals.random.random(sampler_qnn.num_weights)
    
    • 1
    • 2
    • 3
    • 4

    数据的输入分为非分批输入(non-batched input)和分批输入(batched input)

    非分批输入

    非分批输入即直接输入全部参数,属于最简单、最直接的输入方式。当然,在数据集过大的情况下,这种输入方式不利于神经网络的训练。

    estimator_qnn_forward = estimator_qnn.forward(estimator_qnn_input, estimator_qnn_weights)
    print(
        f"Forward pass result for EstimatorQNN: {estimator_qnn_forward}. \nShape: {estimator_qnn_forward.shape}"
    )
    
    sampler_qnn_forward = sampler_qnn.forward(sampler_qnn_input, sampler_qnn_weights)
    print(
        f"Forward pass result for SamplerQNN: {sampler_qnn_forward}.  \nShape: {sampler_qnn_forward.shape}"
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    分批输入

    分批输入即将数据集先裁剪成适当大小(例如6x6、32x32大小的数据矩阵),再输入神经网络。

    estimator_qnn_forward_batched = estimator_qnn.forward(
        [estimator_qnn_input, estimator_qnn_input], estimator_qnn_weights
    )
    print(
        f"Forward pass result for EstimatorQNN: {estimator_qnn_forward_batched}.  \nShape: {estimator_qnn_forward_batched.shape}"
    )
    
    sampler_qnn_forward_batched = sampler_qnn.forward(
        [sampler_qnn_input, sampler_qnn_input], sampler_qnn_weights
    )
    print(
        f"Forward pass result for SamplerQNN: {sampler_qnn_forward_batched}.  \nShape: {sampler_qnn_forward_batched.shape}"
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    反向传递(优化神经网络/训练神经网络)

    反向传递会根据神经网络前向传播的结果,来优化权重参数。反向传递需要使用神经网络对象的backward方法

    estimator_qnn_input_grad, estimator_qnn_weight_grad = estimator_qnn.backward(
        estimator_qnn_input, estimator_qnn_weights
    )
    print(
        f"Input gradients for EstimatorQNN: {estimator_qnn_input_grad}.  \nShape: {estimator_qnn_input_grad}"
    )
    print(
        f"Weight gradients for EstimatorQNN: {estimator_qnn_weight_grad}.  \nShape: {estimator_qnn_weight_grad.shape}"
    )
    
    sampler_qnn_input_grad, sampler_qnn_weight_grad = sampler_qnn.backward(
        sampler_qnn_input, sampler_qnn_weights
    )
    print(
        f"Input gradients for SamplerQNN: {sampler_qnn_input_grad}.  \nShape: {sampler_qnn_input_grad}"
    )
    print(
        f"Weight gradients for SamplerQNN: {sampler_qnn_weight_grad}.  \nShape: {sampler_qnn_weight_grad.shape}"
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    总结

    • 声明参数(Parameter或ParameterVector)并创建参数化电路
    • 传入EstimatorQNN或SamplerQNN,一般格式:xxxQNN(circuit, inputs, weights)
      (Estimator可能需要额外导入力学量矩阵)
    • 前向传递:xxxQNN.forward(inputs, weights) 分为无批次或有批次(有批次时直接将inputs换为多个数据组的列表,[input_list1, input_list2…])
    • 反向传播:xxxQNN.backward(inputs, weights)
  • 相关阅读:
    汽车与交通运输行业智能车辆体验 | 达索系统百世慧®
    pytest-yaml 测试平台-3.创建执行任务定时执行用例
    全志R128应用开发案例——SPI 驱动 TFT LCD 屏
    中小企业数字化转型的三条建议
    nginx反向代理 负载均衡
    STL序列式容器二 ----- vector详解
    Hbase(一)入门
    逆向-还原代码之url_encode (Interl 64)
    一个好的测试工程师一定要了解的测试方法有哪些?
    Open CASCADE学习|一个点的坐标变换
  • 原文地址:https://blog.csdn.net/qq_33943772/article/details/134296012