You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch物理信息神经网络批量输出值一致问题求助

物理信息神经网络(PINN)输出批量样本值全相同问题排查

我用PyTorch实现了一个物理信息神经网络(PINN),输入是距离x和时间t,输出是h和q的预测值。现在遇到一个问题:神经网络对批量内的每个输入样本,输出的h和q值完全相同。

训练过程中,输出值会随迭代次数变化,损失值也在持续降低,说明训练循环本身是正常运行的。怀疑问题出在数据预处理或网络架构的编码上。

训练步骤0和1000的输出结果(值随迭代变化):
迭代0的输出
迭代1000的输出


神经网络架构定义

import torch.nn as nn

class FCN(nn.Module):
    def __init__(self, N_INPUT, N_OUTPUT, N_HIDDEN, N_LAYERS):
        super().__init__()
        activation = nn.Tanh
        self.fcs = nn.Sequential(
            nn.Linear(N_INPUT, N_HIDDEN),
            activation()
        )
        self.fch = nn.Sequential(*[
            nn.Sequential(
                nn.Linear(N_HIDDEN, N_HIDDEN),
                activation()
            ) for _ in range(N_LAYERS - 1)
        ])
        self.fce = nn.Linear(N_HIDDEN, N_OUTPUT)  # Output layer

    def forward(self, x, t):
        inputs = torch.cat([x, t], axis = 1)
        inputs = self.fcs(inputs)
        inputs = self.fch(inputs)
        outputs = self.fce(inputs)
        return outputs

pinn = FCN(2, 2, 9, 12)

输入定义

import torch

x_colloc = torch.linspace(0, 300, 500).view(-1,1).requires_grad_(True)
t_colloc = torch.linspace(0, 10, 500).view(-1,1).requires_grad_(True)

输入x范围是0到300,t范围是0到10,但每次迭代中,批量内所有样本的输出值均相同,如上述图表所示。

训练循环定义

for i in range (200000):
   optimiser.zero_grad()

   colloc_output = pinn(x_colloc, t_colloc)

   h_hat, q_hat = colloc_output[:,0], colloc_output[:,1]
   dq_dt = torch.autograd.grad(q_hat, t_colloc, 
   torch.ones_like(q_hat), create_graph=True)[0]
   dq_dx = torch.autograd.grad(q_hat, x_colloc, 
   torch.ones_like(q_hat), create_graph=True)[0]
   dh_dt = torch.autograd.grad(h_hat, t_colloc, 
   torch.ones_like(h_hat), create_graph=True)[0]
   dh_dx = torch.autograd.grad(h_hat, x_colloc, 
   torch.ones_like(h_hat), create_graph=True)[0]

   F1 = Cs_A * dq_dt + q_hat * dq_dx + g * Cs_A**2 * dh_dx + f * (torch.abs(q_hat) * q_hat) / (2 * diam)
   F2 = Cs_A * dh_dt + q_hat * dh_dx + a**2/g * dq_dx

   loss_pde = torch.mean(F1**2 + F2**2)

   train_output = pinn(x_train_rand, t_train_rand)

   loss_data = torch.mean((hq_tr - torch.squeeze(train_output))**2)

   loss = w_f * loss_pde + loss_data

   loss.backward()
   optimiser.step()

数据预处理定义

x_train = torch.tensor(x_inp.values).to(dtype=torch.float32)
t_train = torch.tensor(t_inp.values).to(dtype=torch.float32)
h_train = torch.tensor(h_inp.values).to(dtype=torch.float32)
q_train = torch.tensor(q_inp.values).to(dtype=torch.float32)

n_samples = len(x_train)
perm_indicies = torch.randperm(n_samples)

x_train_rand = x_train[perm_indicies].view(-1,1)
t_train_rand = t_train[perm_indicies].view(-1,1)
h_train_rand = h_train[perm_indicies].view(-1,1)
q_train_rand = q_train[perm_indicies].view(-1,1)

可能的原因及解决方法

  1. 输入尺度差异过大,未做归一化
    x的范围是0-300,t是0-10,两者尺度差异会导致网络难以捕捉输入变化。建议将输入缩放到[-1,1]或[0,1]区间:

    # 对配置点输入归一化
    x_colloc = (x_colloc - x_colloc.min()) / (x_colloc.max() - x_colloc.min())
    t_colloc = (t_colloc - t_colloc.min()) / (t_colloc.max() - t_colloc.min())
    # 训练数据执行相同归一化
    x_train = (x_train - x_train.min()) / (x_train.max() - x_train.min())
    t_train = (t_train - t_train.min()) / (t_train.max() - t_train.min())
    
  2. 网络层数过多导致激活函数饱和
    12层隐藏层搭配Tanh激活函数,容易因输入绝对值过大进入饱和区,导致梯度消失,网络无法学习输入差异。可尝试减少隐藏层数量(如3-5层),或改用LeakyReLU等非饱和激活函数。

  3. 自动求导与维度匹配问题
    检查torch.autograd.grad调用是否正确,确保对x和t的求导针对每个样本。同时验证hq_tr与train_output的维度是否匹配,torch.squeeze可能意外压缩维度,建议打印维度排查:

    print("train_output shape:", train_output.shape)
    print("hq_tr shape:", hq_tr.shape)
    
  4. 权重初始化过于一致
    Linear层默认初始化可能导致网络初始状态同质化,可手动用Xavier或He初始化优化:

    def init_weights(m):
        if isinstance(m, nn.Linear):
            nn.init.xavier_uniform_(m.weight)
            nn.init.zeros_(m.bias)
    pinn.apply(init_weights)
    

内容的提问来源于stack exchange,提问作者Felix Spiers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 07:53:21