物理学家理查德· 费曼曾说过:
自然不是古板的,如果想要要模拟自然,最好使用量子力学定律。
2020年3月11日,TensorFlow Dev Summit峰会通过线上直播的方式与各位开发者见面。会上,谷歌介绍了近期宣布开源的一款用于训练量子模型的机器学习库TensorFlow Quantum(简称TFQ)。谷歌表示,该量子机器学习模型能够处理量子数据,并能够在量子计算机上执行。
机器学习(ML)虽然不能精确模拟自然界中的系统,但却能够学习系统模型并预测系统行为。在过去几年,经典的ML模型解决了科学领域诸多难题,在癌症检测、地震余震预测、极端天气预测以及系外行星探测等方面发挥了巨大作用。
近年来,随着量子计算技术的发展,在量子机器学习模型上的新发现将对世界级重大问题产生深远影响,从而带来医学、材料、传感和通信领域的突破。但是,迄今为止我们遇到的瓶颈是,缺乏研究工具来发现有用的、可以处理量子数据并能在计算机上使用的量子机器学习模型。
基于此,谷歌最神秘的部门Google X与滑铁卢大学和大众汽车公司等合作,联合发布TensorFlow Quantum(TFQ),这是一个用于快速建立量子ML模型原型的开源库。TFQ为量子计算和机器学习研究社区的结合提供了必要工具,从而控制/建模自然或人工量子系统,比如内含大约50~100量子比特的噪声中级量子处理器(NISQ)。
在底层,TFQ 集成了NISQ算法的开源框架Cirq(Cirq 是 Google 专为 NISQ 算法打造的框架,允许开发者为特定的量子处理器编写量子算法)和TensorFlow,通过提供与现有 TensorFlow API兼容的量子计算原语和高性能量子电路模拟器,为鉴别、生成量子经典模型的设计实现,提供高层次的抽象。
量子模型能用量子力学原点表示和概括数据。但是,要了解量子模型,必须引入两个概念:量子数据模型和混合量子经典模型。
量子数据模型表现出量子叠加和量子纠缠的特性,导致联合概率分布,这可能需要成倍数量的经典计算资源来表示或存储。能够在量子处理器/传感器/网络上生成/模拟的量子数据包括化学物质和量子物质的模拟、量子控制、量子通信网络、量子计算学等。
但一个不容忽视的问题是,NISQ处理器生成的量子数据是嘈杂的,通常在测量发生之前就被纠缠了。但是,将量子机器学习应用于嘈杂的纠缠量子数据上,可以最大程度地提取有用的经典信息。基于这种技术的启发,TFQ库为模型的开发提供了基元(该模型可分解和概括量子数据中的关联),从而为改进现有量子算法或发现新的量子算法提供了可能。
引入的第二个概念是混合量子经典模型。由于近期的量子处理器仍然很小且嘈杂,因此量子模型不能单独使用量子处理器,NISQ处理器需要与经典处理器协同工作才有效。由于TensorFlow已经支持跨CPU、GPU和TPU的异构计算,因此它是试验混合量子经典算法的天然平台。
TFQ包含了特定量子计算所需的基本结构,例如量子比特、门、电路和测量运算符。用户指定的量子计算然后可以在模拟或真实硬件上执行。Cirq也包含了大量机器,可帮助用户为NISQ机器(例如编译器和调度程序)设计出高效算法,并且能使混合量子经典算法的实现在量子电路模拟器上运行,并最终在量子处理器上运行。
如今,谷歌已经将TFQ应用到了混合量子经典卷积神经网络、量子控制的机器学习、量子神经网络的分层学习、量子动态学习、混合量子态的生成建模以及通过经典递归神经网络来学习量子神经网络等方面。以及通过经典循环神经网络,来学习量子神经网络等等方面。
谷歌团队在TFQ白皮书中放出了这些量子应用的示例,并能在浏览器中通过Colab运行(项目地址:https://github.com/tensorflow/quantum/tree/research)。
TFQ能够帮助研究人员在单个计算图中构建量子数据集、量子模型和作为张量的经典控制参数。导致经典概率事件的量子测量结果可通过TensorFlow Ops获得,可用标准Keras函数进行训练。
为直观地阐述如何使用量子数据,可以考虑使用量子神经网络对量子状态进行监督分类。正如经典ML一样,量子ML面临的关键问题是如何对“噪音数据”进行分类。为了建立和训练这种模型,研究人员需要做的工作有:
量子数据被加载为张量(数字的多维数组)。每个量子数据张量都指定为用Cirq编写的量子电路,该电路可实时生成量子数据。张量由TensorFlow在量子计算机上执行以生成量子数据集。
研究人员可以使用Cirq设计量子神经网络原型,然后将其嵌入TensorFlow计算图中。基于对量子数据结构的认知,可以从几大类中选择参数化的量子模型。该模型的目标是执行量子处理,以提取隐藏在典型纠缠状态下的信息。换言之,量子模型本质上是对输入的量子数据进行分离,将隐藏的信息编码在经典关联中,从而使其可用于局部测量和经典后处理(算法)。
量子态的测量从经典随机变量中,以样本形式提取经典信息。来自该随机变量值的分布通常取决于量子态本身以及所测得的可观测值。由于许多变分算法依赖于测量值的平均值,因此TFQ提供了在涉及步骤(1)和(2)的多个运行中求平均值的方法。
提取经典信息后,其格式适用于进一步经典后处理。由于所提取的信息仍然可能被编码为测量期望之间的经典关联,因此可以使用经典的深度神经网络来提取这种关联。
根据经典后处理的结果,评估成本函数。这可以基于模型执行分类任务的准确性(如果量子数据被标记),或者基于其他标准(如果任务是无监督的)。
评估成本函数后,应更新管道中的自由参数,这通常是通过梯度下降执行的。
TensorFlow Quantum的关键特征是它能够同时训练和执行多个量子电路。TensorFlow能够跨计算机集群进行并行计算,并能够在多核计算机上模拟相对较大的量子电路。为了实现后者,谷歌还宣布发布新的高性能开源量子电路模拟器 qsim (项目地址:https://github.com/quantumlib/qsim),该模拟器已证明能够在111秒内模拟门深度为14的32比特量子电路。
接下来,谷歌列举了具体的示例来帮助开发者理解。
安装TensorFlow Quantum:
pip install -q tensorflow-quantum
导入TensorFlow和模块依赖项:
import tensorflow as tf
import tensorflow_quantum as tfq
import cirq
import sympy
import numpy as np
# visualization tools
%matplotlib inline
import matplotlib.pyplot as plt
from cirq.contrib.svg import SVGCircuit
现在,使用cirq来模拟量子电路。Cirq是谷歌提供的用于量子计算的Python库,可以使用它来定义电路,包括静态和参数化门。Cirq使用SymPy符号表示自由参数:
a, b = sympy.symbols('a b')
以下代码使用参数创建一个两比特电路:
# Create two qubits
q0, q1 = cirq.GridQubit.rect(1, 2)
# Create a circuit on these qubits using the parameters you created above.
circuit = cirq.Circuit(
cirq.rx(a).on(q0),
cirq.ry(b).on(q1), cirq.CNOT(control=q0, target=q1))
SVGCircuit(circuit)
findfont: Font family ['Arial'] not found. Falling back to DejaVu Sans.
要评估电路,可以使用该cirq.Simulator,可以通过传入cirq.ParamResolver对象来用特定编号替换电路中的自由参数。以下代码计算参数化电路的原始状态向量输出:
# Calculate a state vector with a=0.5 and b=-0.5.
resolver = cirq.ParamResolver({a: 0.5, b: -0.5})
output_state_vector = cirq.Simulator().simulate(circuit, resolver).final_state
output_state_vector
我们得到具有4个元素的状态向量:
数组([0.9387913 + 0.j,-0.23971277 + 0.j,
0. + 0.06120872j,0. -0.23971277j],dtype = complex64)
通常,我们不能直接从量子计算机获得状态向量。因此,我们通常不尝试读取状态向量,而是尝试计算与状态向量间接相关的特定值。
z0 = cirq.Z(q0)
qubit_map = {q0:0,q1:1}
z0.expectation_from_wavefunction(output_state_vector,qubit_map).real
这是Z运算符的期望值。通常,我们在布洛球的Z轴上获得量子计算结果。通过获取样本,您可以轻松估算pauli Z运算符的期望值。
量子态表示为布洛球
结果是:
0.8775825500488281
如果:
z0x1 = 0.5 * z0 + cirq.X(q1)
z0x1.expectation_from_wavefunction(output_state_vector, qubit_map).real
结果为:
-0.04063427448272705
TensorFlow Quantum(TFQ)提供tfq.convert_to_tensor将Cirq对象转换为张量,开发者可以将Cirq对象发送到谷歌的 quantum layers和quantum ops,可以在Cirq电路和Cirq Paulis的列表或数组上调用该函数:
# Rank 1 tensor containing 1 circuit.
circuit_tensor = tfq.convert_to_tensor([circuit])
print(circuit_tensor.shape)
print(circuit_tensor.dtype)
结果如下:
(1,)
<dtype: 'string'>
这会将Cirq对象编码为tf.string张量,tfq操作可根据需要对其进行解码:
# Rank 1 tensor containing 2 Pauli operators.
pauli_tensor = tfq.convert_to_tensor([z0, z0x1])
pauli_tensor.shape
结果为:
TensorShape([2])
现在,开发者已经了解部分基础知识,让我们使用TensorFlow Quantum构建一个混合的量子经典神经网络,将训练经典的神经网络来控制单个量子位。将优化控制以正确准备处于0或1状态的量子位,从而克服模拟的系统校准误差。该图显示了体系结构:
即使没有神经网络,这也是一个直接解决的问题,但主题类似于可能使用TFQ解决的实际量子控制问题,演示了使用tfq.layers.ControlledPQC内部的(参数化量子电路)层进行量子经典计算的端到端示例tf.keras.Model。
第一步:受控电路定义
# Parameters that the classical NN will feed values into.
control_params = sympy.symbols('theta_1 theta_2 theta_3')
# Create the parameterized circuit.
qubit = cirq.GridQubit(0, 0)
model_circuit = cirq.Circuit(
cirq.rz(control_params[0])(qubit),
cirq.ry(control_params[1])(qubit),
cirq.rx(control_params[2])(qubit))
SVGCircuit(model_circuit)
第二步:定义控制器网络
# The classical neural network layers.
controller = tf.keras.Sequential([
tf.keras.layers.Dense(10, activation='elu'),
tf.keras.layers.Dense(3)
])
给定一批命令,控制器为受控电路输出一批控制信号。 控制器是随机初始化的,因此,这些输出尚无用。
controller(tf.constant([[0.0],[1.0]])).numpy()
结果为:
数组([[0.,0.,0.],
[-0.16003934,0.26334327,0.3790441]],dtype = float32)
第三步:将控制器连接到电路
使用tfq将控制器连接到被控制电路,作为单一的keras.Model。首先,定义模型的输入:
# This input is the simulated miscalibration that the model will learn to correct.
circuits_input = tf.keras.Input(shape=(),
# The circuit-tensor has dtype `tf.string`
dtype=tf.string,
name='circuits_input')
# Commands will be either `0` or `1`, specifying the state to set the qubit to.
commands_input = tf.keras.Input(shape=(1,),
dtype=tf.dtypes.float32,
name='commands_input')
接下来,将运算应用于这些输入,以定义计算:
dense_2 = controller(commands_input)
# TFQ layer for classically controlled circuits.
expectation_layer = tfq.layers.ControlledPQC(model_circuit,
# Observe Z
operators = cirq.Z(qubit))
expectation = expectation_layer([circuits_input, dense_2])
现在将此计算打包为tf.keras.Model:
# The full Keras model is built from our layers.
model = tf.keras.Model(inputs=[circuits_input, commands_input],
outputs=expectation)
注意:可能需要系统安装graphviz软件包。
tf.keras.utils.plot_model(model, show_shapes=True, dpi=70)
结果为:
无法导入pydot。您必须安装pydot和graphviz才能使pydotprint运行。
数据集
模型尝试为每个命令输出正确的正确测量值$ \ hat {Z} $,命令和正确值定义如下:
# The command input values to the classical NN.
commands = np.array([[0], [1]], dtype=np.float32)
# The desired Z expectation value at output of quantum circuit.
expected_outputs = np.array([[1], [-1]], dtype=np.float32)
这不是此任务的整个训练数据集。数据集中的每个数据点也需要一个输入电路。
输入点定义
下面的输入电路定义了模型将学习校正的随机失调:
random_rotations = np.random.uniform(0, 2 * np.pi, 3)
noisy_preparation = cirq.Circuit(
cirq.rx(random_rotations[0])(qubit),
cirq.ry(random_rotations[1])(qubit),
cirq.rz(random_rotations[2])(qubit)
)
datapoint_circuits = tfq.convert_to_tensor([
noisy_preparation
] * 2) # Make two copied of this circuit
电路有两个副本,每个数据点一个。
datapoint_circuits.shape
TensorShape([2])
训练
使用定义的输入测试tfq模型:
model([datapoint_circuits, commands]).numpy()
数组([[0.16693401],
[-0.17766671]],dtype = float32)
现在,运行标准的训练过程将这些值调整为expected_outputs。
optimizer = tf.keras.optimizers.Adam(learning_rate=0.05)
loss = tf.keras.losses.MeanSquaredError()
model.compile(optimizer=optimizer, loss=loss)
history = model.fit(x=[datapoint_circuits, commands],
y=expected_outputs,
epochs=30,
verbose=0)
plt.plot(history.history['loss'])
plt.title("Learning to Control a Qubit")
plt.xlabel("Iterations")
plt.ylabel("Error in Control")
plt.show()
从该图中可以看出,神经网络已经学会克服系统失调。
验证输出
现在,使用经过训练的模型来校正量子位校准误差。使用Cirq:
现在,使用经过训练的模型来校正量子位校准误差。使用Cirq:
def check_error(command_values, desired_values):
"""Based on the value in `command_value` see how well you could prepare
the full circuit to have `desired_value` when taking expectation w.r.t. Z."""
params_to_prepare_output = controller(command_values).numpy()
full_circuit = noisy_preparation + model_circuit
# Test how well you can prepare a state to get expectation the expectation
# value in `desired_values`
for index in [0, 1]:
state = cirq_simulator.simulate(
full_circuit,
{s:v for (s,v) in zip(control_params, params_to_prepare_output[index])}
).final_state
expectation = z0.expectation_from_wavefunction(state, {qubit: 0}).real
print(f'For a desired output (expectation) of {desired_values[index]} with'
f' noisy preparation, the controller\nnetwork found the following '
f'values for theta: {params_to_prepare_output[index]}\nWhich gives an'
f' actual expectation of: {expectation}\n')
check_error(commands, expected_outputs)
For a desired output (expectation) of [1.] with noisy preparation, the controller
network found the following values for theta: [-0.22817115 -0.2512403 -1.5496594 ]
Which gives an actual expectation of: 0.9663878679275513
For a desired output (expectation) of [-1.] with noisy preparation, the controller
network found the following values for theta: [-1.2500848 1.4088008 2.5982447]
Which gives an actual expectation of: -0.9780153036117554
训练期间损失函数的值提供了关于模型学习程度的粗略概念。损耗越小,上述单元格中的期望值越接近desired_values。如果不关心参数值,则可以始终使用tfq命令检查上面的输出:
model([datapoint_circuits, commands])
结果为:
<tf.Tensor: shape=(2, 1), dtype=float32, numpy=
array([[ 0.96638787],
[-0.9780154 ]], dtype=float32)>
如果想了解更多教程,可以访问Tensorflow网站。
教程链接: https://www.tensorflow.org/quantum/tutorials/hello_many_worlds/ 参考连接: https://ai.googleblog.com/2020/03/announcing-tensorflow-quantum-open.html 论文地址: https://arxiv.org/pdf/2003.02989.pdf Crip项目地址: https://github.com/quantumlib/Cirq
领取专属 10元无门槛券
私享最新 技术干货