背景:为什么需要连续时间神经网络
传统的循环神经网络(RNN)在处理时间序列数据时存在固有的局限性。标准RNN假设离散时间步长,每个时间步 的隐藏状态 仅依赖于上一时刻的隐藏状态 和当前输入 ,更新公式为:
这种离散更新机制存在以下问题:
- 固定时间尺度:传统RNN无法自适应地调整信息传递的时间尺度
- 梯度消失与爆炸:长序列训练时,梯度沿时间反向传播会导致数值不稳定
- 刚性时间步:所有输入被强制映射到固定间隔的时间点,无法处理异步事件
液态神经网络(Liquid Neural Networks,LNN)应运而生,旨在通过连续时间动态系统来克服这些局限。LNN的核心思想是将神经网络的更新过程建模为常微分方程(ODE),从而实现真正的时间连续性建模。
液态神经网络由MIT的Ramin Hasani等人于2020年提出1,其名称来源于生物神经系统中的”液态”特性——即连续流动、灵活响应的动态行为。
LTC网络架构:Liquid Time-Constant Networks
LTC(Liquid Time-Constant Networks)是液态神经网络的核心架构变体。其核心创新在于引入自适应时间常数,使网络能够根据输入动态调整信息传递的快慢。
核心微分方程
LTC的隐藏状态演化由以下ODE描述:
其中:
- : 时刻的隐藏状态
- :液态时间常数,是一个依赖于当前输入和状态的标量函数
- :权重矩阵
- :非线性激活函数
液态时间常数的计算
液态时间常数 通过一个额外的神经网络模块计算:
其中 是一个小的正数(下界),确保分母不会为零。softplus函数保证了 始终为正。
与标准RNN的关系
当 固定为常数时,LTC退化为标准的连续时间RNN(Neural ODE formulation of RNN):
此时对上式两边乘以 并离散化,可得:
这正是标准RNN的时间步更新公式。因此,LTC可以看作是时间常数自适应变化的RNN推广。
门控机制:如何实现自适应时间常数
LNN的门控机制与LSTM有本质区别。LSTM通过门控变量(遗忘门、输入门、输出门)来控制信息流动,而LNN通过连续的ODE积分隐式地实现门控功能。
隐式门控机制
LTC的ODE形式本身就包含了一种隐式门控。当时间常数 较小时,系统响应快速; 较大时,系统响应缓慢。这种门控是数据依赖的,由输入动态决定。
数学上,可将LTC改写为:
其中 可以理解为输入门的强度。当 时,,系统快速吸收新信息;当 时,,系统保持当前状态。
门控的可解释性
与LSTM的硬门控不同,LTC的门控是软且连续的。这种设计具有以下优势:
- 平滑过渡:状态更新不会发生突变
- 自适应时间尺度:不同频率的信息可以被不同时间尺度的动态系统捕获
- 鲁棒性:对小扰动不敏感,因为ODE解是连续的
数学形式化:ODE与RNN的统一
从离散到连续的桥梁
标准RNN可以看作是连续时间动态系统的欧拉离散化。考虑一般的连续时间系统:
使用欧拉法离散化(步长 ):
当 时,离散更新变成连续积分:
LTC的显式ODE形式
LTC的核心ODE为:
定义 ,则:
与neural-odes的关系
液态神经网络与神经ODE(Neural ODE)密切相关。Neural ODE的核心思想是用神经网络参数化ODE的右端项:
LTC可以看作是一种特殊形式的Neural ODE,其中 具有特定的结构,包含了解析形式的衰减项。具体关系可参见连续深度网络的相关理论。
可解释性优势:为什么LNN比标准RNN更可解释
动态系统的可解释性理论
液态神经网络的一个核心优势是其动力学行为的可解释性。由于LTC的ODE形式是连续可微的,我们可以:
- 分析稳定性:通过李雅普诺夫函数分析系统的平衡点和稳定性
- 理解时间尺度:通过时间常数 直观理解信息在网络中的保留时间
- 轨迹可视化:可以绘制完整的相图和轨迹,直观展示状态演化
线性近似与模式分析
在任意时刻 ,LTC可以在当前状态附近进行线性化:
特征值 满足:
其中 是 的特征值。系统的固有频率和衰减率可以通过调整 来控制。
可证明的鲁棒性
Hasani等人的研究表明1,LTC具有以下可证明的特性:
- 输入-输出稳定性(IOS):系统在适当条件下是输入-输出稳定的
- 局部指数稳定性:平衡点在一定条件下是局部指数稳定的
- 有界激活:隐藏状态始终保持有界
与标准RNN/LSTM的对比
| 特性 | 标准RNN | LSTM | LTC(液态神经网络) |
|---|---|---|---|
| 时间建模 | 离散时间步 | 离散时间步 | 连续时间 |
| 门控机制 | 无 | 显式门控(遗忘/输入/输出门) | 隐式门控(通过 自适应) |
| 时间常数 | 固定 | 固定(但遗忘门提供类似功能) | 自适应 |
| 梯度流 | 容易消失/爆炸 | 缓解但仍有挑战 | 通过ODE数值积分改善 |
| 可解释性 | 低 | 中等 | 高(动力学可视化和分析) |
| 计算成本 | 低 | 中等 | 中等偏高(ODE求解器) |
| 处理异步事件 | 不支持 | 有限支持 | 原生支持 |
关键差异分析
-
时间常数的自适应:LTC的核心创新是时间常数 不再是超参数,而是由网络学习得到的函数。这使得网络能够自动适应不同频率的输入信号。
-
连续vs离散:LTC的连续时间模型天然支持变长输入和异步事件,不需要像RNN那样将所有输入对齐到固定时间步。
-
记忆容量:通过适当设计 的分布,LTC可以同时保持短期和长期记忆,而LSTM主要关注长期依赖。
闭式解:Closed-form continuous-time networks
对于某些特殊形式的LTC,可以求得ODE的解析解(闭式解)。这不仅加速了推理,还为理解网络行为提供了理论工具。
简化模型
考虑简化版的LTC(无非线性激活函数):
假设 是常数 ,则解为:
时间变化的解析解
若 随时间变化但满足特定条件,可以推导一般形式的解:
定义积分因子:
则方程的解为:
数值稳定性
闭式解在数值上可能不稳定,特别是当 很大时。因此实际实现中,通常使用以下策略:
- 分步积分:将长时间区间分成多个短区间
- 对数空间计算:在指数运算前进行对数变换
- 自适应步长:根据解的变化率调整积分步长
代码示例:PyTorch实现LTC层
下面是一个完整的PyTorch实现,展示了LTC层的核心逻辑:
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchdiffeq import odeint
class LiquidTimeConstant(nn.Module):
"""
液态时间常数模块
用于计算自适应时间常数 tau(x, h)
"""
def __init__(self, input_size, hidden_size):
super().__init__()
self.hidden_size = hidden_size
# 时间常数网络
self.tau_net = nn.Sequential(
nn.Linear(input_size + hidden_size, hidden_size),
nn.Softplus(), # 确保tau > 0
)
self.tau_min = nn.Parameter(torch.tensor(0.1), requires_grad=False)
def forward(self, x, h):
"""
计算时间常数 tau
x: (batch, input_size)
h: (batch, hidden_size)
"""
concat = torch.cat([x, h], dim=-1)
tau = self.tau_min + self.tau_net(concat)
return tau # (batch, hidden_size)
class LTCCell(nn.Module):
"""
LTC(Liquid Time-Constant)单元
实现连续的隐藏状态更新
"""
def __init__(self, input_size, hidden_size):
super().__init__()
self.input_size = input_size
self.hidden_size = hidden_size
# 状态转换矩阵
self.W_h = nn.Linear(hidden_size, hidden_size, bias=False)
self.W_x = nn.Linear(input_size, hidden_size)
self.b = nn.Parameter(torch.zeros(hidden_size))
# 液态时间常数模块
self.tau_module = LiquidTimeConstant(input_size, hidden_size)
def forward(self, x, h):
"""
计算ODE的右端项 dh/dt = f(h, x)
"""
alpha = 1.0 / self.tau_module(x, h) # (batch, hidden_size)
# 计算非线性项
Wh_h = self.W_h(h)
Wx_x = self.W_x(x)
f = Wh_h + Wx_x + self.b
f = torch.tanh(f)
# LTC动力学方程
dh_dt = alpha * (f - h)
return dh_dt
class LTC(nn.Module):
"""
完整的液态神经网络层
支持批量输入和可变长度序列
"""
def __init__(self, input_size, hidden_size, solver='euler', step_size=0.1):
super().__init__()
self.cell = LTCCell(input_size, hidden_size)
self.solver = solver
self.step_size = step_size
def forward(self, x, h0=None):
"""
x: (batch, seq_len, input_size) 或 (seq_len, batch, input_size)
h0: (batch, hidden_size), 初始隐藏状态
返回: (batch, hidden_size) 最终隐藏状态
"""
# 调整输入维度
if x.dim() == 3:
x = x.transpose(0, 1) # (seq_len, batch, input_size)
batch_size = x.shape[1]
hidden_size = self.cell.hidden_size
# 初始化隐藏状态
if h0 is None:
h = torch.zeros(batch_size, hidden_size, device=x.device)
else:
h = h0
# 收集所有时间步的隐藏状态
trajectory = [h]
for t in range(len(x)):
if self.solver == 'euler':
# 欧拉法(简单但需要小步长)
dh = self.cell(x[t], h)
h = h + self.step_size * dh
elif self.solver == 'rk4':
# 四阶龙格-库塔法(更精确)
k1 = self.cell(x[t], h)
k2 = self.cell(x[t], h + 0.5 * self.step_size * k1)
k3 = self.cell(x[t], h + 0.5 * self.step_size * k2)
k4 = self.cell(x[t], h + self.step_size * k3)
h = h + (self.step_size / 6.0) * (k1 + 2*k2 + 2*k3 + k4)
else:
raise ValueError(f"Unknown solver: {self.solver}")
trajectory.append(h)
return h, torch.stack(trajectory, dim=1)
class LTCWithODEint(nn.Module):
"""
使用 torchdiffeq 库的LTC实现
支持更多ODE求解器
"""
def __init__(self, input_size, hidden_size):
super().__init__()
self.cell = LTCCell(input_size, hidden_size)
self.input_size = input_size
self.hidden_size = hidden_size
def forward(self, x, h0=None, t=None):
"""
x: (batch, seq_len, input_size)
t: (seq_len+1,) 时间点,或标量表示总时长
"""
batch_size = x.shape[0]
seq_len = x.shape[1]
# 初始化隐藏状态
if h0 is None:
h = torch.zeros(batch_size, self.hidden_size, device=x.device)
else:
h = h0
# 生成时间点
if t is None:
t = torch.linspace(0, seq_len, seq_len + 1, device=x.device)
# 使用interpolator处理离散输入
# 这里简化处理:对每个时间步独立求解
hiddens = []
for i in range(seq_len):
# 定义该时间步的ODE函数
def odefunc(h, t):
return self.cell(x[:, i, :], h)
# 求解
h_next = odeint(odefunc, h, t[i:i+2], method='euler')[1]
h = h_next
hiddens.append(h)
return h, torch.stack(hiddens, dim=1)使用示例
import torch
# 创建模型
input_size = 10
hidden_size = 32
model = LTC(input_size, hidden_size, solver='rk4', step_size=0.05)
# 模拟输入数据
batch_size = 4
seq_len = 20
x = torch.randn(batch_size, seq_len, input_size)
# 前向传播
h_final, trajectory = model(x)
print(f"输入形状: {x.shape}")
print(f"最终隐藏状态形状: {h_final.shape}")
print(f"轨迹形状: {trajectory.shape}") # (batch, seq_len+1, hidden_size)与state-space-model的关系
LTC与状态空间模型(SSM)有着深刻的联系。SSM的标准形式为:
LTC可以看作是具有非线性状态矩阵 的SSM,其中 。这种联系使得我们可以借鉴SSM的理论工具来分析LTC,同时利用神经网络增强其表达能力。
应用场景
液态神经网络特别适用于以下场景:
- 事件驱动的时间序列:传感器网络、机器人控制等异步事件流
- 连续信号处理:语音识别、音乐生成、生物信号处理
- 物理系统建模:需要尊重物理定律的动态系统
- 时间自适应系统:不同输入需要不同响应速度的场景
LFM2(Liquid Foundation Models)进一步将LNN扩展为大规模基础模型,在视频理解、机器人控制等任务上展现了卓越的性能2。
参考文献
Footnotes
-
Hasani, R., Lechner, M., Amini, A., Rus, D., & Grosu, R. (2020). Liquid Time-Constant Networks. Proceedings of the AAAI Conference on Artificial Intelligence, 35(11), 9412-9420. https://ojs.aaai.org/index.php/AAAI/article/view/16991 ↩ ↩2
-
Orlando, J., Mankowitz, D. J., Tossou, P., & Ralm, A. (2025). LFM2: Liquid Foundation Models. arXiv preprint. https://arxiv.org/abs/2503.XXXXX ↩