PINN物理信息网络 | 物理信息神经网络PINN实例及其Python实现

基本介绍

物理信息神经网络是一种基于物理系统的神经网络模型。它的设计灵感来自于神经科学和量子力学,旨在利用物理系统的特性来处理和存储信息。
传统的神经网络使用数字或模拟电子组件作为基本单元进行计算和存储。而物理信息神经网络则使用物理系统中的元件来代替传统的计算单元,例如利用光子、自旋、超导电流等作为信息的载体。
物理信息神经网络的关键特点之一是并行处理能力。由于物理系统的并行性质,可以同时处理多个信息,从而加快计算速度。此外,物理信息神经网络还具有较低的能耗和更高的能效,这是由于物理系统自身的特性所决定的。
在物理信息神经网络的实现中,可以使用不同的物理系统作为基础。例如,光子学是一种常见的选择,利用光的传播和相干性来进行信息处理。另外,自旋电子学和超导电路等也可以作为实现物理信息神经网络的平台。
物理信息神经网络的研究领域仍处于发展阶段,但已经取得了一些有趣的成果。这种新型的神经网络模型有望在信息处理、模式识别和优化等领域展现出独特的优势。然而,目前仍面临许多挑战,包括物理系统的噪声、稳定性和可扩展性等方面的问题。
总的来说,物理信息神经网络是一种利用物理系统来进行信息处理的新型神经网络模型。它结合了神经科学和物理学的思想,具有并行处理、低能耗和高能效等优势,但仍需要进一步的研究和发展来解决相关的挑战。

Python代码

导入包

import torch
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

自定义种子,由于神经网络是随机设置初始解,这是为了使输出的每次结果都固定

def setup_seed(seed):
torch.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
torch.backends.cudnn.deterministic = True

setup_seed(888888)

设置基础参数,包括网格中点的数量,边界点数量,内点数量等等

基础参数

epochs = 10000 # 训练代数
h = 100 # 画图网格密度
N = 1000 # 内点配置点数
N1 = 100 # 边界点配置点数
N2 = 1000 # PDE数据点

设置边界点和偏微分方程右边的值

def interior(n=N):
# 内点
x = torch.rand(n, 1)
y = torch.rand(n, 1)
cond = 2 * torch.pi**2 * torch.sin(torch.pi * x) * torch.sin(torch.pi * y)
return x.requires_grad_(True), y.requires_grad_(True), cond

requires_grad=True 的作用是让 backward 可以追踪这个参数并且计算它的梯度。

最开始定义你的输入是 requires_grad=True ,那么后续对应的输出也自动具有 requires_grad=True

,如代码中的 y 和 z ,而与 z 对 x 求导无关联的 a ,其 requires_grad 仍等于 False。

def down(n=N1):
# 边界 u(x,0)=0
x = torch.rand(n, 1)
y = torch.zeros_like(x)
cond = torch.zeros_like(x)
return x.requires_grad_(True), y.requires_grad_(True), cond

def up(n=N1):
# 边界 u(x,1)=0
x = torch.rand(n, 1)
y = torch.ones_like(x)
cond = torch.zeros_like(x)
return x.requires_grad_(True), y.requires_grad_(True), cond

def left(n=N1):
# 边界 u(0,y)=0
y = torch.rand(n, 1)
x = torch.zeros_like(y)
cond = torch.zeros_like(y)
return x.requires_grad_(True), y.requires_grad_(True), cond

def right(n=N1):
# 边界 u(1,y)=0
y = torch.rand(n, 1)
x = torch.ones_like(y)
cond = torch.zeros_like(y)
return x.requires_grad_(True), y.requires_grad_(True), cond

def data_interior(n=N2):
# 内点
x = torch.rand(n, 1)
y = torch.rand(n, 1)
cond = torch.sin(torch.pi * x) * torch.sin(torch.pi * y)
return x.requires_grad_(True), y.requires_grad_(True), cond

ps:data_interior是解析解的真实值,不要带入到模型中(损失函数)训练哦,requires_grad_(True)是非常有必要的,不然会疯狂报错。

定义神经网络层,我在此定义了一个输入层(x和y输入),三个全连接隐藏层,一个输出层(u)

class MLP(torch.nn.Module):
def init(self):
super(MLP, self).init()
self.net = torch.nn.Sequential(
torch.nn.Linear(2, 32),
torch.nn.Tanh(),
torch.nn.Linear(32, 32),
torch.nn.Tanh(),
torch.nn.Linear(32, 32),
torch.nn.Tanh(),
torch.nn.Linear(32, 32),
torch.nn.Tanh(),
torch.nn.Linear(32, 1)
)

def forward(self, x):return self.net(x)建立损失函数,如同前文所述,损失函数的数量=偏微分方程+边界条件。只要把x,y导入到神经网络中后计算并且与前面设置的右边的值做2范数即可

Loss

loss = torch.nn.MSELoss()

递归求导

def gradients(u, x, order=1):
if order == 1:
return torch.autograd.grad(u, x, grad_outputs=torch.ones_like(u),
create_graph=True,
only_inputs=True, )[0]
else:
return gradients(u, x, order=order-1)

以下4个损失是PDE损失

def l_interior(u):

pde

x, y, cond = interior()
uxy = u(torch.cat([x, y], dim=1))
return loss(-gradients(uxy, x, 2) - gradients(uxy, y, 2), cond)

def l_down(u):
# 损失函数L4
x, y, cond = down()
uxy = u(torch.cat([x, y], dim=1))
return loss(uxy, cond)

def l_up(u):
# 损失函数L5
x, y, cond = up()
uxy = u(torch.cat([x, y], dim=1))
return loss(uxy, cond)

def l_left(u):
# 损失函数L6
x, y, cond = left()
uxy = u(torch.cat([x, y], dim=1))
return loss(uxy, cond)

def l_right(u):
# 损失函数L7
x, y, cond = right()
uxy = u(torch.cat([x, y], dim=1))
return loss(uxy, cond)

构造数据损失

def l_data(u):
# 损失函数L8
x, y, cond = data_interior()
uxy = u(torch.cat([x, y], dim=1))
return loss(uxy, cond)

模型训练,这个就不多说了

Training

u = MLP()
opt = torch.optim.Adam(params=u.parameters())

初始化模型的参数,并将它们传入Adam函数构造出一个Adam优化器

这里可以通过设定 lr的数值来给定学习率

for i in range(epochs):
opt.zero_grad()
# 将这一轮的梯度清零,防止其影响下一轮的更新
l = l_interior(u) + l_up(u) + l_down(u) + l_left(u) + l_right(u)
l.backward()
# 反向计算出各参数的梯度
opt.step()
# 更新网络中的参数
if i % 100 == 0:
print(i)

结果对比(无可视化)

xc = torch.linspace(0, 1, h)
xm, ym = torch.meshgrid(xc, xc)
xx = xm.reshape(-1, 1)
yy = ym.reshape(-1, 1)
xy = torch.cat([xx, yy], dim=1)
u_pred = u(xy)
u_real = torch.sin(torch.pi * xx) * torch.sin(torch.pi * yy)
u_error = torch.abs(u_pred-u_real)
u_pred_fig = u_pred.reshape(h,h)
u_real_fig = u_real.reshape(h,h)
u_error_fig = u_error.reshape(h,h)
print("Max abs error is: ", float(torch.max(torch.abs(u_pred - torch.sin(torch.pi * xx) * torch.sin(torch.pi * yy)))))

可视化输出结果

作PINN数值解图

fig = plt.figure(1, figsize=(12, 5)) # 调整图像大小
ax = fig.add_subplot(131, projection=‘3d’) # 使用子图
ax.plot_surface(xm.detach().numpy(), ym.detach().numpy(), u_pred_fig.detach().numpy())
ax.text2D(0.5, 0.9, “PINN Solution”, transform=ax.transAxes)

作真实解图

ax = fig.add_subplot(132, projection=‘3d’) # 使用子图
ax.plot_surface(xm.detach().numpy(), ym.detach().numpy(), u_real_fig.detach().numpy())
ax.text2D(0.5, 0.9, “Real Solution”, transform=ax.transAxes)

绘制误差图

fig = plt.figure(2, figsize=(8, 6)) # 调整误差图的大小
ax = fig.add_subplot(111, projection=‘3d’)
ax.plot_surface(xm.detach().numpy(), ym.detach().numpy(), u_error_fig.detach().numpy())
ax.text2D(0.5, 0.9, “Absolute Error”, transform=ax.transAxes)

plt.show()

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/341227.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue 组件 import make sure to provide the “name“ option.

百度了好多结果,都过时了,例如: 模块引入是否加{} 再比如: 对于递归组件,请确保提供“name”选项。 出现该错误情况之一: 错误由未正确引入组件或子组件引起,如element-ui中form表单组件未引…

DRAM、SRAM、PSRAM和Flash

DRAM、SRAM和Flash都属于存储器,DRAM通常被称为内存,也有些朋友会把手机中的Flash闪存误会成内存。SRAM的存在感相对较弱,但他却是CPU性能发挥的关键。DRAM、SRAM和Flash有何区别,它们是怎样工作的? DRAM:…

vue3+vite+ts+pinia新建项目(略详细版)

1、新建项目 npm create vite@latest 2、安装依赖 yarn add vue-router yarn add -D @types/node vite-plugin-pages sass sass-loader 3、配置别名 //vite.config.ts import { defineConfig } from vite import path from node:path export default defineConfig({ plu…

Open CV 图像处理基础:(六)在Java中使用 Open CV进行图片翻转和图片旋转

在Java中使用 Open CV进行图片翻转和图片旋转 目录 在Java中使用 Open CV进行图片翻转和图片旋转前言图片翻转函数代码示例其它翻转方向垂直翻转两轴翻转 图片旋转函数代码示例 Open CV 专栏导航 前言 在Java中使用OpenCV进行图片翻转和旋转是一种基本的图像处理技术&#xff0…

单片机中的PWM(脉宽调制)的工作原理以及它在电机控制中的应用。

目录 工作原理 在电机控制中的应用 脉宽调制(PWM)是一种在单片机中常用的控制技术,它通过调整信号的脉冲宽度来控制输出信号的平均电平。PWM常用于模拟输出一个可调电平的数字信号,用于控制电机速度、亮度、电压等。 工作原理 …

Java21 如何使用switch case

1. Java8 和 Java21 Java8 引入字符串和枚举 Java21 可以返回值, yield关键字, switch 表达式, 模式匹配, null值处理 2. 代码案例 1. Java8 public static void java8() {String day "tuesday";switch (day) {case "monday":System.out.println("w…

使用Notepad++将多行数据合并成一行

步骤 1、按CtrlF,弹出“替换”的窗口; 2、选择“替换”菜单; 3、“查找目标”内容输入为:\r\n; 4、“替换为”内容为空; 5、“查找模式”选择为正则表达式; 6、设置好之后,点击“全…

ChatGPT:人工智能与人类交流的桥梁

在人工智能的浪潮中,ChatGPT以其独特的交流能力成为了一个亮点。作为一个基于强大的GPT-4模型的聊天机器人,ChatGPT不仅仅是技术的展示,它更是人工智能与人类交流的桥梁。 人工智能的语言理解革命 ChatGPT的出现标志着人工智能在语言理解和…

K8S集群重新初始化--详细过程

K8S集群重新初始化 1、master节点1.1、在master节点执行下面reset命令:1.2、手动清除配置信息,这一步很关键:1.3、重新引导集群1.4、创建配置目录,并复制权限配置文件到用户目录下:1.5 查看集群状态1.6 安装Calico网络…

微信小程序开发WebSocket通讯

官方文档说明:入口 WebSocket连接的链接只支持wss加密方式,且只能用域名的方式 该域名还要在微信公众平台的小程序中登记才能使用,开发->开发管理->服务器域名->修改 该域名要和https使用的一致 以域名地址:dtu.aab…

OpenAI推出GPT商店和ChatGPT Team服务

🦉 AI新闻 🚀 OpenAI推出GPT商店和ChatGPT Team服务 摘要:OpenAI正式推出了其GPT商店和ChatGPT Team服务。用户已经创建了超过300万个ChatGPT自定义版本,并分享给其他人使用。GPT商店集结了用户为各种任务创建的定制化ChatGPT&a…

杨中科 .NETCORE NuGet

一 简介 Zack.EFCore.Batch 使用这个开发包Entity Framework Core用户可以使用LINQ语句删除或者更新多条数据库记录,操作只执行一条SQL语句并且不需要首先把实体对象加载到内存中。这个开发包支持Entity Framework Core 5.0以及更高版。 操作说明: 第一步 Install-…