2024.8.18周报

摘要

本周利用阳朔水站的数据对1D浅水方程进行了求解,通过将1D浅水方程的物理约束纳入到神经网络,将时空坐标x,t作为输入到神经网络中,得到预测解水深和流量的数据,然后利用真实的数据进行比较,计算损失。

ABSTRACT

This week, the data of Yangshuo water station was used to solve the 1D shallow water equation, and the physical constraints of the 1D shallow water equation were incorporated into the neural network, and the spatiotemporal coordinates x,t were used as inputs to the neural network to obtain the data that predicted the water depth and flow rate of the solution, and then the real data were used to compare and calculate the loss.

具体实现

一、数据处理

数据被从Excel文件加载、预处理(例如清除缺失值、转换日期时间格式、创建假设的空间坐标、标准化或归一化等),然后被分割为训练集和测试集。

import pandas as pd
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.model_selection import train_test_split

def preprocess_data(filepath):
    data = pd.read_excel(filepath)
    data.dropna(inplace=True)  # 删除缺失值
    data['DateTime'] = data['DateTime'].astype('int64') // 10**9

    # 假设空间坐标
    data['Space'] = range(len(data))

    # 特征和标签
    X = data[['Space', 'DateTime']]
    y = data[['WaterLevel', '流量']]

    # 数据标准化
    x_scaler = MinMaxScaler()
    y_scaler = StandardScaler()
    X_scaled = x_scaler.fit_transform(X)
    y_scaled = y_scaler.fit_transform(y)

    # 分割数据为训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(X_scaled, y_scaled, test_size=0.2, random_state=42)

    return X_train, X_test, y_train, y_test, x_scaler, y_scaler

二、model

import torch
import torch.nn as nn
import torch.autograd as autograd

class PINN(nn.Module):
    def __init__(self, gravity=9.81):
        super(PINN, self).__init__()
        self.gravity = gravity
        self.dense1 = nn.Linear(2, 50)  # 假设输入是位置和时间
        self.dense2 = nn.Linear(50, 50)
        self.dense3 = nn.Linear(50, 50)
        self.out = nn.Linear(50, 2)  # 输出水位h和速度u

        self.activation = nn.Tanh()

    def forward(self, inputs):
        x = self.activation(self.dense1(inputs))
        x = self.activation(self.dense2(x))
        x = self.activation(self.dense3(x))
        return self.out(x)

    def physics(self, inputs):
        inputs.requires_grad_(True)
        h_u = self(inputs)
        h = h_u[:, 0]
        u = h_u[:, 1]

        h_t = autograd.grad(h.sum(), inputs, create_graph=True)[0][:, 1]
        h_x = autograd.grad(h.sum(), inputs, create_graph=True)[0][:, 0]
        u_t = autograd.grad(u.sum(), inputs, create_graph=True)[0][:, 1]
        u_x = autograd.grad(u.sum(), inputs, create_graph=True)[0][:, 0]

        continuity = h_t + (h * u_x + u * h_x)
        momentum = (h * u).t() + autograd.grad((h * u**2 + 0.5 * self.gravity * h**2).sum(), inputs, create_graph=True)[0][:, 0]

        return continuity, momentum

    def loss(self, inputs, outputs, targets):
        prediction_loss = nn.MSELoss()(outputs, targets)
        continuity_res, momentum_res = self.physics(inputs)
        physics_loss = torch.mean(continuity_res**2 + momentum_res**2)

        total_loss = prediction_loss + physics_loss
        return total_loss

三、train

import torch
from torch.optim import Adam
from model import PINN
from data_preprocess import preprocess_data
from config import learning_rate, epochs, batch_size

def train_model(X_train, y_train):
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model = PINN().to(device)
    optimizer = Adam(model.parameters(), lr=learning_rate)

    model.train()
    for epoch in range(epochs):
        optimizer.zero_grad()
        inputs = torch.tensor(X_train).float().to(device)
        targets = torch.tensor(y_train).float().to(device)
        outputs = model(inputs)
        loss = model.loss(inputs, outputs, targets)
        loss.backward()
        optimizer.step()

        if epoch % 100 == 0:
            print(f"Epoch {epoch}, Loss: {loss.item()}")

    return model

if __name__ == "__main__":
    X_train, _, y_train, _, _, _ = preprocess_data('./阳朔水站流量流速数据.xlsx')
    trained_model = train_model(X_train, y_train)
    torch.save(trained_model.state_dict(), 'trained_pinn_model.pth')

训练结果:

2d7b9b943f064849b8d3770443862173.png

四、test

import torch
from model import PINN
from data_preprocess import preprocess_data

def test_model(model_path, X_test, y_test):
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model = PINN().to(device)
    model.load_state_dict(torch.load(model_path))
    # 保留模型在训练模式以保持梯度计算,或者确保模型中的物理损失计算适当处理
    model.train()

    # 确保输入启用梯度计算
    inputs = torch.tensor(X_test, requires_grad=True).float().to(device)
    targets = torch.tensor(y_test).float().to(device)

    predictions = model(inputs)
    test_loss = model.loss(inputs, predictions, targets)  # 这里计算包括物理损失在内的总损失
    print(f"Test Loss: {test_loss.item()}")

if __name__ == "__main__":
    _, X_test, _, y_test, _, _ = preprocess_data('./阳朔水站流量流速数据.xlsx')
    model_path = 'trained_pinn_model.pth'
    test_model(model_path, X_test, y_test)

测试结果:9b86bd5553e8468c8a8f0cf1daab7cb8.png                                                                  可视化结果:

80a703bb9bb4491c9d67885e6f29a9db.png

 

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值