基于 MindQuantum 实现对含有自定义量子门且损失函数涉及多个哈密顿量的量子线路的训练

基于 MindQuantum 实现对含有自定义量子门且损失函数涉及多个哈密顿量的量子线路的训练

前面文章 如何利用 MindQuantum 中自定义的量子门,实现对多个哈密顿量求期望值和梯度? 中已经提到了,采用 Projectq 后端的 MindQuantum 0.7.0 及之前的版本不支持对损失函数涉及多个哈密顿量的自定义量子门组成的量子线路求梯度,我们在那篇文章中就采用中心差分,自己动手编了一个函数来完成该任务。在本文中,我们更进一步,综合起之前的几篇文章(如何利用 MindQuantum 中自定义的量子门,实现对多个哈密顿量求期望值和梯度? ,MindQuantum 中 get_exceptation_with_grad 和 grad_ops 之间的关系,MindQuantum自定义损失函数和目标标签训练部分量子线路等)来实现一个更高级的任务:构建框架,实现对含有自定义量子门且损失函数涉及多个哈密顿量的量子线路的训练。我们希望随着 MindQuantum 下个版本推出的新的自研后端,能天然地解决这个问题,而不必像现在这样麻烦。

我们先导入依赖库:

import mindspore as ms
import numpy as np
from mindspore import context, nn
from mindspore.ops import operations
from mindquantum import *
from mindspore.nn import Adam, TrainOneStepCell, LossBase
from mindspore.common.initializer import initializer
from mindspore.common.parameter import Parameter
ms.context.set_context(mode=ms.context.PYNATIVE_MODE, device_target="CPU")
import copy

自定义量子门。此处 gate_xgate_z 实际就是 MindQuantum 中的 RXRZ,但采用自定义的方式。虽然本质是一样的,但因为当前的后端 Projectq 不支持自定义的量子门,所以才出现了本文要解决的这个问题。

def matrix_x(theta):
    return np.array([[np.cos(theta / 2), -1j * np.sin(theta / 2)],
                     [-1j * np.sin(theta / 2), np.cos(theta / 2)]])

def diff_matrix_x(theta):
    return 0.5 * np.array([[-np.sin(theta / 2), -1j * np.cos(theta / 2)],
                           [-1j * np.cos(theta / 2), -np.sin(theta / 2)]])

def matrix_z(theta):
    return np.array([[np.exp(-1j * theta / 2), 0], [0, np.exp(1j * theta / 2)]])

def diff_matrix_z(theta):
    return 0.5j * np.array([[-np.exp(-1j * theta / 2), 0], [0, np.exp(1j * theta / 2)]])

gate_x = gene_univ_parameterized_gate('gete_x', matrix_x, diff_matrix_x) # 自定义量子门
gate_z = gene_univ_parameterized_gate('gete_z', matrix_z, diff_matrix_z) # 自定义量子门

仿照 MindQuantum 中 Simulator 搭建自定义的模拟器类,但只有求期望值和梯度的功能,且梯度的计算使用差分法。

class my_simulator: 
    
    def get_expectation_with_grad(self, hams, circ): # 输入为 hams, circ_right, simulator_left 等,这里就只用 hams 代替。
        sim = Simulator('projectq', 1) 
        
        def grad_ops(inputs): # 输入为各量子门的参数
            h = 1e-4
            grad = []
            sim.reset()
            sim.apply_circuit(circ, inputs)
            exceptation = [sim.get_expectation(ham).real for ham in hams]
            for i in range(inputs.size):
                params_p, params_n = copy.deepcopy(inputs), copy.deepcopy(inputs)
                params_p[i] += h
                params_n[i] -= h
                sim.reset()
                sim.apply_circuit(circ, params_p)
                g_p = [sim.get_expectation(ham) for ham in hams]
                sim.reset()
                sim.apply_circuit(circ, params_n)
                g_n = [sim.get_expectation(ham) for ham in hams]
                grad.append([(p.real - n.real)/(2*h) for p, n in zip(g_p, g_n)])
                sim.reset()
            return exceptation, np.array(grad).T # 运行结果为期望值和梯度
        return grad_ops # MindQuantum 中,这里返回的是一个封装了 hams, grad_ops 等的一个封装器,这里简化为单独的 grad_ops

仿照 MindQuantum 中的 AnsatzOnlyOps 搭建的一个 ops

class ansatz_only_ops(nn.Cell):
    def __init__(self, expectation_with_grad):
        super().__init__()
        self.expectation_with_grad = expectation_with_grad
        self.shape_ops = operations.Shape()
        self.g = None 

    def construct(self, arg):
        fval, g_ans = self.expectation_with_grad(arg.asnumpy())
        self.g = np.real(g_ans)
        return ms.Tensor(np.real(fval), dtype=ms.float32)

    def bprop(self, arg, out, dout): 
        dout = dout.asnumpy()
        grad = dout @ self.g
        return ms.Tensor(grad, dtype=ms.float32)

仿照 MindQuantum 中的 AnsatzOnlyLayer 搭建的一个 Layer,用于封装量子线路,就可以和 MindSpore 的参数优化功能完美融合在一起了。

class ansatz_only_layer(nn.Cell):
    def __init__(self, expectation_with_grad, weight='ones'):
        super().__init__()
        self.evolution = ansatz_only_ops(expectation_with_grad)
        weight_size = len(circ.params_name)
        self.weight = Parameter(initializer(weight, weight_size, dtype=ms.float32), name='ansatz_weight')

    def construct(self):
        return self.evolution(self.weight)

损失函数,为展示此工程功能,这里的损失函数设定为两个哈密顿量的和,即 Z0 + X0

class MyLoss(LossBase):
    def __init__(self, reduction='mean'):
        super(MyLoss, self).__init__(reduction)

    def construct(self, logits):
        out = logits[0] + logits[1] 
        return self.get_loss(out)

将量子网络和损失函数合并起来。

class MyWithLossCell(nn.Cell):
    def __init__(self, backbone, loss_fn):
       super(MyWithLossCell, self).__init__(auto_prefix=False)
       self._backbone = backbone
       self._loss_fn = loss_fn

    def construct(self):
       out = self._backbone()
       return self._loss_fn(out)

    @property
    def backbone_network(self):
       return self._backbone

包含有自定义量子门的量子线路和构建损失函数哈密顿量。其中,量子线路采用 ZXZ 分解,而损失函数涉及多个哈密顿量(Z0X0)。

circ = Circuit()
circ += gate_z('a').on(0)
circ += gate_x('b').on(0)
circ += gate_z('c').on(0)
circ.as_ansatz()

hams = [Hamiltonian(QubitOperator('Z0')),Hamiltonian(QubitOperator('X0'))] # 多个哈密顿量

实例化自定义的类,且将量子网络和损失函数整合起来。

my_sim = my_simulator()
grad_ops = my_sim.get_expectation_with_grad(hams, circ)

qnet = ansatz_only_layer(grad_ops)
loss = MyLoss()
net_with_criterion = MyWithLossCell(qnet, loss)
opti = Adam(qnet.trainable_params(), learning_rate=0.5) 
net = TrainOneStepCell(net_with_criterion, opti)

训练并得到最终结果:

for i in range(100):
    res = net()
    if i % 10 == 0:
        print(f'当前训练次数为:{i}, 损失函数值为:{res}')
当前训练次数为:0, 损失函数值为:1.2483757
当前训练次数为:10, 损失函数值为:-1.0459888
当前训练次数为:20, 损失函数值为:-1.3248273
当前训练次数为:30, 损失函数值为:-1.4057021
当前训练次数为:40, 损失函数值为:-1.4104203
当前训练次数为:50, 损失函数值为:-1.4127097
当前训练次数为:60, 损失函数值为:-1.4128952
当前训练次数为:70, 损失函数值为:-1.4132676
当前训练次数为:80, 损失函数值为:-1.4137471
当前训练次数为:90, 损失函数值为:-1.4141047

验证结果:

sim = Simulator('projectq', 1)

sim.apply_circuit(circ, pr=qnet.weight.asnumpy())
print('\n最终的量子态为:\n', sim.get_qs(ket=True))

z0 = sim.get_expectation(Hamiltonian(QubitOperator('Z0')))
x0 = sim.get_expectation(Hamiltonian(QubitOperator('X0')))
print('\n最终损失函数值为:', (z0+x0).real)
最终的量子态为:
 (0.36679647134390286+0.10726773357418498j)¦0⟩
(-0.8864696281552857-0.2610087743769323j)¦1⟩

最终损失函数值为: -1.4142114663496177

你可能感兴趣的:(量子神经网络,MindQuantum,机器学习,python,人工智能)