深度学习--循环神经网络RNN(ing)
参考
循环神经网络
一文搞懂RNN(循环神经网络)基础篇
零基础入门深度学习(5) - 循环神经网络
史上最详细循环神经网络讲解(RNN/LSTM/GRU)
循环神经网络(recurrent neural network,RNN)
到目前为止默认数据都来自于某种分布,并且所有样本都是独立同分布的.然而大多数数据并非如此。
不仅仅可以接收一个序列作为输入,而是还可能期望继续猜测这个序列的后续。
循环神经网络(recurrent neural network,RNN)则可以更好地处理序列信息。 循环神经网络通过引入状态变量存储过去的信息和当前的输入,从而可以确定当前的输出。
自回归模型
维度 | 自回归模型(AR) | 隐变量自回归模型(Latent AR) |
---|---|---|
是否含隐变量 | 否 | 是,隐变量为概率意义上的状态 |
数据依赖 | 仅自身历史数据 | 依赖历史观测 + 推断出的隐状态 |
趋势建模能力 | 线性、平稳趋势 | 可建模非线性、状态切换、多模态序列 |
推断方式 | 参数估计(如最小二乘) | 概率推断(如EM、变分推断) |
表达能力 | 有限,主要适用于简单结构序列 | 表达力强,适用于复杂动态系统 |
自回归模型(autoregressive models,AR)
使用时间序列自身的过去值的线性组合来预测未来值
$$
X_t = c + \sum_{i=1}^p \phi_i X_{t-i} + \epsilon_t
$$
- $p$:滞后阶数;
- $\phi_i$:模型参数;
- $\epsilon_t$:白噪声项。
缺陷:仅依赖自身历史观测值;假设数据平稳,趋势是线性的;无需建模潜在状态;适用于简单趋势建模,不擅长处理状态切换或复杂行为。
隐变量自回归模型(latent autoregressive models)
引入不可观测的隐状态变量(latent variable),作为对历史信息的压缩总结,通过该状态驱动观测值的生成。
$$
\begin{cases}
z_t = f(z_{t-1}, x_{t-1}) & \text{(隐状态递归更新)} \\
x_t \sim p(x_t \mid z_t) & \text{(观测值生成)}
\end{cases}
$$
- $z_t$:隐状态(通常为概率分布);
- $f$:状态转移函数(可为神经网络或状态空间模型);
- $p(x_t \mid z_t)$:条件生成分布。
特点:能建模状态转换、周期性、非线性结构;适用于多模态、复杂序列;需要通过统计方法(如 EM 算法、变分推断)估计隐变量的分布;隐状态是软分配的,不是硬选择。
马尔可夫模型
时间序列的当前状态 $X_t$ 理论上依赖于全部过去:
$$
P(X_t \mid X_{t-1}, X_{t-2}, \ldots)
$$
马尔可夫条件假设此依赖可简化为有限阶:
$$
P(X_t \mid X_{t-1}, \ldots, X_{t-p})
$$
当 $p=1$ 时,即为一阶马尔可夫性质,当前状态只依赖前一状态:
$$
P(X_t \mid X_{t-1}, X_{t-2}, \ldots) = P(X_t \mid X_{t-1})
$$
特点对比 | 马尔可夫模型 | 自回归模型 |
---|---|---|
状态类型 | 离散(如晴天、雨天、雪天) | 连续数值(如体重) |
依赖对象 | 前一时刻的状态 | 前几个时刻的观测值 |
预测方式 | 状态转移概率 | 线性组合(加权求和)加白噪声 |
序列模型
$$
x_t \sim P(x_t \mid x_{t-1}, \ldots, x_1)
$$
$\sim$ 代表“从……中采样”。随机变量 $x_t$ 的取值是根据条件概率分布 $P(x_t\mid x_{t-1}, \ldots, x_1)$ 生成的。当前时刻的 $x_t$ 是依赖于之前所有时刻的变量 $x_1, x_2, \ldots, x_{t-1}$ 的。这反映了序列中元素之间的关联性,说明 $x_t$ 与之前的元素有关联,而非独立产生。
ps:下标顺序只是展示的顺序问题,数学意义上并不影响条件集合的内容。
给定一个长度为 $T$ 的序列 $(x_1, x_2, \ldots, x_T)$,它们的联合概率分布满足链式法则
$$
P(x_1, x_2, \ldots, x_T) = \prod_{t=1}^T P(x_t \mid x_1, x_2, \ldots, x_{t-1})
$$
时间步(time step)用 $t \in \mathbb{Z}^+$ 表示序列中的第 $t$ 个时间点。
目标是建模序列中任一时刻的输出依赖于之前的若干时间步输入。
自回归模型
第一种策略,假设在现实情况下相当长的序列$x_{t-1}, \dots, x_1$ 可能是不必要的, 因此我们只需要满足某个长度为 $\tau$ 的时间跨度,即使用观测序列 $x_{t-1}, \dots, x_{t-\tau}$。当下获得的最直接的好处就是参数的数量总是不变的,至少在 $t > \tau$ 时如此,这就使我们能够训练一个上面提及的深度网络。这种模型被称为 自回归模型(autoregressive models),因为它们是对自己执行回归。
第二种策略,如图 8.1.2 所示,是保留一些对过去观测的总结 $h_t$,并且同时更新预测 $\hat{x}t$ 和总结 $h_t$。这就产生了基于 $\hat{x}t = P(x_t \mid h_t)$ 估计 $x_t$,以及公式 $h_t = g(h{t-1}, x{t-1})$ 更新的模型。由于 $h_t$ 从未被观测到,这类模型也被称为隐变量自回归模型(latent autoregressive models)。
线性自回归模型(AR(p))
$$
x_t = \phi_1 x_{t-1} + \phi_2 x_{t-2} + \dots + \phi_p x_{t-p} + \epsilon_t
$$
- $x_t$:当前值
- $\phi_i$:模型参数
- $\epsilon_t$:噪声项(白噪声)
- $p$:窗口长度
非线性自回归模型(如 RNN)
将上式替换为非线性表达:
$$
x_t = f(x_{t-1}, x_{t-2}, \dots, x_{t-p}) + \epsilon_t
$$
或使用隐藏状态方式:
$$
\begin{aligned}
h_t &= f(h_{t-1}, x_{t-1}) \\
\hat{x}_t &= g(h_t)
\end{aligned}
$$
马尔可夫模型(Markov Model)
马尔可夫模型是一个统计建模方法。
时间序列的当前状态 $X_t$ 理论上依赖于全部过去:
$$
P(X_t \mid X_{t-1}, X_{t-2}, \ldots)
$$
马尔可夫条件假设此依赖可简化为有限阶:
$$
P(X_t \mid X_{t-1}, \ldots, X_{t-p})
$$
当 $p=1$ 时,即为一阶马尔可夫性质,当前状态只依赖前一状态:
$$
P(X_t \mid X_{t-1}, X_{t-2}, \ldots) = P(X_t \mid X_{t-1})
$$
特点对比 | 马尔可夫模型 | 自回归模型 |
---|---|---|
状态类型 | 离散(如晴天、雨天、雪天) | 连续数值(如体重) |
依赖对象 | 前一时刻的状态 | 前几个时刻的观测值 |
预测方式 | 状态转移概率 | 线性组合(加权求和)加白噪声 |
有隐状态的循环神经网络
代码中的 H 被初始化为一个随机值,表示初始时刻的隐藏状态。这一点是非常重要的,因为在序列数据的处理过程中,我们通常需要为网络提供一个初始的隐藏状态,这个初始隐藏状态的选择可以影响模型的学习过程。
H 的初始化表示的是 初始时刻的隐藏状态,它在第一次前向传播时被赋值为随机值,之后的每个时间步中,隐藏状态会根据前一个时间步的隐藏状态和当前的输入来更新。
1 | X, W_xh = torch.normal(0, 1, (3, 1)), torch.normal(0, 1, (1, 4)) |
拼接的目的:合并计算,减少操作次数.只是计算上的重排和合并,模型逻辑没变,还是用两个不同的权重矩阵分别对不同输入部分作用,只是计算时合成一步。
1 | torch.matmul(torch.cat((X, H), 1), torch.cat((W_xh, W_hh), 0)) |
循环神经网络的从零开始实现
独热编码
PyTorch 的 F.one_hot 函数将数字序列 [0, 2] 转换为 独热编码(one-hot encoding),是高维稀疏向量。
ps:word embedding可以替代one hot
1 | F.one_hot(torch.tensor([0, 2]), len(vocab)) |
1 | # inputs的形状:(时间步数量,批量大小,词表大小) |
循环神经网络的简洁实现
256个隐藏单元,一维张量,长度256。
1 | num_hiddens = 256 |
1 | class RNNModel(nn.Module): |
RNN
RNN 本质上就是一个非线性的、自适应的、神经网络形式的自回归模型。
只能从前往后建模:
- 状态更新:
$$
S_t = f(U V_t + W S_{t-1} + b)
$$
- 输出计算:
$$
O_t = g(S_t, V_t)
$$
权重在所有时间步(t=1 到 t=T)之间是相同的,同一组权重参数会被用于所有时间步的计算
双向 RNN
同时考虑过去和未来:
$$
\begin{aligned}
h_t^{\rightarrow} &= f(h_{t-1}^{\rightarrow}, x_t) \\
h_t^{\leftarrow} &= f(h_{t+1}^{\leftarrow}, x_t) \\
h_t &= [h_t^{\rightarrow}; h_t^{\leftarrow}] \\
y_t &= g(h_t)
\end{aligned}
$$
向量化
神经网络的输入和输出都是向量,为了让语言模型能够被神经网络处理,我们必须把词表达为向量的形式,这样神经网络才能处理它。
深度循环神经网络
前面循环神经网络只有一个隐藏层,我们当然也可以堆叠两个以上的隐藏层,这样就得到了深度循环神经网络。
循环神经网络的训练算法:BPTT
BPTT算法是针对循环层的训练算法,它的基本原理和BP算法是一样的,也包含同样的三个步骤:
前向计算每个神经元的输出值;
反向计算每个神经元的误差项值,它是误差函数E对神经元j的加权输入的偏导数;
计算每个权重的梯度。
最后再用随机梯度下降算法更新权重。
1 | ``` |
1 | ``` |