谷歌开源TensorFlow Quantum,用于训练量子模型的机器学习框架

图片

作者 | Google AI译者 | 李冬梅策划 | 钰莹“自然不是古板的,如果想要要模拟自然,最好使用量子力学定律。”
                                                                                 — 物理学家理查德· 费曼

2020 年 3 月 11 日,TensorFlow Dev Summit 峰会通过线上直播的方式与各位开发者见面。会上,谷歌介绍了近期宣布开源的一款用于训练量子模型的机器学习库 TensorFlow Quantum(简称 TFQ)。谷歌表示,该量子机器学习模型能够处理量子数据,并能够在量子计算机上执行。

图片

量子机器学习库 TensorFlow Quantum

机器学习(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 的工作原理

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 网站。


猜你喜欢

转载自blog.51cto.com/15060462/2675616