我正在使用 darts 来预测 Lorenz 系统,这是一个来自 3 个常微分方程的 3D 多元混沌时间序列。我创建了一个 TFT 模型,该模型经过合成数据的训练 - 使用的每个数据集都被放入一个系列中:
train_series = TimeSeries.from_group_dataframe(training_df,
group_cols = 'simNum',
time_col = 'time_idx',
value_cols = ['x','y','z'],
static_cols = ['sigma','rho','beta'])
其中 sigma、rho 和 beta 是恒定的、静态的协变量,对于每个组都是有界和随机的(这个特定的尝试有 200 次模拟)。输入数据帧的所有列都是浮点数(使用
Scaler
进行缩放,time_idx
除外,它是为每个组重置的时间整数。
我的目标是将洛伦兹系统的 3 个 ODE 合并到损失函数中作为残差最小化,所以我目前有:
import torch
import torch.nn as nn
def grad(outputs, inputs):
"""Computes the partial derivative of
an output with respect to an input."""
return torch.autograd.grad(
outputs,
inputs,
grad_outputs=torch.ones_like(outputs),
create_graph=True
)
def lorenz(x, y, z, s, r, b):
# Function modeling lorenz attractor system
x_dot = s * (y - x)
y_dot = x * (r - z) - y
z_dot = (x * y) - (b * z)
return x_dot, y_dot, z_dot
def odeLoss(model):
#defining collocation points
ts = torch.linspace(0, timeMax, TOTAL_SAMPLES).view(-1, 1).requires_grad_(True)
# Run collocation points through network
out = model.predict(ts, TOTAL_SAMPLES)
# Get gradient
dT = grad(out, ts)
# Compute ODE
odeOut = 0
# Return MSE of ODE
return torch.mean(odeOut**2)
除了数据丢失项之外,我还打算使用
loss_fn = MSELoss() + odeLoss()
将其添加到模型参数中。
odeLoss 函数是我需要帮助的地方:我不确定如何在搭配点上生成模型预测或将 ODE 合并到具有未知静态协变量的函数中。我是否只需生成 3 个随机值来定义搭配点上的 sigma、rho 和 beta,并将它们集成到
model.predict
和 odeOut
计算中?我陷入了僵局,不知道如何继续。我相信 darts 库使用 pytorch 和 pytorch lighting,所以我可能会尝试定义一个继承训练器的子类。
odeLoss 函数是我需要帮助的地方:我不确定如何在搭配点上生成模型预测或将 ODE 合并到具有未知静态协变量的函数中。我是否只需生成 3 个随机值来定义搭配点上的 sigma、rho 和 beta,并将它们集成到 model.predict 和 odeOut 计算中?
在这里,只需使用函数的残差作为损失:
class LorenzLoss(nn.Module):
def __init__(self, sigma, rho, beta, dt):
super(LorenzLoss, self).__init__()
self.sigma = sigma
self.rho = rho
self.beta = beta
self.dt = dt
def forward(self, y_pred, y_true):
# Extracting the predicted values for x, y, and z
x, y, z = y_pred[:, 0], y_pred[:, 1], y_pred[:, 2]
# Calculating the residuals for the Lorenz system
dx = self.sigma * (y - x) - (x - y_true[:, 0]) / self.dt
dy = x * (self.rho - z) - y - (y - y_true[:, 1]) / self.dt
dz = x * y - self.beta * z - (z - y_true[:, 2]) / self.dt
# Summing up the residuals to compute the loss
loss = torch.mean(dx**2 + dy**2 + dz**2)
return loss