问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

AI for Science:基于OpenVINO+英特尔独立显卡解薛定谔方程

创作时间:
作者:
@小白创作中心

AI for Science:基于OpenVINO+英特尔独立显卡解薛定谔方程

引用
CSDN
1.
https://m.blog.csdn.net/virobotics/article/details/144351898

随着人工智能与科学计算的深度融合,基于物理信息的神经网络(PINN)在求解偏微分方程方面展现出独特优势。本文将介绍如何使用OpenVINO和英特尔独立显卡来求解薛定谔方程,通过结合深度学习和物理约束,展示AI在科学研究中的应用潜力。

PINN——加入物理约束的神经网络

基于物理信息的神经网络(Physics-informed Neural Network,简称PINN),是一类用于解决有监督学习任务的神经网络,它不仅能够像传统神经网络一样学习到训练数据样本的分布规律,而且能够学习到数学方程描述的物理定律。与纯数据驱动的神经网络学习相比,PINN在训练过程中施加了物理信息约束,因而能用更少的数据样本学习到更具泛化能力的模型。

算法描述

所谓的物理神经网络,其实就是把物理方程作为限制加入神经网络中使训练的结果满足物理规律。而这个所谓的限制是怎么实现的?其实就是通过把物理方程的迭代前后的差值加到神经网络的损失函数里面去,让物理方程也“参与”到了训练过程。这样,神经网络在训练迭代时候优化的不仅仅是网络自己的损失函数,还有物理方程每次迭代的差,使得最后训练出来的结果就满足物理规律了。

DeepXDE框架详解

DeepXDE由Lu Lu在布朗大学George Karniadakis教授的指导下于2018年夏季至2020年夏季开发,并得到PhILM的支持。DeepXDE最初是在布朗大学的Subversion中自行托管的,名称为SciCoNet(科学计算神经网络)。2019年2月7日,SciCoNet从Subversion迁移到GitHub,更名为DeepXDE。

DeepXDE特性

DeepXDE已经实现了如上所示的许多算法,并支持许多特性:

  • 复杂的域几何图形,没有专制网格生成。原始几何形状是间隔、三角形、矩形、多边形、圆盘、长方体和球体。其他几何可以使用三个布尔运算构建为构造实体几何(CSG):并集、差集和交集。
  • 多物理场,即(时间相关的)耦合偏微分方程。
  • 5种类型的边界条件(BC):Dirichlet、Neumann、Robin、周期性和一般BC,可以在任意域或点集上定义。
  • 不同的神经网络,例如(堆叠/非堆叠)全连接神经网络、残差神经网络和(时空)多尺度傅里叶特征网络。
  • 6种抽样方法:均匀抽样、伪随机抽样、拉丁超立方抽样、Halton序列、Hammersley序列、Sobol序列。
  • 训练点可以在训练期间保持不变,也可以每隔一定的迭代重新采样一次。
  • 方便保存训练期间的模型,并加载训练好的模型。
  • 使用dropout的不确定性量化。
  • 许多不同的(加权)损失、优化器、学习率计划、指标等回调,用于在训练期间监控模型的内部状态和统计信息,例如提前停止。
  • 使用户代码紧凑,与数学公式非常相似。
  • DeepXDE的所有组件都是松耦合的,因此DeepXDE结构良好且高度可配置。
  • 可以轻松自定义DeepXDE以满足新的需求。

数值算例:求解薛定谔方程

我们将求解由下式给出的非线性薛定谔方程:

周期性边界条件为:

x∈[-5,5],t∈[0,π⁄2]
h(t,-5)=h(t,5)
h_x (t,-5)=h_x (t,5)

初始条件为:

h(0,x)=2sech(x)

Deepxde只使用实数,因此我们需要明确拆分复数PDE的实部和虚部。代替单个残差:
我们得到两个(实值)残差:
f_R=u_t+1/2 V_xx+(u2+v2)v
f_L=v_t-1/2 U_xx-(u2+v2)u
其中u(x,t)和v(x,t)分别表示h的实部和虚部。

import numpy as np
import deepxde as dde
# 用于绘图
import matplotlib.pyplot as plt
from scipy.interpolate import griddata

x_lower = -5
x_upper = 5
t_lower = 0
t_upper = np.pi / 2

# 创建 2D 域(用于绘图和输入)
x = np.linspace(x_lower, x_upper, 256)
t = np.linspace(t_lower, t_upper, 201)
X, T = np.meshgrid(x, t)

# 整个域变平
X_star = np.hstack((X.flatten()[:, None], T.flatten()[:, None]))

# 空间和时间域/几何(对于 deepxde 模型)
space_domain = dde.geometry.Interval(x_lower, x_upper)
time_domain = dde.geometry.TimeDomain(t_lower, t_upper)
geomtime = dde.geometry.GeometryXTime(space_domain, time_domain)

# 损失的“物理信息”部分
def pde(x, y):
    """
    INPUTS:
        x: x[:,0] 是 x 坐标
           x[:,1] 是 t 坐标
        y: 网络输出,在这种情况下:
            y[:,0] 是 u(x,t) 实部
            y[:,1] 是 v(x,t) 虚部
    OUTPUT:
        标准形式的 pde,即必须为零的东西
    """
    u = y[:, 0:1]
    v = y[:, 1:2]
    # 在'jacobian'中,i 是输出分量,j 是输入分量
    u_t = dde.grad.jacobian(y, x, i=0, j=1)
    v_t = dde.grad.jacobian(y, x, i=1, j=1)
    u_x = dde.grad.jacobian(y, x, i=0, j=0)
    v_x = dde.grad.jacobian(y, x, i=1, j=0)
    # 在“hessian”中,i 和 j 都是输入分量。 (Hessian 原则上可以是 d^2y/dxdt、d^2y/d^2x 等)
    # 输出组件由“组件”选择
    u_xx = dde.grad.hessian(y, x, component=0, i=0, j=0)
    v_xx = dde.grad.hessian(y, x, component=1, i=0, j=0)
    f_u = u_t + 0.5 * v_xx + (u ** 2 + v ** 2) * v
    f_v = v_t - 0.5 * u_xx - (u ** 2 + v ** 2) * u
    return [f_u, f_v]

# 边界条件和初始条件
# 周期性边界条件
bc_u_0 = dde.PeriodicBC(
    geomtime, 0, lambda _, on_boundary: on_boundary, derivative_order=0, component=0
)
bc_u_1 = dde.PeriodicBC(
    geomtime, 0, lambda _, on_boundary: on_boundary, derivative_order=1, component=0
)
bc_v_0 = dde.PeriodicBC(
    geomtime, 0, lambda _, on_boundary: on_boundary, derivative_order=0, component=1
)
bc_v_1 = dde.PeriodicBC(
    geomtime, 0, lambda _, on_boundary: on_boundary, derivative_order=1, component=1
)

# 初始条件
def init_cond_u(x):
    "2 sech(x)"
    return 2 / np.cosh(x[:, 0:1])

def init_cond_v(x):
    return 0

ic_u = dde.IC(geomtime, init_cond_u, lambda _, on_initial: on_initial, component=0)
ic_v = dde.IC(geomtime, init_cond_v, lambda _, on_initial: on_initial, component=1)

data = dde.data.TimePDE(
    geomtime,
    pde,
    [bc_u_0, bc_u_1, bc_v_0, bc_v_1, ic_u, ic_v],
    num_domain=10000,
    num_boundary=20,
    num_initial=200,
    train_distribution="pseudo",
)

# 网络架构
net = dde.maps.FNN([2] + [100] * 4 + [2], "tanh", "Glorot normal")
model = dde.Model(data, net)

# Adam 优化
# 强烈建议使用 GPU 加速系统.
model.compile("adam", lr=1e-3, loss="MSE")
model.train(epochs=1000, display_every=100)

# L-BFGS 优化
dde.optimizers.config.set_LBFGS_options(
    maxcor=50,
    ftol=1.0 * np.finfo(float).eps,
    gtol=1e-08,
    maxiter=1000,
    maxfun=1000,
    maxls=50,
)
model.compile("L-BFGS")
model.train()

# 做预测
prediction = model.predict(X_star, operator=None)
u = griddata(X_star, prediction[:, 0], (X, T), method="cubic")
v = griddata(X_star, prediction[:, 1], (X, T), method="cubic")
h = np.sqrt(u ** 2 + v ** 2)

# 绘制预测
fig, ax = plt.subplots(3)
ax[0].set_title("Results")
ax[0].set_ylabel("Real part")
ax[0].imshow(
    u.T,
    interpolation="nearest",
    cmap="viridis",
    extent=[t_lower, t_upper, x_lower, x_upper],
    origin="lower",
    aspect="auto",
)
ax[1].set_ylabel("Imaginary part")
ax[1].imshow(
    v.T,
    interpolation="nearest",
    cmap="viridis",
    extent=[t_lower, t_upper, x_lower, x_upper],
    origin="lower",
    aspect="auto",
)
ax[2].set_ylabel("Amplitude")
ax[2].imshow(
    h.T,
    interpolation="nearest",
    cmap="viridis",
    extent=[t_lower, t_upper, x_lower, x_upper],
    origin="lower",
    aspect="auto",
)
plt.show()

生成OpenVINO IR模型

如需使用LabVIEW OpenVINO推理deepxde的模型,需要做以下几步:

  1. 将deepxde模型转成onnx模型作为中间件:
    代码中,我们首先要创建一个和X_star的形状相同的X2作为参考输入(X2必须是cpu上的矩阵),其次是新建一个基于cpu的mode2,其权重和model完全一致。最后使用torch.onnx.export生成onnx模型。

  2. 使用命令行将onnx模型转为IR模型:

mo --input_model Schrodinger.onnx --input_shape "[256,2]"

命令中,我们将输入的形状设置为256*2,其中第0列为位置x,第1列为时间t。256为我们设置的每个时间点需要推理的x的点数,可以为任意长度。

完成上述两个步骤后,我们可以看到文件夹里多了三个文件Schrodinger.onnx、Schrodinger.xml和Schrodinger.bin。其中onnx为pytorch生成的onnx模型,xml和bin为mo生成的OpenVINO IR模型。

LabVIEW调用IR模型

LabVIEW是NI推出的图形化编程环境,在科研、工业测控领域有着广泛的应用。使用LabVIEW的波形图、强度图等控件,可以使用户更直观的观测自己模型的训练结果。

使用我们编写好的Schrodinger_OpenVINO.vi,即可快速推理Schrodinger方程的OpenVINO模型。以下是使用LabVIEW调用模型的步骤:

  1. 初始化模型:使用LoadIR.vi调用xml和bin文件,推理引擎可使用CPU或GPU(Intel核显或独显);
  2. 初始化位置。根据我们训练时用的参数,需要模拟-5~5范围内任意数量的位置点(本案例中使用256个位置点)。
  3. 初始化时间,根据我们训练的参数,需要模拟0~pi/2范围内任意数量的时间点(本案例中使用201个时间点。
  4. 推理模型时。每次循环将某一个时间点复制256份,和所有的256个位置点组成2256的二维数组,然后转置成2562的数组,输入至网络中。
  5. 获取输出。输出为2562,但和输入的意义不同:其中第0列为波函数h的实部,第1列为h的虚部。因此需要将结果转置成2256,后,方能使用波形图(Waveform Graph)显示两条曲线。
  6. 获取整个时间段、所有位置的结果。使用For循环索引,保存所有时间段实部、虚部和幅值的结果,并显示在强度图上。
  7. 使用release.vi关闭OpenVINO模型。
  8. 运行程序。我们使用Intel A770独立显卡(设备名称为GPU.1)运行该模型。运行结果如下图:

左边的波形图为每一个时间点的波函数实部和虚部的曲线,右边的强度图为所有时间点的实部、虚部和幅值分布。结果表明,使用OpenVINO推理物理信息神经网络模型,和deepxde的结果完全一致。此外,在A770上模型也得到了最大加速,并节省了大量的cpu资源。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号