随机2D形状周围层流预测!基于飞桨实现图形神经网络

news2024/11/28 16:40:46

项目背景

近年来,快速流场预测领域一直由基于像素的卷积神经网络(Convolution Neural Network,CNN)主导。当 CFD 与基于 CNN 的神经网络模型耦合时,来自网格的数据必须在笛卡尔网格上进行插值,然后再投影回网格。然而均匀笛卡尔网格的内在几何表示较差,相关的计算成本很大,并不适合快速流场预测。与 CNN 不同,图卷积神经网络(Graph Convolution Neural Network,GCNN)可以直接应用于实体拟合的三角网格,从而与 CFD 求解器轻松耦合,解决上述问题。本项目选择复现基于 GCNN 结构的论文《Graph neural networks for laminar flow prediction around random two-dimensional shapes》,验证飞桨框架能够基于 GCNN 模型实现 2D 障碍物周围层流预测的能力。

论文原文

https://hal.archives-ouvertes.fr/hal-03432662/document

原文代码

https://github.com/cfl-minds/gnn_laminar_flow

开发环境与实现过程

开发环境

本文依托于飞桨框架2.4版本实现 2D 障碍物周围层流预测的图卷积神经网络。可以通过访问飞桨官网的安装文档完成安装。详情见链接:https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/install/conda/macos-conda.html

实现过程

图卷积神经网络的基本组成部分是卷积块。卷积块由一个两步图卷积层和一个两步平滑层组成。在论文中,节点和边上的特征矩阵分别用表示,其中,Nv 和 NE 是节点和边的数量,dV 和 dE 是节点和边上特征向量的维度。卷积层将节点级消息传播到边缘,然后聚合新的边缘特征并根据以下规则更新节点特征。
其中,v1 和 v2 是由边 e 连接的两个节点,N(v)是围绕节点 v 的相邻边的集合。卷积核 fe 和 fv 为单隐藏层的全连接神经网络,隐藏层中的神经元数量设置为128。
节点特征更新代码如下:

def update_node_features(node_features, grad_P1, num_filters, initializer, message_fn):
    message_input = paddle.concat([node_features, grad_P1], axis=1)
    updated = message_fn(message_input)
    return updated

边特征更新代码如下:

def update_symmetry_edge_features(node_features, edges, edge_features, edge_feat_dim, initializer, message_fn):
    n_nodes = paddle.to_tensor(node_features.shape[0])
    n_features = paddle.to_tensor(node_features.shape[1])
    reshaped = paddle.reshape(node_features[edges], shape=[-1, 2 * n_features])
    symmetric = 0.5 * paddle.add(reshaped[:, 0:n_features], reshaped[:, n_features:2 * n_features])
    asymmetric = 0.5 * paddle.abs(paddle.subtract(reshaped[:, 0:n_features],
    reshaped[:, n_features:2 * n_features]))
    inputs = paddle.concat([symmetric, asymmetric, edge_features], axis=1)
    messages = message_fn(inputs)  # n_edges, n_output
    n_edges = edges.shape[0]
    updates = paddle.slice(
        paddle.add(paddle.index_add_(paddle.zeros([n_edges, messages.shape[1]]), edges[:, 0], 0, messages),
        paddle.index_add_(paddle.zeros([n_edges, messages.shape[1]]), edges[:, 1], 0, messages)),
        axes=[0, 1], starts=[0, 0], ends=[n_nodes, messages.shape[1]])
    return messages, updates

在边缘卷积步骤中,对称节点特征
优先于 x1 和 x2,以保持排列不变性。节点卷积步骤中的求和对于相邻边的排列也是不变的。平滑图层对输出图形执行平均操作。在三角网格上实现的平均内核分为两个步骤:

添加此层的动机不是为了消息传播,而是为了减少节点要素的空间变异性。它通过相邻节点要素的补偿来压低卷积层的特征图。平滑层代码如下:

class EdgeSmoothing(nn.Layer):
    def __init__(self):
        super(EdgeSmoothing, self).__init__()
    def forward(self, to_concat, node_features, edges, count):
        n_nodes = paddle.to_tensor(node_features.shape[0])
        flow_on_edge = paddle.mean(node_features[edges], axis=1)
        aggre_flow = paddle.add(paddle.index_add_(paddle.zeros([edges.shape[0], flow_on_edge.shape[1]]), edges[:, 0], 0,flow_on_edge[:, :]),
        paddle.index_add_(paddle.zeros([edges.shape[0], flow_on_edge.shape[1]]), edges[:, 1], 0,flow_on_edge[:, :]))
        return paddle.concat([to_concat, paddle.divide(aggre_flow[:n_nodes, :], count)], axis=1)

下图为论文中采用的网络架构图,该架构图由图卷积层和平滑层组成。输入由三个图像组成,8个卷积块/平滑层堆叠形成图卷积神经网络,然后以1×1卷积作为输出层。架构中一个重要组成部分是从输入图到卷积块的跳过连接。在每个平滑图层之后,结点的坐标将连接到结点要素。这些跳跃连接为公式中的边缘卷积步骤提供空间信息。

图1 网络架构图

网络架构代码如下:

class InvariantEdgeModel(nn.Layer):
    def __init__(self, edge_feature_dims, num_filters, initializer):
        super(InvariantEdgeModel, self).__init__()
        self.edge_feat_dims = edge_feature_dims
        self.num_filters = num_filters
        self.initializer = initializer
        self.layer0 = InvariantEdgeConv(self.edge_feat_dims[0], self.num_filters[0], self.initializer)
        self.layer1 = InvariantEdgeConv(self.edge_feat_dims[1], self.num_filters[1], self.initializer)
        self.layer2 = InvariantEdgeConv(self.edge_feat_dims[2], self.num_filters[2], self.initializer)
        self.layer3 = InvariantEdgeConv(self.edge_feat_dims[3], self.num_filters[3], self.initializer)
        self.layer4 = InvariantEdgeConv(self.edge_feat_dims[4], self.num_filters[4], self.initializer)
        self.layer5 = InvariantEdgeConv(self.edge_feat_dims[5], self.num_filters[5], self.initializer)
        self.layer6 = InvariantEdgeConv(self.edge_feat_dims[6], self.num_filters[6], self.initializer)
        self.layer7 = InvariantEdgeConv(self.edge_feat_dims[7], self.num_filters[7], self.initializer)
        self.layer8 = nn.Linear(10, 3)
        self.smoothLayer = EdgeSmoothing()
    def forward(self, node_input, edges, edge_input, smoothing_weights):
        new_node_features_0, new_edge_features_0 = self.layer0(node_input, edge_input, edges)
        smoothed_0 = self.smoothLayer(node_input[:, 0:2], new_node_features_0, edges, smoothing_weights)
        new_node_features_1, new_edge_features_1 = self.layer1(smoothed_0, new_edge_features_0, edges)
        smoothed_1 = self.smoothLayer(node_input[:, 0:2], new_node_features_1, edges, smoothing_weights)
        new_node_features_2, new_edge_features_2 = self.layer2(smoothed_1, new_edge_features_1, edges)
        smoothed_2 = self.smoothLayer(node_input[:, 0:2], new_node_features_2, edges, smoothing_weights)
        new_node_features_3, new_edge_features_3 = self.layer3(smoothed_2, new_edge_features_2, edges)
        smoothed_3 = self.smoothLayer(node_input[:, 0:2], new_node_features_3, edges, smoothing_weights)
        new_node_features_4, new_edge_features_4 = self.layer4(smoothed_3, new_edge_features_3, edges)
        smoothed_4 = self.smoothLayer(node_input[:, 0:2], new_node_features_4, edges, smoothing_weights)
        new_node_features_5, new_edge_features_5 = self.layer5(smoothed_4, new_edge_features_4, edges)
        smoothed_5 = self.smoothLayer(node_input[:, 0:2], new_node_features_5, edges, smoothing_weights)
        new_node_features_6, new_edge_features_6 = self.layer6(smoothed_5, new_edge_features_5, edges)
        smoothed_6 = self.smoothLayer(node_input[:, 0:2], new_node_features_6, edges, smoothing_weights)
        new_node_features_7, new_edge_features_7 = self.layer7(smoothed_6, new_edge_features_6, edges)
        smoothed_7 = self.smoothLayer(node_input[:, 0:2], new_node_features_7, edges, smoothing_weights)
        node_outputs = self.layer8(smoothed_7[:, 0:])
        return node_outputs

项目结果


为了展示复现的效果,我们使用复现模型对圆柱流场进行预测,结果如下:

图2 预测效果对比图

其中左侧为论文原文中采用的真实流场,右侧为我们复现的模型所预测的流场。可见我们得到的预测值(右边)与真实值(左边)基本一致,模型精度很好。我们复现的模型在实验结果中的 MAE 为0.0046,与原论文的结果0.0043也非常接近,验证了飞桨框架能够基于该模型实现 2D 障碍物周围层流预测的能力。

心得体会

百度飞桨的论文复现比赛为我们团队提供了宝贵的学习和成长机会。这个比赛不仅让我们深入了解流场预测这个细分领域,还锻炼了我们团队合作和解决问题的能力。现在回顾这次比赛,值得称赞的地方有很多。第一,飞桨官方强大的赛事组织能力,将比赛组织的规范和有序。从项目前期宣传、队伍报名、赛前讲解、赛中答疑以及结果提交一环扣一环,项目安排有序,每支队伍都清楚每个阶段该干什么。第二,比赛中,飞桨科学计算团队的技术人员提供细致答疑。比赛要求我们仔细阅读论文,并根据论文提供的参考代码使用飞桨进行复现。这个过程不仅需要我们对深度学习模型有深入的理解,也需要我们熟悉飞桨框架。作为一个新手,难免遇到各种各样的技术问题,每次找飞桨技术人员,总能得到耐心细致的解答。除此之外,官方还会定期跟踪复现的进展情况,有问题立即为选手解决问题。第三,参加飞桨的论文复现比赛也为我们打开了更广阔的视野。通过此次比赛,我们有机会接触到 AI for Science 这个领域很多优秀论文。在复现实践的过程中,我们深入研究了这些论文的方法和技术,加深了我们对这个领域的理解,了解到了学术界的最新进展和应用。最后,我要衷心感谢百度飞桨团队所有组织者和工作人员。他们的辛勤付出和专业支持使得这次比赛得以顺利进行。也要特别感谢陆林、汪璐、孔德天这些一起参加比赛的师兄弟,感谢我们团队中每一位成员的努力和奉献。未来,我们将继续保持学习的态度,不断探索和创新,争取为推动该领域的发展做出贡献。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Jetpack Compose Material3 组件之 DatePicker(日期选择)

前言 在之前我使用 Comose 写 APP 的时候,官方还没有给出关于 DatePicker 的解决方案。 当时为了在 Compose 中实现 DatePicker ,大致有两种方案: 一是使用原生 VIew 的 DatePicker,但是因为觉得我即然都用 Compose 了&#xf…

图书推荐|Python数据分析与挖掘实战(第2版)

Python数据分析与挖掘实战(第2版)一共分为三个部分,包括基础篇(第1~5章)、实战篇(第6~12章)、提高篇(第13章)。其中基础篇介绍了数据挖掘的基本原…

揭秘猫狗的微生物世界:肠道微生物群的意义和影响

谷禾健康 “铲屎官”们都希望自己的宠物有一个健康的身体。但是猫狗都不会说话,平时我们只能从它们的精神状态来判断它们是否健康,但这并不准确。去宠物医院又不太方便,很多猫咪和狗狗还会对抽血等检查有所抗拒。 肠道微生物检测在人类中的应…

边云协同:大小模型如何协同推理?

1 背景 “化繁为简、大巧不工”是机器学习的初衷之一。 费米曾讲述一个故事,冯诺依曼告诉他,用四个参数就可以拟合出一头大象,用五个参数就可以让大象鼻子动起来,这就是“四个参数画大象”的故事。 但AI模型规模不断剧增已是不…

CVE-2023-27524 Apache Superset 身份认证绕过漏洞

漏洞简介 Apache Superset是一个开源的数据可视化和数据探测平台,它基于Python构建,使用了一些类似于Django和Flask的Python web框架。提供了一个用户友好的界面,可以轻松地创建和共享仪表板、查询和可视化数据,也可以集成到其他应…

第一章 string模块

1. string模块介绍 Python中的第三方模块 string 模块解决了一些关于字符串操作的问题。例如,string 模块中可列出所有的大小写英文字母、数字、标点符号、八进制数字字符、十进制数字字符、十六进制数字字符等 Python 中可打印的字符;还可以进行格式化…

学习笔记之MySQL存储引擎

一、MySQL架构 MySQL的连接层处理客户端连接和权限管理,服务层解析和执行SQL语句,引擎层负责数据的存储和检索,存储层处理数据在磁盘上的读写操作。这种架构使得MySQL可以在不同的场景中灵活运行,并根据需求选择合适的存储引擎和…

Spring Security OAuth2.0认证授权 --- 基础篇

一、基本概念 1.1、什么是认证 进入移动互联网时代,大家每天都在刷手机,常用的软件有微信、支付宝、头条等,下边拿微信来举例子说明认证相关的基本概念,在初次使用微信前需要注册成为微信用户,然后输入账号和密码即可…

CVPR2022 多目标跟踪(MOT)汇总-补充篇

为该文章的后续补充https://blog.csdn.net/qq_34919792/article/details/124343166 七、《Multi-Object Tracking Meets Moving UAV》 作者: Shuai Liu†1, Xin Li†2, Huchuan Lu1,2, You He∗3 1Dalian University of Technology, 2Peng Cheng Laboratory, 3Naval Aeronaut…

【yolov5系列】将模型部署到瑞芯微RK3566上面

本篇博客记录将yolov5s移植到瑞芯微3566上的整体流程。当然在其它芯片上的操作类似,差别会在具体的API的调用上。 1 芯片相关 芯片参数:https://www.rock-chips.com/a/cn/product/RK35xilie/2021/0113/1273.htmlCPU:四核,1.8GHZ.N…

CSS查缺补漏之《选择器的复杂用法》

最近在复盘CSS基础知识,发现很多CSS选择器里面还是大有学问,需要详细总结一番,以备差缺补漏~ 作为CSS基础的一大类别,选择器又分为多种类别,本篇内容默认读者已了解并掌握基础选择器【通配符选择器】、【元素选择器】…

企业采用融合CDN战略之前的相关注意事项

很多企业可能都会犹豫是否要从单CDN模式到转向为多CDN模式,一方面因为这可能看起来很复杂,这不仅涉及到需要建立更多的CDN提供商,而且还有其他较多的操作和配置要做,尤其是在当前单CDN供应商似乎一切正常的情况下。但从另一方面来…

【每日算法】【203. 移除链表元素】

☀️博客主页:CSDN博客主页 💨本文由 我是小狼君 原创,首发于 CSDN💢 🔥学习专栏推荐:面试汇总 ❗️游戏框架专栏推荐:游戏实用框架专栏 ⛅️点赞 👍 收藏 ⭐留言 📝&…

《C++高级编程》读书笔记(八、九:类和对象)

1、参考引用 C高级编程(第4版,C17标准)马克葛瑞格尔 2、建议先看《21天学通C》 这本书入门,笔记链接如下 21天学通C读书笔记(文章链接汇总) 1. 编写类 编写类时,需要指定行为或方法 (应用于类的…

8.3 TCP/IP协议与五层体系结构

目录 TCP/IP及五层体系结构 OSI与TCP/IP TCP/IP 的体系结构 沙漏计时器形状的 TCP/IP 协议族 具有五层协议的体系结构 五层协议的体系结构 各层的主要功能 互联网中客户-服务器工作方式 同时为多个客户进程提供服务 TCP/IP及五层体系结构 OSI与TCP/IP TCP/IP 的体系结构 现…

Atcoder Beginner Contest 306

A - Echo AC代码&#xff1a; #include<iostream> #include<algorithm> #include<cstring> using namespace std; int main() {int n;cin>>n;string s;cin>>s;for(int i0;i<n;i){cout<<s[i]<<s[i];}return 0; } B - Base 2 lo…

服务调用OpenFeign

OpenFeign OpenFeign 介绍OpenFeign 的使用OpenFeign 参数传递OpenFeign 超时控制OpenFeign 日志设置OpenFeign 的工作流程 OpenFeign 介绍 Feign 是 SpringCloud组件中一个轻量级RESTful的HTTP服务客户端&#xff0c;Feign集成了Ribbon、RestTemplate 实现了负载均衡的执行Ht…

拉普拉斯方程解决有介质导体球壳问题

一个内径和外径分别为和的导体球壳&#xff0c;带电荷&#xff0c;同心地包围着一个的导体球&#xff0c;使这个导体球接地&#xff0c;求空间各点的电势和这个导体球的感应电荷 我们不难发现&#xff0c;球对称性非常强&#xff0c;电势只和半径有关系 所以我们可以假设电势为…

Python面向对象编程1-面向过程的简单纸牌游戏程序 项目1.6 完整的猜大小纸牌游戏

总项目目标&#xff1a;用面向过程思想设计一个简单的纸牌游戏程序&#xff0c;称为"Higher or Lower"&#xff08;高还是低&#xff09;。游戏中&#xff0c;玩家需要猜测接下来的一张牌是比当前牌高还是低。根据猜测的准确性&#xff0c;玩家可以得到或失去相应的积…

学了些性能知识,实际工作如何开展性能测试?

目录 前言&#xff1a; 确定需求 了解业务 搭建测试环境 脚本执行及监控 收集测试结果 持续学习 前言&#xff1a; 学到了性能测试的知识&#xff0c;接下来如何在实际工作中开展性能测试呢&#xff1f; 确定需求 刚接触性能测试的同学往往不知道性能测试是有需求的。…