2025.2.23机器学习笔记:PINN文献阅读
2025.2.23周报
- 一、文献阅读
- 题目信息
- 摘要
- Abstract
- 创新点
- 网络架构
- 架构A
- 架构B
- 架构C
- 实验
- 结论
- 后续展望
一、文献阅读
题目信息
- 题目: Physics-Informed Neural Networks for Modeling Water Flows in a River Channel
- 期刊: IEEE TRANSACTIONS ON ARTIFICIAL INTELLIGENCE
- 作者: Luis Fernando Nazari,Eduardo Camponogara,Laio Oriel Seman
- 发表时间: 2024/03/03
- 文章链接: https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=9863669
摘要
洪水灾害对世界各地的影响重大,造成了严重的社会和经济问题,洪水防控策略依赖于水文预报模型,而这些模型主要通过数据驱动方法获得。所以模型需要达到期望的精度需要大量物理参数,而这些参数往往难以确获取;且传统的数据驱动模型往往需要可靠且真实的数据保证模型的数值模拟准确性。所以在以上背景研究下,本论文提出了一个基于物理信息神经网络(Physics-Informed Neural Networks,PINNs)的河道水流替代模型,作者总共设计了三个PINNs模型架构A、B、C,通过调节模型的输入与输出参数以探究在不同场景中模型的适用性。其中在架构C中作者引入了贝叶斯推断,限制参数偏离合理范围,提升物理可解释性。该论文旨在解决传统方法存在的问题,为流域水流的水文建模领域的研究做出贡献。
Abstract
Flood disasters exert profound impacts on populations worldwide, resulting in severe social and economic challenges. Effective flood prevention strategies hinge on hydrological forecasting models, which are predominantly derived through data-driven approaches. Achieving the desired precision in these models necessitates a multitude of physical parameters, which are often difficult to accurately acquire. Moreover, conventional data-driven models typically require reliable and authentic datasets to ensure the accuracy of numerical simulations. Against this backdrop, this paper proposes a surrogate model for river channel water flow based on Physics-Informed Neural Networks (PINNs). The authors developed three distinct PINN architectures—A, B, and C—by adjusting the input and output parameters to investigate their applicability across varying scenarios. Notably, in Architecture C, Bayesian inference is introduced to constrain parameter deviations within physically plausible ranges, thereby enhancing physical interpretability. This study aims to address the limitations inherent in traditional methodologies, contributing to advancements in the field of hydrological modeling for watershed water flows.
创新点
- 将PINNs应用于河道水流建模,通过融合圣维南方程的物理约束与实测数据,解决了传统方法中数据稀缺和参数依赖的问题;
- 通过PINNs直接预测水文动力学的关键参数,如:曼宁系数 n n n和河床坡度 S 0 S_0 S0。这种方法减少了传统方法中对地区数据的依赖;
- 使用了基于贝叶斯推理的PINNs训练新方法,解决参数预测的不确定性问题。
网络架构
本文提出了一种基于物理信息神经网络(PINN)的河流水流建模方法,重点解决了传统水文模型中参数识别困难和数据不足的问题。
作者提出了圣维南方程作为物理模型:
关于 Q ( x , t ) Q(x,t) Q(x,t) 与 P w ( x , t ) P_w(x,t) Pw(x,t)的形象表示如下图所示:
下面对论文中三种网络架构进行分析:
架构A
- 输入:
ψ = [ x , t , h ( x , t ) , Δ h t ( x , t ) , Δ h x ( x , t ) ] ∈ R 5 \psi = [x, t, h(x,t), \Delta h_t(x,t), \Delta h_x(x,t)] \in \mathbb{R}^5 ψ=[x,t,h(x,t),Δht(x,t),Δhx(x,t)]∈R5
其中,参数含义如下:
x x x:空间;
t t t:时间;
h ( x , t ) h(x,t) h(x,t):水位;
Δ h t \Delta h_t Δht :
数值微分计算的时间导数;
Δ h x \Delta h_x Δhx:空间导数。 - 输出:
模型的输出为 Q Q Q水流速。 - 损失函数
PINN的模型架构的损失函数由两部分组成:数据误差和物理误差,即 Loss = MSE u + MSE p \text{Loss} = \text{MSE}_u + \text{MSE}_p Loss=MSEu+MSEp
M S E u MSE_u MSEu为数据误差,公式表达为: MSE u = 1 N u ∑ i = 1 N u ∣ N N Q ( ψ u i ) − Q u i ∣ 2 \text{MSE}_u = \frac{1}{N_u} \sum_{i=1}^{N_u} \left| \mathcal{NN}_Q(\psi_u^i) - Q_u^i \right|^2 MSEu=Nu1∑i=1Nu NNQ(ψui)−Qui 2,表示真实值与预测值之间的误差。具体展开为: MSE p = 1 N c ∑ i = 1 N c [ ∣ ∂ A ∂ t + ∂ N N Q ∂ x ∣ 2 + ∣ ∂ N N Q ∂ t + ∂ ∂ x ( N N Q 2 A ) + g A ( ∂ h ∂ x + S f − S 0 ) ∣ 2 ] \text{MSE}_p = \frac{1}{N_c} \sum_{i=1}^{N_c} \left[ \left| \frac{\partial A}{\partial t} + \frac{\partial \mathcal{NN}_Q}{\partial x} \right|^2 + \left| \frac{\partial \mathcal{NN}_Q}{\partial t} + \frac{\partial}{\partial x} \left( \frac{\mathcal{NN}_Q^2}{A} \right) + gA \left( \frac{\partial h}{\partial x} + S_f - S_0 \right) \right|^2 \right] MSEp=Nc1∑i=1Nc[ ∂t∂A+∂x∂NNQ 2+ ∂t∂NNQ+∂x∂(ANNQ2)+gA(∂x∂h+Sf−S0) 2]
架构B
- input:
ψ = [ x , t , h ( x , t ) ] ∈ R 3 \psi = [x, t, h(x,t)] \in \mathbb{R}^3 ψ=[x,t,h(x,t)]∈R3
其中,参数含义如下:
x x x:空间;
t t t:时间;
h ( x , t ) h(x,t) h(x,t):水位程高; - output:
输出为: h和Q,分别表示水位高度与流速。 - Loss function
损失函数扩展为三部分,分别为:数据误差和圣维南方程质量守恒约束以及圣维南方程动量守恒约束
l o s s f u n c t i o n = 1 N u ∑ i = 1 N u ∣ N N ( ψ u i ) − ( h i , Q i ) ∣ 2 + 1 N c ∑ i = 1 N c ∣ ∂ A ∂ h ∂ ∂ t N N h ( ψ c i ) + ∂ ∂ x N N Q ( ψ c i ) ∣ 2 + 1 N c ∑ i = 1 N c ∣ ∂ ∂ t N N Q ( ψ c i ) + ∂ ∂ x N N Q 2 ( ψ c i ) A ( x c i , t c i ) + g A ( x c i , t c i ) ( ∂ ∂ x N N h ( ψ c i ) + S f ( x c i , t c i ) − S 0 ) ∣ 2 loss function = \frac{1}{N_{u}} \sum_{i=1}^{N_{u}}\left|\mathcal{N N}\left(\psi_{u}^{i}\right)-\left(h^{i}, Q^{i}\right)\right|^{2} +\frac{1}{N_{c}} \sum_{i=1}^{N_{c}}\left|\frac{\partial A}{\partial h} \frac{\partial}{\partial t} \mathcal{N} \mathcal{N}_{h}\left(\psi_{c}^{i}\right)+\frac{\partial}{\partial x} \mathcal{N} \mathcal{N}_{Q}\left(\psi_{c}^{i}\right)\right|^{2} +\frac{1}{N_{c}} \sum_{i=1}^{N_{c}} \left\lvert\, \frac{\partial}{\partial t} \mathcal{N N}_{Q}\left(\psi_{c}^{i}\right)+\frac{\partial}{\partial x} \frac{\mathcal{N N}_{Q}^{2}\left(\psi_{c}^{i}\right)}{A\left(x_{c}^{i}, t_{c}^{i}\right)}\right. +\left.g A\left(x_{c}^{i}, t_{c}^{i}\right)\left(\frac{\partial}{\partial x} \mathcal{N} \mathcal{N}_{h}\left(\psi_{c}^{i}\right)+S_{f}\left(x_{c}^{i}, t_{c}^{i}\right)-S_{0}\right)\right|^{2} lossfunction=Nu1i=1∑Nu NN(ψui)−(hi,Qi) 2+Nc1i=1∑Nc ∂h∂A∂t∂NNh(ψci)+∂x∂NNQ(ψci) 2+Nc1i=1∑Nc ∂t∂NNQ(ψci)+∂x∂A(xci,tci)NNQ2(ψci)+gA(xci,tci)(∂x∂NNh(ψci)+Sf(xci,tci)−S0) 2
其中, N c N_c Nc为配准点(collocation points)的数量,这些点是用来强制满足物理方程的时空坐标; N N h ( ψ c i ) \mathcal{N} \mathcal{N}_{h}\left(\psi_{c}^{i}\right) NNh(ψci):神经网络预测的水位高度h在配准点 ( x c i , t c i ) \left(x_c^i, t_c^i\right) (xci,tci)上的值; N N Q ( ψ c i ) \mathcal{N} \mathcal{N}_{Q}\left(\psi_{c}^{i}\right) NNQ(ψci):神经网络预测的水流量Q在配准 ( x c i , t c i ) \left(x_c^i, t_c^i\right) (xci,tci)上的值。
架构C
- input:
ψ = [ x , t , h ( x , t ) , Δ h t ( x , t ) ] ∈ R 4 \psi = [x, t, h(x,t), \Delta h_t(x,t)] \in \mathbb{R}^4 ψ=[x,t,h(x,t),Δht(x,t)]∈R4
其中,参数 R 4 \mathbb{R}^4 R4表示四维空间;
x x x:空间;
t t t:时间;
h h h:水位;
Δ h t \Delta h_t Δht:表示水面程高对时间t的求导。 - 输出:
输出与架构B相同都是 h h h和 Q Q Q,输出是一个二维向量。 - 损失函数
与架构A和架构B不同的是,架构C在损失函数引入贝叶斯推断,增加惩罚项,其整体的损失函数表示为:
Loss Function = 1 N u ∑ i = 1 N u ∣ N N ( ψ u i ) − [ h i , Q i ] ∣ 2 ⏟ 数据误差 + 1 N c ∑ i = 1 N c ∣ ∂ A ∂ h ∂ N N h ∂ t + ∂ N N Q ∂ x ∣ 2 ⏟ 质量守恒 + 1 N c ∑ i = 1 N c ∣ ∂ N N Q ∂ t + ∂ ∂ x N N Q 2 A + g A ( ∂ N N h ∂ x + S f − S 0 ) ∣ 2 ⏟ 动量守恒 + ∑ i = 1 N p 1 σ i 2 ( λ i − μ i ) 2 ⏟ 贝叶斯正则化 + 1 N c ∑ i = 1 N c ∣ ∂ N N h ∂ t − Δ h t ∣ 2 ⏟ 导数误差 \text{Loss Function} = \underbrace{\frac{1}{N_u} \sum_{i=1}^{N_u} \left| \mathcal{NN}(\psi_u^i) - [h^i, Q^i] \right|^2}_{\text{数据误差}} + \underbrace{\frac{1}{N_c} \sum_{i=1}^{N_c} \left| \frac{\partial A}{\partial h} \frac{\partial \mathcal{NN}_h}{\partial t} + \frac{\partial \mathcal{NN}_Q}{\partial x} \right|^2}_{\text{质量守恒}} + \underbrace{\frac{1}{N_c} \sum_{i=1}^{N_c} \left| \frac{\partial \mathcal{NN}_Q}{\partial t} + \frac{\partial}{\partial x} \frac{\mathcal{NN}_Q^2}{A} + g A \left( \frac{\partial \mathcal{NN}_h}{\partial x} + S_f - S_0 \right) \right|^2}_{\text{动量守恒}} + \underbrace{\sum_{i=1}^{N_p} \frac{1}{\sigma_i^2} \left( \lambda_i - \mu_i \right)^2}_{\text{贝叶斯正则化}} + \underbrace{\frac{1}{N_c} \sum_{i=1}^{N_c} \left| \frac{\partial \mathcal{NN}_h}{\partial t} - \Delta h_t \right|^2}_{\text{导数误差}} Loss Function=数据误差 Nu1i=1∑Nu NN(ψui)−[hi,Qi] 2+质量守恒 Nc1i=1∑Nc ∂h∂A∂t∂NNh+∂x∂NNQ 2+动量守恒 Nc1i=1∑Nc ∂t∂NNQ+∂x∂ANNQ2+gA(∂x∂NNh+Sf−S0) 2+贝叶斯正则化 i=1∑Npσi21(λi−μi)2+导数误差 Nc1i=1∑Nc ∂t∂NNh−Δht 2
引入贝叶斯推断可以参数 S 0 S_0 S0 和 n n n 更靠,贝叶斯推断表示为: 1 N p ∑ j = 1 N p 1 σ i 2 ( λ i − μ i ) 2 \frac{1}{N_p} \sum_{j=1}^{N_p} \frac{1}{\sigma_i^2} (\lambda_i - \mu_i)^2 Np1∑j=1Npσi21(λi−μi)2
其中, λ i \lambda_i λi为待估计参数; N p N_p Np为参数数量; μ i \mu_i μi参数的均值; σ i 2 {\sigma_i^2} σi2为参数的方差。
架构A、B、C的比较以及适用场景
架构 | 对输入参数的依赖车程度 | 物理可解释性 | 适用场景 |
---|---|---|---|
A | 高 | 高 | 密集监测场景 |
B | 低 | 低 | 监测站稀疏的实际场景 |
C | 中 | 最高 | 需平衡数据与物理定律的场景 |
实验
-
PINNs用于河道水流建模的初步实验结果
在模拟环境下,以圣维南方程配置构建的系统中进行实验,目的是在评估PINNs预测河道水流的有效性。实验分两个阶段,第一阶段假设PDE参数和水位函数已知,验证PINNs的数据同化能力;第二阶段聚焦于识别定义PDE的向量参数,以描述水流动力学并捕捉河道内在特征。
通过数值解圣维南方程得到训练数据和配置点集,采用如架构A进行实验,结果表明PINN方法在系统识别方面,使用相对少的数据点,在所有实验中达到相当的精度和强大的数据同化能力,验证的均方误差在0.00648% - 0.0466%之间。
-
不同架构下的建模结果
架构A
在将 S 0 S_0 S0和 n n n作为优化变量加入损失函数后,经过一定训练轮次,架构A在所有实验中的预测误差(MSE)低于0.305%,最佳情况MSE为0.0263%。
基于PINNs发现的摩擦斜率和曼宁系数近似于圣维南方程中的实际参数,表明PINNs通过利用微分方程模型知识实现有效正则化。尽管没有理论保证神经网络模型和参数发现的联合学习收敛到全局最优,但在一定条件下可达到较好预测精度。
架构B
为解决数据点缺乏问题提出架构B,其输入变量仅包含距离、时间和河流水位,输出除水流率外还尝试学习水位函数用于自动微分计算物理正则化中的偏导数。
实验结果显示架构B发现真实PDE参数的能力不如架构A,但能较好地近似系统行为,MSE验证指数较低。
架构C
为改进参数识别提出架构C,采用新结构并受益于新的损失函数,引入贝叶斯推理到训练过程。
架构C添加 Δ h t Δh_t Δht作为输入变量,新的损失函数包含对参数偏离均值的惩罚项和对输出自动微分与数值导数差异的惩罚项。
实验结果表明,架构C在系统行为的泛化方面,MSE验证指数在0.0762% - 0.298%之间,相比架构B有所改进,在参数估计方面也有显著提升,能以较好的初始先验值逼近真实参数并保持物理特性。对比固定方差向量的情况,虽然参数有显著改进,但会导致系统识别能力的损失。
-
伊塔雅伊米林河中的实验结果
以伊塔雅伊河的伊塔雅伊米林河河段为研究对象,该区域有水位和流量测量数据,以及政府提供的地理研究数据。
利用2020年1月10 - 14日一次洪水事件的960个样本数据训练PINN模型,采用架构C并加入贝叶斯推理正则化的实验结果显示,架构为八层隐藏层、每层30个神经元、80000个配置点时,数据集同化效果最佳(MSE = 4.126×10⁻³),发现的床坡和曼宁系数参数,其中曼宁系数收敛到接近文献中的值,床坡参数收敛到区域研究中的极限值内。
代码如下:
# 导入必要的库
import torch # 用于张量计算和神经网络搭建
import torch.nn as nn # 提供神经网络层和激活函数
import numpy as np # 用于数据转换和绘图
import matplotlib.pyplot as plt # 用于可视化训练结果
from time import time # 用于测量训练时间
from pytorch_lbfgs import LBFGS # 导入支持GPU的L-BFGS优化器# 设置随机种子,确保结果可重复
torch.manual_seed(42)# 检查并设置计算设备,确保使用GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
if not torch.cuda.is_available():raise RuntimeError("GPU not available. This code requires CUDA support.")
print(f"Using device: {device} ({torch.cuda.get_device_name(0)})")# 定义Saint-Venant方程
def saint_venant_equations(h, Q, x, t, S0, n, g=9.81, eps=1e-6):"""计算Saint-Venant方程的残差,用于物理约束"""width = 2.0 # 矩形横截面宽度2mA = h * width + eps # 横截面积,添加偏移避免除零P_w = 2 * h + width + eps # 湿周长,添加偏移R = A / P_w # 水力半径# 自动微分计算偏导数h_t = torch.autograd.grad(h.sum(), t, create_graph=True) # 计算 ∂h/∂th_t = h_t[0] if h_t is not None else torch.zeros_like(h) # 若梯度为空,返回零张量h_x = torch.autograd.grad(h.sum(), x, create_graph=True) # 计算 ∂h/∂xh_x = h_x[0] if h_x is not None else torch.zeros_like(h) # 若梯度为空,返回零张量Q_x = torch.autograd.grad(Q.sum(), x, create_graph=True) # 计算 ∂Q/∂xQ_x = Q_x[0] if Q_x is not None else torch.zeros_like(Q) # 若梯度为空,返回零张量Q_t = torch.autograd.grad(Q.sum(), t, create_graph=True) # 计算 ∂Q/∂tQ_t = Q_t[0] if Q_t is not None else torch.zeros_like(Q) # 若梯度为空,返回零张量Q2_A = Q ** 2 / (A + eps) # 计算 Q^2/A,添加偏移避免除零Q2_A_x = torch.autograd.grad(Q2_A.sum(), x, create_graph=True) # 计算 ∂(Q^2/A)/∂xQ2_A_x = Q2_A_x[0] if Q2_A_x is not None else torch.zeros_like(Q) # 若梯度为空,返回零张量S_f = (n ** 2 * Q * torch.abs(Q)) / (A ** 2 * R ** (4 / 3) + eps) # 摩擦坡度,添加偏移f1 = (width * h_t) + Q_x # 质量守恒方程f2 = Q_t + Q2_A_x + g * A * (h_x + S_f - S0) # 动量守恒方程return f1, f2 # 返回残差# 数据生成函数
def generate_data(N_u=1200, N_c=150000, N_val=100):"""生成训练数据、配准点和验证点,模拟2km河道洪水波"""t = torch.linspace(0, 12000, N_u // 2, device=device, dtype=torch.float32).reshape(-1, 1) # 生成时间序列x_train = torch.cat([torch.zeros_like(t), 2000 * torch.ones_like(t)], dim=0) # 设置x=0m和x=2000mt_train = torch.cat([t, t], dim=0) # 拼接完整时间序列h_train = torch.zeros_like(t_train) # 初始化水深数组mask1 = t_train <= 6000 # 上升阶段mask2 = (t_train > 6000) & (t_train <= 9000) # 下降阶段mask3 = t_train > 9000 # 平稳阶段h_train[mask1] = (1.000735) ** (t_train[mask1] / 10) * 0.4 # 上升阶段水深h_ta = (1.000735) ** (6000 / 10) * 0.4 # t=6000s参考值h_train[mask2] = (0.9985) ** ((t_train[mask2] - 6000) / 10) * h_ta # 下降阶段水深h_train[mask3] = 0.4 # 平稳阶段水深A0 = h_train * 2.0 + 1e-6 # 初始横截面积P0 = 2 * h_train + 2.0 + 1e-6 # 初始湿周长Q_train = ((0.0025) ** 0.5 / 0.02) * (A0 ** (5 / 3)) / (P0 ** (2 / 3)) # 稳态流量x_c = torch.rand(N_c, 1, device=device, dtype=torch.float32) * 2000 # 配准点空间t_c = torch.rand(N_c, 1, device=device, dtype=torch.float32) * 12000 # 配准点时间x_val = torch.tensor([500, 1000, 1500], device=device, dtype=torch.float32).repeat(N_val).reshape(-1, 1) # 验证点位置t_val = torch.linspace(0, 12000, N_val, device=device, dtype=torch.float32).repeat(3).reshape(-1, 1) # 验证点时间return (x_train.requires_grad_(True), t_train.requires_grad_(True), h_train, Q_train), \(x_c.requires_grad_(True), t_c.requires_grad_(True)), \(x_val.requires_grad_(True), t_val.requires_grad_(True))# 定义PINN模型(架构C)
class PINN_C(nn.Module):def __init__(self, hidden_layers=8, neurons=20):"""定义架构C的神经网络:输入[x, t, Δh_t],输出[h, Q]"""super(PINN_C, self).__init__()layers = [nn.Linear(3, neurons), nn.Tanh()] # 输入层:3维 -> neurons,使用tanh激活for _ in range(hidden_layers - 1):layers += [nn.Linear(neurons, neurons), nn.Tanh()] # 添加隐层layers += [nn.Linear(neurons, 2)] # 输出层:neurons -> 2 (h, Q)self.net = nn.Sequential(*layers).to(device) # 构建网络并移到GPUself.S0 = nn.Parameter(torch.tensor([0.002], device=device, dtype=torch.float32)) # 初始化床坡self.n = nn.Parameter(torch.tensor([0.03], device=device, dtype=torch.float32)) # 初始化曼宁系数def forward(self, x, t, dh_dt):"""前向传播,输入[x, t, Δh_t],输出[h, Q]"""inputs = torch.cat([x, t, dh_dt], dim=1) # 拼接输入向量out = self.net(inputs) # 通过神经网络h = torch.relu(out[:, 0:1]) + 0.01 # 输出水深,确保非负并加偏移Q = torch.relu(out[:, 1:2]) + 0.01 # 输出流量,确保非负并加偏移return h, Q# 损失函数
def loss_fn_C(model, x_u, t_u, h_u, Q_u, x_c, t_c, mu, sigma):"""计算损失函数,包括数据项、物理项、正则化项和导数惩罚项"""dh_dt_u = torch.zeros_like(h_u) # 初始化训练数据的 Δh_tdh_dt_u[1:] = (h_u[1:] - h_u[:-1]) / 10 # 计算数值导数dh_dt_u[0] = dh_dt_u[1] # 边界填充h_pred, Q_pred = model(x_u, t_u, dh_dt_u) # 预测训练点的 h 和 Qmse_u = torch.mean((h_pred - h_u) ** 2 + (Q_pred - Q_u) ** 2) # 计算数据误差dh_dt_c = torch.zeros_like(x_c) # 初始化配准点的 Δh_th_c, Q_c = model(x_c, t_c, dh_dt_c) # 预测配准点的 h 和 Qf1, f2 = saint_venant_equations(h_c, Q_c, x_c, t_c, model.S0, model.n) # 计算PDE残差mse_p = torch.mean(f1 ** 2) + torch.mean(f2 ** 2) # 计算物理误差reg = (1 / (sigma[0] ** 2 + 1e-6)) * (model.S0 - mu[0]) ** 2 + \(1 / (sigma[1] ** 2 + 1e-6)) * (model.n - mu[1]) ** 2 # 参数正则化项h_t = torch.autograd.grad(h_c.sum(), t_c, create_graph=True) # 计算配准点 ∂h/∂th_t = h_t[0] if h_t is not None else torch.zeros_like(h_c) # 若梯度为空,返回零张量penalty = torch.mean((h_t - dh_dt_c) ** 2) # 计算导数惩罚项return mse_u + mse_p + reg + penalty # 返回总损失# 验证MSE计算
def compute_validation_mse(model, x_val, t_val, h_true, Q_true):"""计算验证点的MSE"""dh_dt_val = torch.zeros_like(h_true) # 初始化验证点 Δh_tdh_dt_val[1:] = (h_true[1:] - h_true[:-1]) / 10 # 计算数值导数dh_dt_val[0] = dh_dt_val[1] # 边界填充with torch.no_grad(): # 无梯度计算h_pred, Q_pred = model(x_val, t_val, dh_dt_val) # 预测验证点 h 和 Qmse_val = torch.mean((h_pred - h_true) ** 2 + (Q_pred - Q_true) ** 2) # 计算MSEreturn mse_val.item() # 返回标量值# 训练函数
def train_model(model, x_u, t_u, h_u, Q_u, x_c, t_c, x_val, t_val, h_val, Q_val):"""训练模型:2000次ADAM + 5000次L-BFGS,全部在GPU上"""optimizer_adam = torch.optim.Adam(model.parameters(), lr=0.0001) # 初始化ADAM优化器optimizer_lbfgs = LBFGS(model.parameters(), lr=0.1, max_iter=20) # 初始化GPU支持的L-BFGSmu = torch.tensor([0.002, 0.03], device=device, dtype=torch.float32) # 初始化先验均值sigma = torch.tensor([4.17e-4, 5e-3], device=device, dtype=torch.float32) # 初始化先验方差S0_history, n_history, losses, val_mses = [], [], [], [] # 初始化历史记录列表print("Training with ADAM on GPU (2000 epochs)...")start_time = time() # 记录ADAM阶段开始时间for epoch in range(2000): # 2000次ADAM迭代optimizer_adam.zero_grad() # 清零梯度loss = loss_fn_C(model, x_u, t_u, h_u, Q_u, x_c, t_c, mu, sigma) # 计算总损失if torch.isnan(loss): # 检查是否出现NaNprint(f"NaN detected at epoch {epoch}")breakloss.backward() # 反向传播torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0) # 梯度裁剪optimizer_adam.step() # 更新参数S0_history.append(model.S0.item()) # 记录床坡n_history.append(model.n.item()) # 记录曼宁系数losses.append(loss.item()) # 记录损失mu[0] = torch.tensor(S0_history, device=device, dtype=torch.float32).mean() # 更新S0均值mu[1] = torch.tensor(n_history, device=device, dtype=torch.float32).mean() # 更新n均值sigma[0] = max((max(S0_history) - min(S0_history)) / 6, 1e-6) # 更新S0方差sigma[1] = max((max(n_history) - min(n_history)) / 6, 1e-6) # 更新n方差val_mse = compute_validation_mse(model, x_val, t_val, h_val, Q_val) # 计算验证MSEval_mses.append(val_mse) # 记录验证MSEif epoch % 200 == 0: # 每200次打印结果print(f"Epoch {epoch}, Loss: {loss.item():.6f}, Val MSE: {val_mse:.6f}, "f"S0: {model.S0.item():.6f}, n: {model.n.item():.6f}")print(f"ADAM Training Time: {time() - start_time:.2f}s") # 打印ADAM阶段时间print("Training with L-BFGS on GPU (5000 epochs)...")start_time = time() # 记录L-BFGS阶段开始时间def closure(): # 定义L-BFGS闭包函数optimizer_lbfgs.zero_grad() # 清零梯度loss = loss_fn_C(model, x_u, t_u, h_u, Q_u, x_c, t_c, mu, sigma) # 计算总损失if torch.isnan(loss): # 检查是否出现NaNprint("NaN detected in L-BFGS")return lossloss.backward() # 反向传播return lossfor epoch in range(5000): # 5000次L-BFGS迭代loss = optimizer_lbfgs.step(closure) # 执行一步优化if torch.isnan(loss): # 检查是否出现NaNprint(f"NaN detected at epoch {epoch + 2000}")breakS0_history.append(model.S0.item()) # 记录床坡n_history.append(model.n.item()) # 记录曼宁系数losses.append(loss.item()) # 记录损失mu[0] = torch.tensor(S0_history, device=device, dtype=torch.float32).mean() # 更新S0均值mu[1] = torch.tensor(n_history, device=device, dtype=torch.float32).mean() # 更新n均值sigma[0] = max((max(S0_history) - min(S0_history)) / 6, 1e-6) # 更新S0方差sigma[1] = max((max(n_history) - min(n_history)) / 6, 1e-6) # 更新n方差val_mse = compute_validation_mse(model, x_val, t_val, h_val, Q_val) # 计算验证MSEval_mses.append(val_mse) # 记录验证MSEif (epoch + 2000) % 500 == 0: # 每500次打印结果print(f"Epoch {epoch + 2000}, Loss: {loss.item():.6f}, Val MSE: {val_mse:.6f}, "f"S0: {model.S0.item():.6f}, n: {model.n.item():.6f}")print(f"L-BFGS Training Time: {time() - start_time:.2f}s") # 打印L-BFGS阶段时间return losses, val_mses, S0_history, n_history # 返回训练历史# 可视化结果
def plot_results(model, x_u, t_u, h_u, Q_u, x_val, t_val, losses, val_mses, S0_history, n_history):"""绘制训练结果"""x_u, t_u, h_u = x_u.to('cpu'), t_u.to('cpu'), h_u.to('cpu') # 数据移到CPU用于绘图dh_dt_u = torch.zeros_like(h_u) # 初始化 Δh_tdh_dt_u[1:] = (h_u[1:] - h_u[:-1]) / 10 # 计算数值导数dh_dt_u[0] = dh_dt_u[1] # 边界填充with torch.no_grad(): # 无梯度计算model = model.to('cpu') # 模型移到CPUh_pred, Q_pred = model(x_u, t_u, dh_dt_u) # 预测 h 和 Qh_u, Q_u = h_u.numpy(), Q_u.numpy() # 转换为NumPy数组h_pred, Q_pred = h_pred.numpy(), Q_pred.numpy() # 同上t_u = t_u.numpy() # 同上plt.figure(figsize=(15, 10)) # 设置图形大小plt.subplot(2, 2, 1) # 子图1:损失曲线plt.plot(losses, label='Loss') # 绘制总损失plt.plot(val_mses, label='Validation MSE') # 绘制验证MSEplt.xlabel('Epoch') # x轴标签plt.ylabel('Value') # y轴标签plt.yscale('log') # 对数刻度plt.legend() # 添加图例plt.subplot(2, 2, 2) # 子图2:流量预测plt.plot(t_u[:len(t_u) // 2], Q_u[:len(t_u) // 2], label='True Q (x=0)') # 真实流量plt.plot(t_u[:len(t_u) // 2], Q_pred[:len(t_u) // 2], '--', label='Pred Q (x=0)') # 预测流量plt.xlabel('Time (s)') # x轴标签plt.ylabel('Flow Rate (m^3/s)') # y轴标签plt.legend() # 添加图例plt.subplot(2, 2, 3) # 子图3:水深预测plt.plot(t_u[:len(t_u) // 2], h_u[:len(t_u) // 2], label='True h (x=0)') # 真实水深plt.plot(t_u[:len(t_u) // 2], h_pred[:len(t_u) // 2], '--', label='Pred h (x=0)') # 预测水深plt.xlabel('Time (s)') # x轴标签plt.ylabel('Water Depth (m)') # y轴标签plt.legend() # 添加图例plt.subplot(2, 2, 4) # 子图4:参数估计plt.plot(S0_history, label='S0') # 绘制床坡估计plt.plot(n_history, label='n') # 绘制曼宁系数估计plt.axhline(y=0.0025, color='r', linestyle='--', label='True S0') # 真实床坡plt.axhline(y=0.02, color='g', linestyle='--', label='True n') # 真实曼宁系数plt.xlabel('Epoch') # x轴标签plt.ylabel('Parameter Value') # y轴标签plt.legend() # 添加图例plt.tight_layout() # 调整布局plt.show() # 显示图形# 主程序
if __name__ == "__main__":(x_u, t_u, h_u, Q_u), (x_c, t_c), (x_val, t_val) = generate_data() # 生成数据h_val = h_u[:300] # 设置验证集水深Q_val = Q_u[:300] # 设置验证集流量model = PINN_C().to(device) # 初始化模型并移到GPUlosses, val_mses, S0_history, n_history = train_model(model, x_u, t_u, h_u, Q_u, x_c, t_c, x_val, t_val, h_val,Q_val) # 训练模型plot_results(model, x_u, t_u, h_u, Q_u, x_val, t_val, losses, val_mses, S0_history, n_history) # 可视化结果print(f"Final S0: {model.S0.item():.6f}, True S0: 0.0025") # 打印最终床坡估计print(f"Final n: {model.n.item():.6f}, True n: 0.02") # 打印最终曼宁系数估计print(f"Final Validation MSE: {val_mses[-1]:.6f}") # 打印最终验证MSE
结论
本论文将PINNs作为河流水流率的替代水文模型,研究其在模拟环境中的性能。结果表明PINNs可同化数据并发现控制系统动力学的微分方程参数,能规避概念模型中参数估计的劣势和经验方法中数据缺乏的问题。且在不同条件下,架构A和架构C的PINNs模型分别有较好表现。
后续展望
作者认为未来可将PINNs应用于解决流域的实时系统。此外,进一步探索PINNs在不同真实世界场景中的应用和深入研究物理和数据学习平衡任务的理论。之后可以优化架构C中参数方差的值以提高系统预测能力。
相关文章:
2025.2.23机器学习笔记:PINN文献阅读
2025.2.23周报 一、文献阅读题目信息摘要Abstract创新点网络架构架构A架构B架构C 实验结论后续展望 一、文献阅读 题目信息 题目: Physics-Informed Neural Networks for Modeling Water Flows in a River Channel期刊: IEEE TRANSACTIONS ON ARTIFICI…...
关于Postman自动获取token
在使用postman测试联调接口时,可能每个接口都需要使用此接口生成的令牌做Authorization的Bearer Token验证,最直接的办法可能会是一步一步的点击,如下图: 在Authorization中去选择Bearer Token,然后将获取到的token粘贴…...
Android KMP初探
Android KMP初探 前言: 最近线上听了Kotlin官网举行的KMP会议,感觉听神奇的,于是就把官方demo下载下来尝试了一下,下载插件和所需要的依赖都用了很久,但是发现里面的代码很少,于是尝试自己手写了一下&…...
ncDLRES:一种基于动态LSTM和ResNet的非编码RNA家族预测新方法
现有的计算方法主要分为两类:第一类是通过学习序列或二级结构的特征来预测ncRNAs家族,另一类是通过同源序列之间的比对来预测ncRNAs家族。在第一类中,一些方法通过学习预测的二级结构特征来预测ncRNAs家族。二级结构预测的不准确性可能会导致…...
前端项目打包过滤指定icon文件
1.需求背景 项目中有部分功能需要vip权限才可以使用,所有部分筛选、按钮 等有vip的icon提示 如下图 此项目衍生出一个特殊版本,此版本无需登录且拥有最高权限,所以产品要求去除项目中的所有vip相关的提示。 2.解决思路 (1&am…...
蓝桥杯 Java B 组之最短路径算法(Dijkstra、Floyd-Warshall)
Day 2:最短路径算法(Dijkstra、Floyd-Warshall) 📖 一、最短路径算法简介 最短路径问题是图论中的经典问题,主要用于求解 单源最短路径 或 多源最短路径。在实际应用中,最短路径广泛应用于 导航系统、网络…...
科普:HTTP端口80和HTTPS端口443
你会发现,有的网址不带端口号,怎么回事? HTTP协议默认端口:HTTP协议的默认端口是80。当用户在浏览器中输入一个没有指定端口的以http://开头的网址时,浏览器会自动使用80端口与服务器建立连接,进行超文本数…...
如何安装vm和centos
安装 VMware Workstation Pro 步骤 1:下载 VMware Workstation Pro 访问 VMware 官方网站(Desktop Hypervisor Solutions | VMware ),根据你的操作系统选择合适的版本进行下载。 步骤 2:运行安装程序 找到下载的安装…...
鸿蒙-验证码输入框的几种实现方式-上
文章目录 效果图、优缺点多TextInput多 TextCanvas 绘制 多个 TextInput 拼接放置四个输入框焦点移动输入时向后移动输入完成回调删除时向前移动 防止点击总结 最近在做应用鸿蒙化,说白了就是把原来Android、iOS的代码重新用ArkTS写一遍,我负责基础建设和…...
Vi 编辑器基本使用指南
一、Vi 编辑器的启动与退出 启动 Vi 编辑器 在终端中,输入vi加上要编辑的文件名,如vi example.txt,如果example.txt存在,Vi 编辑器会打开该文件;若不存在,则会创建一个新的空文件并打开。如果只输入vi&am…...
centos 7 安装python3 及pycharm远程连接方法
安装openssl 使用pip3安装 virtualenv的时候会提示WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available. 这是因为缺少openssl 2.0以上版本 解决办法: 一、先确认版本 openssl version 二、安…...
PostgreSQL 使用pgAdmin 4 数据库还原sql文件报错问题分析
sql执行报错问题: C:\Program Files\PostgreSQL\17\bin\pg_restore.exe --host "localhost" --port "5433" --username "postgres" --no-password --dbname "ry_postgresql-final" --verbose "E:\\PostgreSQLProject\\Ruoyi-Po…...
gihub上适合练手的Python项目
GitHub 上有许多适合练手的 Python 项目,涵盖了从初学者到中级开发者的不同难度级别。以下是一些推荐的项目类型和具体示例,帮助你提升 Python 编程技能: 1. 基础项目 适合初学者,帮助掌握 Python 基础语法和常用库。 示例项目&…...
3D Web轻量化引擎HOOPS Communicator如何赋能航空航天制造?
在当今航空航天制造领域,精确度、效率和协作是推动行业发展的关键要素。随着数字化技术的飞速发展,3D Web可视化开发包HOOPS Communicator 为航空航天制造带来了革命性的变化。它凭借强大的功能和灵活的应用,助力企业在设计、生产、培训等各个…...
AWQ和GPTQ量化的区别
一、前言 本地化部署deepseek时发现,如果是量化版的deepseek,会节约很多的内容,然后一般有两种量化技术,那么这两种量化技术有什么区别呢? 二、量化技术对比 在模型量化领域,AWQ 和 GPTQ 是两种不同的量…...
通过恒定带宽服务器调度改进时间敏感网络(TSN)流量整形
论文标题 英文标题:Improving TSN Traffic Shaping with Constant Bandwidth Server Scheduling 中文标题:通过恒定带宽服务器调度改进时间敏感网络(TSN)流量整形 作者信息 作者:Benjamin van Seggelen 指导教师&am…...
气象干旱触发水文(农业)干旱的概率及其触发阈值的动态变化-贝叶斯copula模型
前言 在干旱研究中,一个关键的科学问题是:在某一地区发生不同等级的气象干旱时,气象干旱会以何种概率引发不同等级的水文干旱、农业干旱和地下水干旱?换句话说,气象干旱的不同程度会分别引发其他类型干旱的哪种等级&a…...
自定义Spring Boot Starter(官网文档解读)
摘要 本文将详细介绍自定义 Spring Boot Starter 的完整过程。要构建自定义 Starter,首先需掌握 Spring Boot 中 Auto-configuration 以及相关注解的工作原理,同时了解 Spring Boot 提供的一系列条件注解。在具备这些知识基础后,再按照特定步…...
开发 picgo-plugin-huawei 插件,解决华为云社区外链限制问题
开发 picgo-plugin-huawei 插件,解决华为云社区外链限制问题 在技术博客平台中,外链的使用常常受到限制,这给我们的写作和内容展示带来了一定的不便。为了应对这一问题,我开发了 picgo-plugin-huawei 插件,它能够有效…...
最长回文子串
标题 1.1 问题描述 给你一个字符串 s,找到 s 中最长的回文子串。 1.2 示例 1.2.1 示例1 输入:s “babad” 输出:“bab” 解释:“aba” 同样是符合题意的答案。 1.2.2 示例2 输入:s “cbbd” 输出:“bb…...
JavaSE学习笔记26-集合(Collection)
集合 Java 中的集合(Collection)是 Java 标准库中非常重要的一部分,用于存储和操作一组对象。Java 集合框架(Java Collections Framework)提供了一套丰富的接口和类,用于处理各种数据结构,如列…...
开源神器KRR:用数据驱动K8s资源优化
引言:云原生时代的资源管理之痛 在Kubernetes集群中,过度配置导致资源浪费与配置不足引发稳定性风险的矛盾始终存在。CNCF调研显示,企业平均有35%的云资源处于闲置状态。本文将揭秘开源神器KRR(Kubernetes Resource Recommender),通过数据驱动方式实现精准资源配置,实测…...
微信小程序:多菜单栏设计效果
一、实现效果 二、代码 wxml 编辑前端界面,步骤 菜单逻辑: 逐步取出数组中的项,首先取出顶部菜单项,然后选中后取出选中的底部数据(左侧菜单+右侧内容),然后点击左侧菜单取出选中的左侧菜单对应的右侧内容 ①这里我的数据是全部封装到一个数组对象的,首先我的循环…...
网络安全-js安全知识点与XSS常用payloads
简介 JavaScript 是一种轻量级的编程语言,定义了HTML的行为。它与Java的关系类似周杰和周杰伦的关系(即没有关系)。 用法 HTML 中的脚本必须位于 <script> 与 </script> 标签之间。 脚本可被放置在 HTML 页面的 <body>…...
无人机实战系列(二)本地摄像头 + Depth-Anything V2
这篇文章介绍了如何在本地运行 Depth-Anything V2,因为我使用的无人机是Tello,其本身仅提供了一个单目视觉相机,在众多单目视觉转 Depth 的方案中我选择了 Depth-Anything V2,这个库的强大在于其基于深度学习模型将单目视觉以较低…...
[杂学笔记]工厂模式、多态、内存空间区域划分、cp指令破坏软连接问题、UDP如何实现可靠传输、滑动窗口的原理、进程与线程、线程之间的通信
目录 1.工厂模式 2.多态 3.内存空间区域划分 4.cp指令破坏软连接问题 5.UDP实现可靠传输 6.滑动窗口的原理 7.进程与线程 8.线程之间的通信 1.工厂模式 工厂模式是一种创建对象的设计模式。它提供了一种创建对象的方式,将对象的创建和使用分离,通…...
【IEEE出版,往届会后3个月EI检索 | 西华大学主办 | 中英文期刊、SCI期刊推荐】第四届能源、电力与电气国际学术会议(ICEPET 2025)
第四届能源、电力与电气国际学术会议(ICEPET 2025)由西华大学主办,西华大学能源与动力工程学院、西华大学电气与电子信息学院、西华大学航空航天学院、流体及动力机械教育部重点实验室、流体机械及工程四川省重点实验室、四川省水电能源动力装…...
【AI+智造】DeepSeek价值重构:当采购与物控遇上数字化转型的化学反应
作者:Odoo技术开发/资深信息化负责人 日期:2025年2月24日 引言:从事企业信息化工作16年,我见证过无数企业从手工台账到ERP系统的跨越。但真正让采购和物控部门脱胎换骨的,是融合了Deepseek AI的Odoo数字化解决方案——…...
1.适配器模式
概述 适配器模式:将一个类的接口转换成客户希望的另一个接口,使得原本不兼容的类可以一起工作。 适配器模式在业务场景中非常有用,尤其是在系统集成、接口兼容性处理以及代码复用等场景。以下是一个实际的业务场景示例: 业务场景…...
选择排序(详解)c++
选择排序(Selection Sort)是⼀种特别直观的排序算法。每次找出未排序序列中最⼩的元素,然后放进有序序列的后⾯ 算法思想: 每次找出未排序序列中最小的元素,然后放进有序序列的后面 在数组中完成选择排序 落实到代码的时候就两步:找最小交换 …...
[java基础-JVM篇]1_JVM自动内存管理
JVM内存管理涉及但不限于类加载、对象分配、垃圾回收等,本篇主要记录运行时数据区域与对象相关内容。 内容主要来源《深入理解Java虚拟机:JVM高级特性与最佳实践》与官方文档,理解与表述错漏之处恳请各位大佬指正。 目录 运行时数据区域 栈 栈…...
python-leetcode 42.验证二叉搜索树
题目: 给定二叉树的根节点root,判断是否是一个有效二叉搜索树 有效二叉搜索树: 1.节点的左子树只包含小于当前节点的树 2.节点的右子树只包含大于当前节点的树 3.所有左子树和右子树自身必须也是二叉搜索树 方法一:递归 如果该二叉树的…...
Unity Shader 学习13:屏幕后处理 - 使用高斯模糊的Bloom辉光效果
目录 一、基本的后处理流程 - 以将画面转化为灰度图为例 1. C#调用shader 2. Shader实现效果 二、Bloom辉光效果 1. 主要变量 2. Shader效果 (1)提取较亮区域 - pass1 (2)高斯模糊 - pass2&3 (3ÿ…...
【Bluedroid】AVRCP 连接源码分析(三)
接着上一篇【Bluedroid】AVRCP 连接源码分析(一)-CSDN博客,继续AVRCP连接的源码分析。 AVRC_OpenBrowse /packages/modules/Bluetooth/system/stack/avrc/avrc_api.cc /******************************************************************************** Function …...
图数据库Neo4j面试内容整理-约束(Constraint)
约束(Constraint) 是数据库中用于确保数据一致性和完整性的一种机制。它限制了数据的某些方面,确保特定条件得到满足。在 Neo4j 中,约束主要用于确保图数据的一致性,防止插入不符合规则的数据。约束通常与索引一起使用,但它们的功能和目的有所不同。 1. Neo4j 中的约束类…...
QUdpSocket的readyRead信号只触发一次
问题 QUdpSocket的readyRead信号只触发一次。 原因 on_readyRead槽函数里必须读出现有数据后,才能触发新的事件。 解决办法 在on_readyRead槽函数里取出数据。 void MainWindow::on_readyRead() {qDebug() << "on_readyRead in";while (m_udp…...
使用Windbg调试目标进程排查C++软件异常的一般步骤与要点分享
目录 1、概述 2、将Windbg附加到已经启动起来的目标进程上,或者用Windbg启动目标程序 2.1、将Windbg附加到已经启动起来的目标进程上 2.2、用Windbg启动目标程序 2.3、Windbg关联到目标进程上会中断下来,输入g命令将该中断跳过去 3、分析实例说明 …...
深度解析:大模型在多显卡服务器下的通信机制与分布式训练——以DeepSeek、Ollama和vLLM为例
一、引言:大模型与多显卡的必然结合 随着大模型参数规模突破千亿级(如GPT-4、DeepSeek),单显卡的显存容量与算力已无法满足需求。多显卡并行计算成为训练与推理的核心技术,其核心挑战在于高效通信与负载均衡。本文以国…...
爬虫基础入门之爬取豆瓣电影Top250-Re正则的使用
网址:豆瓣电影 Top 250 本案例所需要的模块 requests (用于发送HTTP请求)re (用于字符串匹配和操作) 确定需要爬取的数据 : 电影的名称电影的年份电影的评分电影评论人数 一. 发送请求 模拟浏览器向服务器发送请求 准备工作 -分析页面: F12 or 右击点击检查 查看…...
【R安装包报错】在conda环境下用R语言命令安装R包报错
报错如下: gnu/include/c/11.2.0/ctime:80:11: error: ‘timespec_get’ has not been declared in ‘::’ 80 | using ::timespec_get; | ^~~~~~~~~~~~ 修改 报错原因:如果使用的是conda安装的g,可能与系统库不兼容。尝试 切换到系统默认编…...
基于STM32单片机设计的宠物喂食监控系统
1. 项目开发背景 随着宠物数量的增加,尤其是人们对宠物的养护需求日益增多,传统的人工喂养和管理方式难以满足现代养宠生活的需求。人们越来越希望通过智能化手段提高宠物养护的质量和效率,特别是对于宠物喂食、饮水、温湿度控制等方面的智能…...
Minio分布式多节点多驱动器集群部署
Minio分布式多节点多驱动器集群部署 Minio分布式多节点多驱动器集群部署节点规划先决条件开放防火墙端口设置主机名更新域名映射文件时间同步存储要求内存要求 增加虚拟机磁盘(所有机器都要执行)部署分布式 MinIO测试上传与预览测试高可用MinIO 配置限制模拟单节点磁盘故障模拟…...
Web前端开发——HTML基础
本系列博客声明,根据本人所学书籍和网上的一些资料共同磨合,写下web前端系列的博客 HTML基础 一、HTML基本概述[^1]二、HTML大体认知1.HTML基本结构2.HTML 语法格式 三、THML常用标记[^2]1.文本标记(1)标题(2…...
《计算机视觉》——图像拼接
图像拼接 图像拼接是将多幅有重叠区域的图像合并成一幅全景或更大视角图像的技术,以下为你详细介绍: 原理:图像拼接的核心原理是基于图像之间的特征匹配。首先,从每幅图像中提取独特的特征点,如角点、边缘点等&#x…...
zookeeper从入门到精通
一、入门基础 1.1 什么是 ZooKeeper ZooKeeper 是一个开源的分布式协调服务,由雅虎创建,后成为 Apache 的顶级项目。它为分布式应用提供了高效、可靠的协调服务,例如统一命名服务、配置管理、分布式锁、集群管理等。ZooKeeper 的数据模型类…...
2.2 添加注释
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 注释是为了方便理解代码含义而添加的简短的解释性说明。在编译时,编辑器不会将注释加入最终生成的文件中,不…...
具有快慢思考的语言调节机器人操作
24年1月来自华东师范大学、美的集团和上海大学的论文“Language-Conditioned Robotic Manipulation with Fast and Slow Thinking”。 语言调节机器人操作,旨在将自然语言指令转化为可执行动作,从简单的“拾取和放置”到需要意图识别和视觉推理的任务。…...
美颜相机1.0
项目开发步骤 1 界面开发 美颜相机界面构成: 标题 尺寸 关闭方式 位置 可视化 2 创建主函数调用界面方法 3 添加两个面板 一个是按钮面板一个是图片面板 用JPanel 4 添加按钮到按钮面吧【注意:此时要用初始化按钮面板的方法initBtnPanel 并且将按钮添…...
Css3重点知识讲解
选择器 优先级: id 选择器 > 类选择器 > 标签选择器 类选择器: .myClass {color: blue; }id 选择器(全局唯一): #myId {color: green; }标签选择器: p {color: red; }层次选择器: /…...
[Web 安全] Web 安全攻防 - 学习手册
关联专栏:[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01:Web 安全攻防 —— 信息收集篇 Web 信息收集 — 手动收集域名信息 Web 信息收集 — 手动收集 IP 信息 Web 信息收集 — 端口服务信息收集 Web 信息收集 — 自动化信息收集 — ShuiZe 水泽 We…...