量子神经网络(Quantum neural networks, QNN)及其变体量子卷积神经网络(Quantum convolutional networks, QCNN),在内存和速度方面都有着高效的优势,能将经典向量由n维编码到log2^n个量子位,同时量子具有多个状态进行并行叠加运算。
这里给出一个经典结构的量子神经网络模型,如下图所示:
结构类似一个全连接神经网络,特征映射当作输入层进行量子态的准备,量子变换作为隐藏层将经典信息变换为量子信息,量子测量和输出相当于全连接神经网络的输出层。θ作为权重在优化器优化后进行更新。
本次搭建使用到的软件为:Anaconda、JupterNotebook
在Anaconda中新建环境为tensorflowq,选择Python版本为3.8.16,在终端激活环境:
把路径换到我们新建的环境,然后输入
pip install tensorflow==2.7.0
下载2.7.0版本的tensorflow,这里我已经下载过了,得到结果:
安装成功!下面安装要用到的quantum库,输入
pip install tensorflow-quantum==0.7.2
输入pip list查看安装好的库,安装成功:
下面找到官网:https://tensorflow.google.cn/quantum/tutorials/hello_many_worlds 给出的案例hello_many_world
复制代码到JupyterNotebook中:
import cirq
import sympy
import numpy as np
# visualization tools
import matplotlib.pyplot as plt
from cirq.contrib.svg import SVGCircuit
a, b = sympy.symbols('a b')
# 创建两个量子比特
q0, q1 = cirq.GridQubit.rect(1, 2)
# 使用上面创建的参数在这些量子位上创建一个电路。
circuit = cirq.Circuit(
cirq.rx(a).on(q0),
cirq.ry(b).on(q1), cirq.CNOT(control=q0, target=q1))
SVGCircuit(circuit)
使用设置的参数得到一个二量子电路:
在pycharm下调试代码观察参数内容如下:
可以使用criq评估电路,使用特定的数字替换电路中的自由参数对象,下面计算参数化电路的原始状态向量输出:
# 计算 a = 0.5和 b = -0.5的状态向量。
resolver = cirq.ParamResolver({a: 0.5, b: -0.5})
output_state_vector = cirq.Simulator().simulate(circuit, resolver).final_state_vector
得到量子的四个状态向量,这里用复数表示,由于状态向量在模拟之外不能直接访问。实际中需要指定一个度量值,它将状态向量转换为经典计算机能够理解的实数。如下代码:
z0 = cirq.Z(q0)
qubit_map={q0: 0, q1: 1}
z_real = z0.expectation_from_state_vector(output_state_vector, qubit_map).real
print(z_real)
得到结果如下:
z0x1 = 0.5 * z0 + cirq.X(q1)
z0x1.expectation_from_state_vector(output_state_vector, qubit_map).real
得到结果如下:
TensorFlow Quantum提供了将criq对象转化为张量的函数,这使得可以将criq对象发送到量子层并进行量子操作,具体操作如下,该函数可以在Criq Circuit和Cirq Paulis的列表或数组上调用:
# 一阶张量包含一个电路
circuit_tensor = tfq.convert_to_tensor([circuit])
print(circuit_tensor.shape)
print(circuit_tensor.dtype)
将criq对象编码为tf.string张量,并根据需要进行解码:
# 包含两个泡利算子的一阶张量
pauli_tensor = tfq.convert_to_tensor([z0, z0x1])
pauli_tensor.shape
计算期望值的最高级接口是tfq.layers.Expectation层,即tf.keras.Layer。以最简单的形式,该层相当于在cirq.ParamResolvers上模拟参数化电路;然而,TFQ允许按照TensorFlow语义进行批处理,并使用高效的C++代码模拟电路。
下面创造一批值来代替a和b参数。
batch_vals = np.array(np.random.uniform(0, 2 * np.pi, (5, 2)), dtype=float)
在Cirq中对参数值进行电路执行需要一个循环:
cirq_results = []
cirq_simulator = cirq.Simulator()
for vals in batch_vals:
resolver = cirq.ParamResolver({a: vals[0], b: vals[1]})
final_state_vector = cirq_simulator.simulate(circuit, resolver).final_state_vector
cirq_results.append(
[z0.expectation_from_state_vector(final_state_vector, {
q0: 0,
q1: 1
}).real])
print('cirq batch results: \n {}'.format(np.array(cirq_results)))
结果如下:
在TFQ中简化了相同的操作:
tfq.layers.Expectation()(circuit,
symbol_names=[a, b],
symbol_values=batch_vals,
operators=z0)
结果如下: