torch.autograd.grad 在计算时间导数时返回“None”

问题描述 投票:0回答:1

我有一个 LSTM 模型,它采用 3 个温度数据序列并输出下一个序列。

input => [array([0.20408163, 0.40816327, 0.6122449 ]), 
          array([0.40816327, 0.6122449 , 0.81632653])]
 output=> [tensor(0.81632653, dtype=torch.float64),
           tensor(0.91667510, dtype=torch.float64)]

现在,我想将这个 LSTM 模型与基于牛顿冷却定律的物理信息神经网络 (PINN) 结合起来。这个想法是使用 LSTM 预测温度,然后计算预测温度相对于时间的导数,将物理定律纳入损失函数中。

但是,当我尝试计算 LSTM 输出相对于时间 (t) 的梯度时,返回的梯度为 None。我不确定我是否正确使用 torch.autograd 来实现此目的。

这是我的代码的简化版本:

import torch
import torch.nn as nn

def create_lstm_model(input_size, hidden_size, num_layers, output_size):
    class LSTMModel(nn.Module):
        def __init__(self, input_size, hidden_size, num_layers, output_size):
            super(LSTMModel, self).__init__()
            self.hidden_size = hidden_size
            self.num_layers = num_layers
            self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
            self.fc = nn.Linear(hidden_size, output_size)

        def forward(self, x):
            h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
            c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
            out, _ = self.lstm(x, (h0, c0))
            out = self.fc(out[:, -1, :])
            return out


    return LSTMModel(input_size, hidden_size, num_layers, output_size)

def physics_loss_autograd(outputs, time_step):
    """
    Compute the physics-informed loss using autograd to get dT/dt.
    """
    # Compute dT/dt using autograd
    dT_dt = torch.autograd.grad(outputs, time_step, grad_outputs=torch.ones_like(outputs), create_graph=True)[0]

    # Newton's law of cooling: dT/dt = -k(T - T_ambient)
    residual = dT_dt + k * (outputs - T_ambient)

    # Physics loss is the L2 norm of the residual
    physics_loss = torch.mean(residual**2)

    return physics_loss


t = torch.arange(0,100) 
input_size =  1
hidden_size = 64
num_layers = 1
output_size = 1

# Create an instance of the LSTMModel using the function
model = create_lstm_model(input_size, hidden_size, num_layers, output_size)

criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)


num_epochs = 100
for epoch in range(num_epochs):
    model.train()
    total_loss = 0

    for inputs, targets in train_loader:
        inputs, targets = inputs.float(), targets.float()  # Convert to float
        # print(inputs.shape)
        optimizer.zero_grad()
        outputs = model(inputs)


        
        data_loss = criterion(outputs, targets)
        
        # DO SOMETHING LIKE
        phys_loss = physics_loss_autograd(outputs, t)
        loss = data_loss + phys_loss

        loss.backward()
        optimizer.step()
        total_loss += loss.item()

    if (epoch+1) % 20 == 0:
        print(f'Epoch {epoch+1}/{num_epochs}, Loss: {total_loss/len(train_loader)}')

有人解决过类似的问题吗?任何关于如何计算 LSTM 输出的时间导数的指导都会非常有帮助!

附加信息:

  • 时间 t 是时间步长,未明确包含为 LSTM 的输入。我尝试将时间步长作为输入的附加功能包含在内,但它也没有计算导数。
  • 对于使用 PINN 以及将物理损失与 LSTM 相结合,我还是个新手。

当我尝试通过 torch.autograd.grad 计算物理信息损失时,问题就出现了:

dT_dt = torch.autograd.grad(outputs, t, grad_outputs=torch.ones_like(outputs), create_graph=True)[0]

这对 dT_dt 返回 None。我怀疑我处理 time_step 或 autograd 设置的方式存在问题,但我不确定到底出了什么问题。

deep-learning pytorch neural-network lstm physics
1个回答
0
投票

Pytorch 使用 autograd 计算梯度。 Autograd 的工作原理是跟踪计算图中前向传递中的计算,然后向后遍历该计算图以计算梯度。

这意味着计算两个值之间的梯度需要在计算图中链接这些值。相反,Pytorch 无法计算未通过计算图链接的变量之间的梯度。一个简单的例子:

a = torch.randn(8, requires_grad=True)
b = torch.randn(8, requires_grad=True)
c = torch.randn(8, requires_grad=True)

y = a*b

dy_da = torch.autograd.grad(y, a, grad_outputs=torch.ones_like(y), retain_graph=True)[0]
dy_db = torch.autograd.grad(y, b, grad_outputs=torch.ones_like(y), retain_graph=True)[0]
dy_dc = torch.autograd.grad(y, c, grad_outputs=torch.ones_like(y), retain_graph=True, allow_unused=True)[0]

在上面,

dy_da
dy_db
是张量,而
dy_dc
None
。这是因为
c
不参与生成
y
的计算图 - 没有计算将
c
链接到
y

对于您的示例,您的值

t
不参与
outputs
的计算,因此无法计算输出相对于
t
的梯度。

如果您希望这成为可能,您需要设计模型,使

t
成为生成
outputs
的模型函数的输入。

© www.soinside.com 2019 - 2024. All rights reserved.