AI 框架是 AI 算法模型设计、训练和验证的一套标准接口、特性库和工具包,集成了算法的封装、数据的调用以及计算资源的使用,同时面向开发者提供了开发界面和高效的执行平台,是现阶段 AI 算法开发的必备工具。
AI 框架负责给开发者提供构建神经网络模型的数学操作,把复杂的数学表达转换成计算机可识别的计算图,自动对神经网络进行训练,得到一个神经网络模型用于解决机器学习中分类、回归的问题,实现目标分类、语音识别等应用场景。
国内外 AI 框架在 GitHub 上的数据情况:
Rank | Framework | Commits | Fork | Star | Contributors |
---|---|---|---|---|---|
Foreign Framework | |||||
1 | TensorFlow | 124494 | 86300 | 16300 | 3056 |
2 | PyTorch | 43390 | 14800 | 53700 | 2137 |
Domestic Framework | |||||
1 | Mindspore | 37308 | 514 | 2700 | 267 |
2 | PaddlePaddle | 33753 | 4300 | 17500 | 524 |
根据上表可知,TensorFlow 的各项指标在 AI 框架中都是名列前茅的,并且和第二名的差距非常大,是全球目前活跃度最高、应用最广的 AI 框架。在排行榜中的第二名是 PyTorch,近几年在学术领域的表现比较亮眼,有很大的发展潜力,但总体而言,与 TensorFlow 有些差距。
聚焦于国内,目前 MindSpore 是活跃度最高的框架,在贡献者的规模上也积累了一定的群体;排名第二的是 PaddlePaddle,因为开源较早,已经积累了不小的优势,主要集中于点赞数量及贡献者规模上,但在整体活跃度上,稍劣于 MindSpore。
不过如果我们对国内最大的开源代码平台 Gitee 的数据进行分析之后可以发现,MindSpore 各项数据都远超其他框架,说明它最近在国内是关注度以及被应用最多的 AI 框架,发展的势头很猛。数据如下表:
Rank | Framework | Commits | Fork | Star | Contributors |
---|---|---|---|---|---|
1 | MindSpore | 38549 | 2400 | 6100 | 774 |
2 | PaddlePaddle | 32788 | 195 | 3600 | 561 |
3 | OneFlow | 7521 | 2 | 1 | 126 |
4 | MegEngine | 2280 | 6 | 16 | 35 |
TensorFlow (以下简称 TF)是一个核心开源库,一个端到端的开源机器学习平台,在 2015 年 11 月由 Google 设计研发并开源。它拥有一个全面而灵活的生态系统,由 Python 编程语言编写,包含各种工具、库和社区资源,可以帮助用户开发和训练机器学习模型,推动先进机器学习技术的发展。
TF 可以轻松地安装在 Windows、MacOS 以及 Linux 等主流操作系统上,用户甚至可以直接在浏览器中运行 Colab 笔记本来快速上手,它能够帮助开发者轻松地构建和部署由机器学习提供支持的应用。但它丰富多样的 API,也为新用户的上手提高了门槛。
目前 TensorFlow 对于工业环境有着完善的模型训练与部署的解决方案,所以在这些领域内,它的占有率也是最高的。同时 TF 可以轻松地使用高阶 Keras API 构建和训练模型,对于大型的机器学习训练任务,可以使用 Distribution Strategy API 在不同的硬件配置上进行分布式训练,而无需更改模型定义,大大地方便了用户。
凭借着 TF 强大而可靠的机器学习能力,研究人员可以构建和训练先进的模型,并且不会降低速度或性能。借助 Keras Functional API 和 Model Subclassing API 等功能,TF 可以助我们灵活地创建复杂拓扑并实现相关控制。
PyTorch 是一个基于 Torch 的 Python 开源机器学习库,底层由 C++实现,应用于人工智能领域,如自然语言处理等。它主要由 Facebook 的人工智能研究团队开发,自 2017 年开源以来,陆续推出了 Tensor 与 Numpy 互转、与 Caffe2 的融合、支持 Windows 系统、ONNX 转换、FastAI 的发布、支持 Tensorboard、分布式训练等功能。不仅能够实现强大的 GPU 加速,同时还支持动态神经网络,是目前市面上很多主流框架都不支持的。
PyTorch 提供了两个高级功能:
相较于 TensorFlow 来说,PyTorch 不是必须先构建一个神经网络,然后在想要改变网格的结构时就需要从头构建的操作方式。它通过反向求导技术,可以让用户零延迟地任意改变神经网络的行为,灵活性是它最大的一个特性。而且 PyTorch 的编程 API 风格简约,直观易懂,也方便新用户上手。
但因为 PyTorch 还处于成长阶段,所以在全面性上还处于劣势,比如它还不支持快速傅里叶、沿维翻转张量和检查无穷与非数值张量等等功能;针对移动端和嵌入式部署等等性能表现方面,也还需要提供的空间。
MindSpore 是华为 2019 年 8 月推出的新一代全场景 AI 计算框架,于 2020 年 3 月 28 日开源。它的推出旨在实现易开发
、高效执行
、全场景覆盖
三大目标,其中易开发表现为 API 友好、调试难度低;高效执行包括计算效率、数据预处理效率和分布式训练效率;全场景则指框架同时支持云、边缘以及端侧场景。
具体来说,MindSpore 可以提供简单的开发体验,帮助开发者实现网络自动切分,只需串行表达就能实现并行训练,降低开发门槛同时简化开发流程。同时它有灵活的调试模式,具备训练过程静态执行和动态调试能力,开发者通过变更一行代码即可切换运行模式,快速在线定位问题。并且它的适用范围也非常广,支持云、边缘和手机上的快速部署,实现更好的资源利用和隐私保护,让开发者专注于 AI 应用的创造。
凭借底层编译化手段,MindSpore 计算图的运行效率也很高,同时它还先后支持了加强版可视化功能、差分隐私、二阶优化算法、图神经网络、量化训练、混合异构、MindSpore Serving、PS 分布式训练、MindIR、调试器等等功能。为推动人工智能软硬件应用生态的发展做出了贡献。
PaddlePaddle 在 2016 年 8 月由百度进行开源,是国内 AI 框架最早的探索与践行者。它支持声明式、命令式编程,兼具开发灵活、高性能;网络结构自动设计,模型效果超越人类专家,开发起来便捷能够提升效率。兼容多种开源框架训练的模型,不同架构的平台设备轻松部署推理速度全面领先。开源丰富算法和预训练模型,包括国际竞赛冠军模型,快速助力产业应用。
PaddlePaddle 的迭代节奏很快,目前为止,已经支持了全流程能力支持、大规模异步分布式训练等等新功能,Paddle3.0 还提供了 Suite,支持了 VisualDL、PARL、AutoDL、EasyDL、AIStudio 等功能。
在国内,Paddle 的社区也比较活跃,生态链也很完整完整,依靠百度云的加持,对于国内的用户应用还是非常友好的。目前 Paddle 虽然也不乏有 OPPO、京东物流以及度小满等国内厂商进行部署,但主要用户还是个人开发者居多。
我们这里以目前国外及国内使用率排名前列的两个 AI 框架来作为例子进行说明。
TensorFlow Quantum (TFQ) 是一个量子机器学习库,可用于快速设计量子-经典机器学习混合模型的原型。研究人员在研究量子算法和应用时,可以利用 Google 的量子计算框架,而所有的这些框架都可以在 TensorFlow 中找到。
TensorFlow Quantum 侧重于量子数据和构建量子-经典混合模型。它集成了在 Cirq 中设计的量子计算算法和逻辑,并提供与现有 TensorFlow API 兼容的量子计算基元,还提供高性能量子电路模拟器。
TensorFlow 有多种可选择的版本可供安装。这里我们选择稳定版:
pip3 install -U tensorflow-quantum
因为 TF 以 Python 编程语言为基础,所以我们还要设置 Python3.8 开发环境:
sudo apt update
sudo apt-get install pkg-config zip g++ zlib1g-dev unzip python3.8
sudo apt install python3.8 python3.8-dev python3.8-venv python3-pip
python3.8 -m pip install --upgrade pip
接着为 TFQ 开发创建一个虚拟环境:
python3.8 -m venv quantum_env
source quantum_env/bin/activate
随后安装 TF 依赖项:
pip install -U pip six numpy wheel setuptools mock 'future>=0.17.1'
pip install -U keras_applications --no-deps
pip install -U keras_preprocessing --no-deps
pip install numpy==1.19.5
接着构建 TensorFlow Quantum pip 软件包并安装:
./configure.sh
bazel build -c opt --cxxopt="-O3" --cxxopt="-march=native" --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" release:build_pip_package
bazel-bin/release/build_pip_package /tmp/tfquantum/
python3 -m pip install /tmp/tfquantum/<var>name_of_generated_wheel</var>.whl
如此,TensorFlow Quantum 安装完毕,环境也已调试好,可以运行测试代码看看实际情况:
./scripts/test_all.sh
我们以二进制分类为例,看看 TensorFlow Quantum 是如何完成相关操作的。我们知道二进制分类是机器学习中的一项基本任务,也可以应用于量子数据,作为一个经典混合量子模型的最小示例。
我们首先为单个量子比特上的区域提供一个二元分类器,X 与 Y 是其中的两个随机向量。选择布洛赫球面,围绕这两个向量,我们随机抽取两组量子数据积分,让机器学会如何区分这两组积分。
第一步,生成量子数据,我们可以使用 Cirq 完成此任务,具体操作如下:
import cirq , random , sympy
import numpy as np
import tensorflow as tf
import tensorflow_quantum as tfq
利用下面的函数生成量子数据集;标签使用单次编码:
def generate_dataset (
qubit , theta_a , theta_b , num_samples ):
q_data = []
labels = []
blob_size = abs( theta_a - theta_b ) / 5
for _ in range ( num_samples ):
coin = random . random () spread_x ,
spread_y = np . random . uniform (
- blob_size , blob_size , 2)
if coin < 0.5:
label = [1 , 0]
angle = theta_a + spread_y
else :
label = [0 , 1]
angle = theta_b + spread_y
labels . append ( label )
q_data . append ( cirq . Circuit (
cirq . Ry (- angle )( qubit ) ,
cirq . Rx (- spread_x ) ( qubit )) )
return ( tfq . convert_to_tensor ( q_data ) ,
np . array ( labels ))
我们可以在之后生成一个数据集和相关的标签,选择一些参数值:
qubit = cirq . GridQubit (0 , 0)
theta_a = 1
theta_b = 4
num_samples = 200
q_data , labels = generate_dataset (
qubit , theta_a , theta_b , num_samples )
将这些参考值作为我们的量子参数模型,使用最简单的通用量子鉴别器[43,66]的情况,单参数化旋转(线性)和沿 Z 轴(非线性)测量数据:
theta = sympy . Symbol (’theta ’)
q_model = cirq . Circuit ( cirq . Ry ( theta ) ( qubit ))
q_data_input = tf . keras . Input (
shape =() , dtype = tf . dtypes . string )
expectation = tfq . layers . PQC (
q_model , cirq .Z( qubit ))
expectation_output = expectation ( q_data_input )
旋转门的目的是为了使输入的量子数据叠加效应最小化,这样我们就可以从测量中最大限度的获得有用信息。然后我们将这个量子模型附加到一个小的分类器 NN 中完成所需的混合模型:
classifier = tf . keras . layers . Dense (
2, activation = tf . keras . activations . softmax )
classifier_output = classifier (
expectation_output ) model = tf . keras . Model ( inputs = q_data_input ,
outputs = classifier_output )
我们可以在量子数据上对这个混合模型进行训练。下面我们使用标签和预测数据之间的交叉熵作为损失函数,构建经典神经网络,选择 ADAM 优化器进行参数更新:
optimizer = tf . keras . optimizers . Adam (
learning_rate =0.1)
loss = tf . keras . losses . CategoricalCrossentropy ()
model . compile ( optimizer = optimizer , loss = loss )
history = model . fit (
x= q_data , y= labels , epochs =50)
最后我们可以用训练好的混合模型来对新的量子数据点进行分类:
test_data , _ = generate_dataset (
qubit , theta_a , theta_b , 1)
p = model . predict ( test_data ) [0]
print (f" prob (a)={p [0]:.4 f}, prob (b)={p [1]:.4 f}")
Paddle Quantum(量桨)是基于百度飞桨开发的量子机器学习工具集,支持量子神经网络的搭建与训练,提供易用的量子机器学习开发套件与量子优化、量子化学等前沿量子应用工具集,使得百度飞桨也因此成为国内首个支持量子机器学习的深度学习框架。
量桨建立起了人工智能与量子计算的桥梁,通过百度飞桨深度学习平台赋能量子计算,为领域内的科研人员以及开发者便捷地开发量子人工智能的应用提供了强有力的支撑,同时也为广大量子计算爱好者提供了一条可行的学习途径。
量桨有丰富的在线教程,并能够通过模板高效搭建量子神经网络,此外还带有自动微分框架,满足轻松上手的需求;量桨的功能也非常的丰富,提供多种优化工具和 GPU 模式,高性能模拟器支持 25+量子比特的模拟运算,且支持多种噪声模型的模拟;量桨还提供了非常有特色的工具集功能,提供了组合优化和量子化学等前沿领域的计算工具箱,提供了分布式量子信息处理模组 LOCCNet,此外还提供了自研的多种量子机器学习算法。
在安装 Paddle Quantum 时,可以通过以下方式安装:
pip install paddle-quantum
或者下载所有文件后,在本地进行安装:
git clone http://github.com/PaddlePaddle/quantum
cd quantum
pip install -e .
因为 Paddle Quantum 的模型是基于 Python 完成的,所以在执行量子化学操作前,需要安装Psi4
Python 包(建议安装在 Python3.8 环境中)。安装命令为:
conda install psi4 -c psi4 -c conda-forge
当所有准备工作完成后,我们可以通过简单运行一些代码来验证是否成功配置好了 Paddle Quantum 的环境。这里我们以量子近似优化算法(QAOA)为例。
cd paddle_quantum/QAOA/example
python main.py
如果可以成功运行,说明各项组件都已安装完毕,我们就可以运行整个系统来进行量子模拟了。
目前业界普遍认为,量子计算在处理量子化学问题上会有非常大的发展前景,而变分量子本征求解器(VQE)就是这个方向上的核心应用之一。接下来我们将演示如何使用量桨完成相关问题的操作。
以解决氢分子 H2 基态能量问题为例,我们首先需要构建相关的量子化学工具包:
import paddle
import paddle_quantum.qchem as qchem
from paddle_quantum.loss import ExpecVal
from paddle_quantum import Hamiltonian
from paddle_quantum.state import zero_state, State
from paddle_quantum.ansatz import Circuit
from paddle_quantum.linalg import dagger
from paddle_quantum import Backend
import os
import matplotlib.pyplot as plt
import numpy
from numpy import pi as PI
from numpy import savez, zeros
# 无视警告
import warnings
warnings.filterwarnings("ignore")
对于具体分析的分子,我们需要其几何构型、基组、多重度以及分子的净电荷数等多项信息来建模计算出该分子单体积分,双体积分以及哈密顿量等信息。接下来,通过量桨的量子化学工具包将分子的哈密顿量提取出来并储存为 paddle quantum 的Hamilton
类,方便下一步操作:
geo = qchem.geometry(structure=[['H', [-0., 0., 0.0]], ['H', [-0., 0., 0.74]]])
# geo = qchem.geometry(file='h2.xyz')
# 将分子信息存储在 molecule 里,包括单体积分(one-body integrations),双体积分(two-body integrations),分子的哈密顿量等
molecule = qchem.get_molecular_data(
geometry=geo,
basis='sto-3g',
charge=0,
multiplicity=1,
method="fci",
if_save=True,
if_print=True
)
# 提取哈密顿量
molecular_hamiltonian = qchem.spin_hamiltonian(molecule=molecule,
filename=None,
multiplicity=1,
mapping_method='jordan_wigner',)
# 打印结果
print("\nThe generated h2 Hamiltonian is \n", molecular_hamiltonian)
输出结果为:
FCI energy for H2_sto-3g_singlet (2 electrons) is -1.137283834485513.
The generated h2 Hamiltonian is
-0.09706626861762556 I
-0.04530261550868938 X0, X1, Y2, Y3
0.04530261550868938 X0, Y1, Y2, X3
0.04530261550868938 Y0, X1, X2, Y3
-0.04530261550868938 Y0, Y1, X2, X3
0.1714128263940239 Z0
0.16868898168693286 Z0, Z1
0.12062523481381837 Z0, Z2
0.16592785032250773 Z0, Z3
0.17141282639402394 Z1
0.16592785032250773 Z1, Z2
0.12062523481381837 Z1, Z3
-0.2234315367466399 Z2
0.17441287610651626 Z2, Z3
-0.2234315367466399 Z3
当然,在实现 VQE 的过程中,我们首先需要设计量子神经网络 QNN(即参数化量子电路)来准备试探波函数()|Ψ(θ)〉,我们采用的电路图如图所示,虚线框为第一层:
接下来,根据上图中的电路设计,通过 Paddle Quantum 的Circuit
类和内置的real_entangled_layer()
电路模板来高效搭建量子神经网络。
def U_theta(num_qubits: int, depth: int) -> Circuit:
"""
Quantum Neural Network
"""
# 按照量子比特数量/网络宽度初始化量子神经网络
cir = Circuit(num_qubits)
# 内置的 {R_y + CNOT} 电路模板
cir.real_entangled_layer(depth = depth)
# 铺上最后一列 R_y 旋转门
cir.ry()
return cir
完成数据和量子神经网络的架构之后,我们需要定义训练参数、模型和损失函数。其中损失函数公式如下:
\min_{θ}{L(θ)}=\min_{θ}〈\Psi(θ)|H|\Psi(θ)〉=\min_{θ}\sum_{k}{c_k}〈\Psi(\theta)|⨂_{j}{\sigma_j}^{(k)}|\Psi(\theta)〉
class StateNet(paddle.nn.Layer):
"""
Construct the model net
"""
def __init__(self, num_qubits: int, depth: int):
super(StateNet, self).__init__()
self.depth = depth
self.num_qubits = num_qubits
self.cir = U_theta(self.num_qubits, self.depth)
# 定义损失函数和前向传播机制
def forward(self):
# 运行电路
state = self.cir(init_state)
# 计算损失函数
loss = loss_func(state)
return loss, self.cir
完成损失函数的定义后,我们就可以进行量子神经网络的训练了,不过在那之前,还需要设置一下超参数。一般来说,主要是学习速率、迭代次数和量子神经网络计算模块的深度等等。
ITR = 80 # 设置训练的总迭代次数
LR = 0.4 # 设置学习速率
D = 2 # 设置量子神经网络中重复计算模块的深度 Depth
N = molecular_hamiltonian.n_qubits # 设置参与计算的量子比特数
当训练模型的参数都设置完成后,我们将数据转化为 Paddle 中的张量,进而进行量子神经网络的训练:
# 确定网络的参数维度
net = StateNet(N, D)
# 一般来说,我们利用Adam优化器来获得相对好的收敛,
# 当然你可以改成SGD或者是RMS prop.
opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())
# 定义初始态
init_state = zero_state(N)
# 定义损失函数
loss_func = ExpecVal(molecular_hamiltonian)
# 记录优化结果
summary_iter, summary_loss = [], []
# 优化循环
for itr in range(1, ITR + 1):
# 前向传播计算损失函数
loss, cir = net()
# 在动态图机制下,反向传播极小化损失函数
loss.backward()
opt.minimize(loss)
opt.clear_grad()
# 更新优化结果
summary_loss.append(loss.numpy())
summary_iter.append(itr)
# 打印结果
if itr % 20 == 0:
print("iter:", itr, "loss:", "%.4f" % loss.numpy())
print("iter:", itr, "Ground state energy:", "%.4f Ha"
% loss.numpy())
if itr == ITR:
print("\n训练后的电路:")
print(cir)
# 储存训练结果到 output 文件夹
os.makedirs("output", exist_ok=True)
savez("./output/summary_data", iter = summary_iter,
energy=summary_loss)
最后的输入结果为:
iter: 20 loss: -1.0700
iter: 20 Ground state energy: -1.0700 Ha
iter: 40 loss: -1.1309
iter: 40 Ground state energy: -1.1309 Ha
iter: 60 loss: -1.1362
iter: 60 Ground state energy: -1.1362 Ha
iter: 80 loss: -1.1372
iter: 80 Ground state energy: -1.1372 Ha
训练后的电路:
--Ry(7.856)----*--------------x----Ry(4.698)----*--------------x----Ry(6.277)--
| | | |
--Ry(1.548)----x----*---------|----Ry(-1.56)----x----*---------|----Ry(5.041)--
| | | |
--Ry(3.441)---------x----*----|----Ry(4.474)---------x----*----|----Ry(1.745)--
| | | |
--Ry(-0.17)--------------x----*----Ry(1.646)--------------x----*----Ry(3.152)--
至此,我们完成了量子神经网络的训练,通过 VQE 得到的基态能量估计值大概是E0≈−1.137Ha,这与通过psi4
在 sto-3g 基底下,使用 FCI 方法得到的基态能量值E0=−1.13728Ha在化学精度的角度上来说是相符合的。
测试效果代码展示如下:
result = numpy.load('./output/summary_data.npz')
eig_val, eig_state = numpy.linalg.eig(
molecular_hamiltonian.construct_h_matrix())
min_eig_H = numpy.min(eig_val.real)
min_loss = numpy.ones([len(result['iter'])]) * min_eig_H
plt.figure(1)
func1, = plt.plot(result['iter'], result['energy'],
alpha=0.7, marker='', linestyle="-", color='r')
func_min, = plt.plot(result['iter'], min_loss,
alpha=0.7, marker='', linestyle=":", color='b')
plt.xlabel('Number of iteration')
plt.ylabel('Energy (Ha)')
plt.legend(handles=[
func1,
func_min
],
labels=[
r'$\left\langle {\psi \left( {\theta } \right)} '
r'\right|H\left| {\psi \left( {\theta } \right)} \right\rangle $',
'Ground-state energy',
], loc='best')
plt.text(-15.5, -1.145, f'{min_eig_H:.5f}', fontsize=10, color='b')
#plt.savefig("vqe.png", bbox_inches='tight', dpi=300)
plt.show()
同时,我们可以利用 VQE 的数据完成测量原子间的最小间隔是在什么距离发生的,下图展示的是利用 Paddle Quantum 测量所得的最小氢原子间隔:
可以看到,最小值确实发生在d=74pm附近,这个间隔就是真实原子间隔,这与化学中氢原子间原子间隔为74pm非常的相近,说明实验数据是准确的。
参考链接: