PINN神经网络源代码解析(pyTorch)

这篇具有很好参考价值的文章主要介绍了PINN神经网络源代码解析(pyTorch)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考文献

PINN(Physics-informed Neural Networks)的原理部分可参见https://maziarraissi.github.io/PINNs/

考虑Burgers方程,如下图所示,初始时刻u符合sin分布,随着时间推移在x=0处发生间断.
这是一个经典问题,可使用pytorch通过PINN实现对Burgers方程的求解。
PINN神经网络源代码解析(pyTorch),算法,学术论文,神经网络,pytorch,人工智能

源代码与注释

源代码共含有三个文件,来源于Github https://github.com/jayroxis/PINNs

PINN神经网络源代码解析(pyTorch),算法,学术论文,神经网络,pytorch,人工智能
network.py文件用于定义神经网络的结构
train.py文件用于训练神经网络
evaluate.py文件用于测试训练好的模型绘制结果图

建议使用Anaconda构建运行环境,需要安装pytorch和一些辅助包

1、network.py 文件

import torch
import torch.nn as nn
from collections import OrderedDict

# 定义神经网络的架构
class Network(nn.Module):
    # 构造函数
    def __init__(
        self,
        input_size, # 输入层神经元数
        hidden_size, # 隐藏层神经元数
        output_size, # 输出层神经元数
        depth, # 隐藏层数
        act=torch.nn.Tanh, # 输入层和隐藏层的激活函数
    ):
        super(Network, self).__init__()#调用父类的构造函数

        # 输入层
        layers = [('input', torch.nn.Linear(input_size, hidden_size))]
        layers.append(('input_activation', act()))

        # 隐藏层
        for i in range(depth):
            layers.append(
                ('hidden_%d' % i, torch.nn.Linear(hidden_size, hidden_size))
            )
            layers.append(('activation_%d' % i, act()))

        # 输出层
        layers.append(('output', torch.nn.Linear(hidden_size, output_size)))

        #将这些层组装为神经网络
        self.layers = torch.nn.Sequential(OrderedDict(layers))

    # 前向计算方法
    def forward(self, x):
        return self.layers(x)

2、train.py 文件

import math
import torch
import numpy as np
from network import Network

# 定义一个类,用于实现PINN(Physics-informed Neural Networks)
class PINN:
    # 构造函数
    def __init__(self):
        # 选择使用GPU还是CPU
        device = torch.device(
            "cuda") if torch.cuda.is_available() else torch.device("cpu")
        
        # 定义神经网络
        self.model = Network(
            input_size=2,  # 输入层神经元数
            hidden_size=16,  # 隐藏层神经元数
            output_size=1,  # 输出层神经元数
            depth=8,  # 隐藏层数
            act=torch.nn.Tanh  # 输入层和隐藏层的激活函数
        ).to(device)  # 将这个神经网络存储在GPU上(若GPU可用)

        self.h = 0.1  # 设置空间步长
        self.k = 0.1  # 设置时间步长
        x = torch.arange(-1, 1 + self.h, self.h)  # 在[-1,1]区间上均匀取值,记为x
        t = torch.arange(0, 1 + self.k, self.k)  # 在[0,1]区间上均匀取值,记为t

        # 将x和t组合,形成时间空间网格,记录在张量X_inside中
        self.X_inside = torch.stack(torch.meshgrid(x, t)).reshape(2, -1).T

        # 边界处的时空坐标
        bc1 = torch.stack(torch.meshgrid(x[0], t)).reshape(2, -1).T  # x=-1边界
        bc2 = torch.stack(torch.meshgrid(x[-1], t)).reshape(2, -1).T  # x=+1边界
        ic = torch.stack(torch.meshgrid(x, t[0])).reshape(2, -1).T  # t=0边界
        self.X_boundary = torch.cat([bc1, bc2, ic])  # 将所有边界处的时空坐标点整合为一个张量

        # 边界处的u值
        u_bc1 = torch.zeros(len(bc1))  # x=-1边界处采用第一类边界条件u=0
        u_bc2 = torch.zeros(len(bc2))  # x=+1边界处采用第一类边界条件u=0
        u_ic = -torch.sin(math.pi * ic[:, 0])  # t=0边界处采用第一类边界条件u=-sin(pi*x)
        self.U_boundary = torch.cat([u_bc1, u_bc2, u_ic])  # 将所有边界处的u值整合为一个张量
        self.U_boundary = self.U_boundary.unsqueeze(1)

        # 将数据拷贝到GPU
        self.X_inside = self.X_inside.to(device)
        self.X_boundary = self.X_boundary.to(device)
        self.U_boundary = self.U_boundary.to(device)
        self.X_inside.requires_grad = True  # 设置:需要计算对X的梯度

        # 设置准则函数为MSE,方便后续计算MSE
        self.criterion = torch.nn.MSELoss()

        # 定义迭代序号,记录调用了多少次loss
        self.iter = 1

        # 设置lbfgs优化器
        self.lbfgs = torch.optim.LBFGS(
            self.model.parameters(),
            lr=1.0,
            max_iter=50000,
            max_eval=50000,
            history_size=50,
            tolerance_grad=1e-7,
            tolerance_change=1.0 * np.finfo(float).eps,
            line_search_fn="strong_wolfe",
        )

        # 设置adam优化器
        self.adam = torch.optim.Adam(self.model.parameters())

    # 损失函数
    def loss_func(self):
        # 将导数清零
        self.adam.zero_grad()
        self.lbfgs.zero_grad()

        # 第一部分loss: 边界条件不吻合产生的loss
        U_pred_boundary = self.model(self.X_boundary)  # 使用当前模型计算u在边界处的预测值
        loss_boundary = self.criterion(
            U_pred_boundary, self.U_boundary)  # 计算边界处的MSE

        # 第二部分loss:内点非物理产生的loss
        U_inside = self.model(self.X_inside)  # 使用当前模型计算内点处的预测值

        # 使用自动求导方法得到U对X的导数
        du_dX = torch.autograd.grad(
            inputs=self.X_inside,
            outputs=U_inside,
            grad_outputs=torch.ones_like(U_inside),
            retain_graph=True,
            create_graph=True
        )[0]
        du_dx = du_dX[:, 0]  # 提取对第x的导数
        du_dt = du_dX[:, 1]  # 提取对第t的导数

        # 使用自动求导方法得到U对X的二阶导数
        du_dxx = torch.autograd.grad(
            inputs=self.X_inside,
            outputs=du_dX,
            grad_outputs=torch.ones_like(du_dX),
            retain_graph=True,
            create_graph=True
        )[0][:, 0]
        loss_equation = self.criterion(
            du_dt + U_inside.squeeze() * du_dx, 0.01 / math.pi * du_dxx)  # 计算物理方程的MSE

        # 最终的loss由两项组成
        loss = loss_equation + loss_boundary

        # loss反向传播,用于给优化器提供梯度信息
        loss.backward()

        # 每计算100次loss在控制台上输出消息
        if self.iter % 100 == 0:
            print(self.iter, loss.item())
        self.iter = self.iter + 1
        return loss

    # 训练
    def train(self):
        self.model.train()  # 设置模型为训练模式

        # 首先运行5000步Adam优化器
        print("采用Adam优化器")
        for i in range(5000):
            self.adam.step(self.loss_func)
        # 然后运行lbfgs优化器
        print("采用L-BFGS优化器")
        self.lbfgs.step(self.loss_func)

# 实例化PINN
pinn = PINN()

# 开始训练
pinn.train()

# 将模型保存到文件
torch.save(pinn.model, 'model.pth')

运行该文件后模型结果保存在model.pth文件中

3、evaluate.py 文件

import torch
import seaborn as sns
import matplotlib.pyplot as plt

# 选择GPU或CPU
device = torch.device(
    "cuda") if torch.cuda.is_available() else torch.device("cpu")

# 从文件加载已经训练完成的模型
model_loaded = torch.load('model.pth', map_location=device)
model_loaded.eval()  # 设置模型为evaluation状态

# 生成时空网格
h = 0.01
k = 0.01
x = torch.arange(-1, 1, h)
t = torch.arange(0, 1, k)
X = torch.stack(torch.meshgrid(x, t)).reshape(2, -1).T
X = X.to(device)

# 计算该时空网格对应的预测值
with torch.no_grad():
    U_pred = model_loaded(X).reshape(len(x), len(t)).cpu().numpy()

# 绘制计算结果
plt.figure(figsize=(5, 3), dpi=300)
xnumpy = x.numpy()
plt.plot(xnumpy, U_pred[:, 0], 'o', markersize=1)
plt.plot(xnumpy, U_pred[:, 20], 'o', markersize=1)
plt.plot(xnumpy, U_pred[:, 40], 'o', markersize=1)
plt.figure(figsize=(5, 3), dpi=300)
sns.heatmap(U_pred, cmap='jet')
plt.show()

运行该文件后,可绘制u场的结果
PINN神经网络源代码解析(pyTorch),算法,学术论文,神经网络,pytorch,人工智能文章来源地址https://www.toymoban.com/news/detail-652101.html

到了这里,关于PINN神经网络源代码解析(pyTorch)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • matlab实现卷积神经网络CNN(二)——代码实现与解析

            基于上一篇文章对于CNN网络结构的整理,我们将用matlab实现一维数据的CNN网络单多输入和单多输出。         文中字母含义详情可见上一篇文章。         data数据格式应为 M×SN ;M为一维数据的长度(即一个样本有多少个点),由于是一维数据,所以宽度

    2024年02月05日
    浏览(32)
  • Node.js入门笔记(包含源代码)以及详细解析

    01、如何在终端中执行js 文件 目标 :将下面的代码语句在中断中执行 代码演示: 方法: 在文件上右击打开在终端中执行 ,然后输入node空格 输入需要执行的文件名字 02、基于 fs 模块读写文件内容 目标:使用fs模代码操作文件在终端中的读写操作 + 1、加载 fs 模块对象 2、写

    2024年02月14日
    浏览(36)
  • 神经网络学习小记录73——Pytorch CA(Coordinate attention)注意力机制的解析与代码详解

    CA注意力机制是最近提出的一种注意力机制,全面关注特征层的空间信息和通道信息。 Github源码下载地址为: https://github.com/bubbliiiing/yolov4-tiny-pytorch 复制该路径到地址栏跳转。 该文章的作者认为现有的注意力机制(如CBAM、SE)在求取通道注意力的时候,通道的处理一般是采

    2024年02月06日
    浏览(27)
  • 【3D激光SLAM】LOAM源代码解析--scanRegistration.cpp

    ·【3D激光SLAM】LOAM源代码解析–scanRegistration.cpp ·【3D激光SLAM】LOAM源代码解析–laserOdometry.cpp ·【3D激光SLAM】LOAM源代码解析–laserMapping.cpp ·【3D激光SLAM】LOAM源代码解析–transformMaintenance.cpp 本系列文章将对LOAM源代码进行讲解,在讲解过程中,涉及到论文中提到的部分, 会结

    2024年02月11日
    浏览(22)
  • 【3D激光SLAM】LOAM源代码解析--transformMaintenance.cpp

    ·【3D激光SLAM】LOAM源代码解析–scanRegistration.cpp ·【3D激光SLAM】LOAM源代码解析–laserOdometry.cpp ·【3D激光SLAM】LOAM源代码解析–laserMapping.cpp ·【3D激光SLAM】LOAM源代码解析–transformMaintenance.cpp 本系列文章将对LOAM源代码进行讲解,在讲解过程中,涉及到论文中提到的部分, 会结

    2024年02月11日
    浏览(31)
  • 张正友相机标定(全流程,含畸变,matlab源代码解析)

    张正友标定的具体原理很多文章已经介绍,这里主要结合源代码对其中的基本原理及本人遇到的问题进行介绍。(仅介绍基本原理供本人复习,同时方便他人,如有问题,请及时指正勿喷) 相机标定,即获取其内参、外参、畸变系数(内参与外参及相机成像模型的解释可以参

    2024年02月04日
    浏览(36)
  • 【3D激光SLAM】LOAM源代码解析--laserOdometry.cpp

    ·【3D激光SLAM】LOAM源代码解析–scanRegistration.cpp ·【3D激光SLAM】LOAM源代码解析–laserOdometry.cpp ·【3D激光SLAM】LOAM源代码解析–laserMapping.cpp ·【3D激光SLAM】LOAM源代码解析–transformMaintenance.cpp 本系列文章将对LOAM源代码进行讲解,在讲解过程中,涉及到论文中提到的部分, 会结

    2024年02月11日
    浏览(59)
  • 嵌入式音频开发:ES8311驱动开发及源代码解析

    嵌入式音频开发:ES8311驱动开发及源代码解析 嵌入式系统在现代科技应用中起着重要的作用,而其中音频开发更是一个关键领域。本文将重点讨论如何开发 ES8311 驱动程序,并提供相应的源代码。 一、ES8311芯片概述 ES8311 是一款集成了低功耗立体声CODEC功能的音频编解码芯片

    2024年01月18日
    浏览(103)
  • .net core下优秀的日志框架使用解析,附源代码

    在 .NET Core 中,日志是一个非常重要的组件,它可以帮助我们记录应用程序的运行情况,以便在出现问题时进行排查。在本文中,我们将介绍五个优秀的 .NET Core 日志框架,它们分别是 Serilog、NLog、Log4Net、 Microsoft.Extensions.Logging 和 Loupe。我们将为每个框架提供使用方法及步骤

    2024年02月05日
    浏览(40)
  • ASP.NET网络在线考试系统(源代码+论文)ASP.NET网络商店销售管理系统的设计与实现(源代码+论文)

    引言 随着网络技术的飞速发展,网络经济与人们的生活越来越紧密的联系在一起,随着信息技术的发展,网上购物与网上销售也在逐渐发展和普及。消费者与销售商都迫切需要一种简便与高速高效的购物与销售方式,在线商店管理系统的出现正好满足人们的这种需要,通过网

    2024年02月05日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包