15 循环神经网络(基础)

本文介绍循环神经网络(RNN),用于处理序列数据。先阐述RNN Cell本质是共享的线性层,输入序列各项关联,前项输出作为后项输入。接着说明RNN计算过程,包括线性变换、信息融合与激活。还给出两种代码实现方式,最后提及独热向量缺点及嵌入层降维。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

循环神经网络

  之前介绍的全连接网络也叫做稠密网络(Dense)。

在这里插入图片描述
  
  这一篇博客介绍的 RNN 主要用来处理带有序列类型的数据的输入,这就是 RNN 网络主要面向的目标。那么什么是 RNN 呢?


RNN Cell

  首先我们来说一下什么是 RNN Cell?下图中的 x t x_t xt 表示时刻 t t t 的数据(比如说是一个 3 维的向量),然后经过 RNN Cell 的转变之后得到了一个 5 维的向量 h t h_t ht。将一个 3 维的向量变成一个 5 维的向量意味着 RNN Cell 的本质就是一个线性层,线性层是可以把一个维度映射到另外一个维度。

在这里插入图片描述
  
  那么它和一般的线性层有什么区别呢?RNN Cell 这个线性层是共享的,有些参考资料会把 RNN 的图示画成如下:

在这里插入图片描述
  
但是我更喜欢把它展开:

在这里插入图片描述

  其中 x 1 x_1 x1 x 2 x_2 x2 x 3 x_3 x3 x 4 x_4 x4 是输入序列,输入完成之后,送到 RNN Cell 中,注意这里的 RNN Cell 就是一个 Linear(做一个线性变换),然后得到一个输出 h h h,这里的 h h h 叫做 hidden(隐层)这里需要注意,我们将输入序列的每一项都送到 RNN Cell 中,因为这些输入序列之间每一项都和前一项存在关系,所以我们得把当前的前一项的输出作为后一项的 RNN Cell 中其中一个输入。举个栗子,当前为 x 2 x_2 x2 这一项,它计算出的 h 2 h_2 h2 里面不仅要包含 x 2 x_2 x2 的信息,它还要包含 x 1 x_1 x1 的信息。那怎么包含 x 1 x_1 x1 的信息呢?肯定是要想办法把 x 1 x_1 x1 里面向量的值通过某种运算和 x 2 x_2 x2 进行融合。注意上图中的红色箭头,红色箭头指的是当 x 1 x_1 x1 输入到 RNN Cell ,做一个线性变换得到一个输出 h 1 h_1 h1,我们不仅将 h 1 h_1 h1 进行输出,还将它输入到了下一个 RNN Cell 中,所以红色箭头传送的就是上一个计算的结果 h 1 h_1 h1

在这里插入图片描述

  还需要注意一点,上图中的 RNN Cell 都是同一个线性层,所以才可以用下图表示:

在这里插入图片描述
  
  所以我们将 RNN 叫做循环神经网络。


RNN 计算过程

  下面我们看一下 RNN 具体的计算过程。首先我们有一个输入 x t x_t xt ,它的维度是 input_size x 1, 我们对它先做一个线性变换,将其维度变为 hidden_size x 1,那么在线性变换中的 W W W 的维度就应该是 hidden_size x input_size。

在这里插入图片描述
  

  上一层的隐层输入为 h_(t-1),它的输入维度是 hidden_size x 1,输出维度也是 hidden_size x 1,那么 W_hh 的维度就是 hidden_size x hidden_size。

在这里插入图片描述
  
  然后将两个结果进行相加,就相当于把信息进行融合。融合之后,然后做一个激活,这里用的激活函数为 t a n tan tan 函数,因为 t a n tan tan 的取值是在 -1~+1 之间,我们更喜欢在 -1~+1 之间的输入,它是被认为效果比较好的激活函数,所以我们在 RNN 中使用 t a n tan tan 作为激活函数。然后得到计算结果 h t h_t ht,这就是我们这一层隐层的输出。

在这里插入图片描述
  
我们就将下面框中的部分叫做 RNN Cell。

在这里插入图片描述
  

  那么 h t h_t ht 的公式如下:

在这里插入图片描述
  
  以上就是 RNN Cell 的运算。下面我们看一下怎么用代码实现 RNN。这里一共有两种方法,一种是自己定义 RNN Cell,然后再实现处理序列循环。另外一种就是直接使用 Pytorch 中的 RNN。
  
  首先我们看一下第一种方法怎么实现,首先得构造 RNN Cell,那么我们需要设定的参数主要有 input_size 和 hidden_size。只要有了这两个值,就能够把 W W W b b b 的维度确定下来。

在这里插入图片描述
  
  下面我们来举个例子,我们现在如下设置:

在这里插入图片描述
  
  那么 RNN Cell 的输入和输出的 shape 如下:

在这里插入图片描述
  
  那么我们整个输入序列会构造成如下维度:

在这里插入图片描述
  
  下面我们用具体的代码来表示这个过程:

    1. 设置参数 Paeameters
    2. 初始化 RNN Cell
    3. 写个简单示例

在这里插入图片描述
  
  接下来我们使用第二种方法直接使用 RNN,代码如下:

在这里插入图片描述
  
  对于 RNN 单元来说,它的输入输出维度和隐层的维度如下:
  
在这里插入图片描述
  
  现在我们要使用 RNN,还是要设置下面几个参数:

在这里插入图片描述
  
  输入的维度和 h 0 h_0 h0 的维度:

在这里插入图片描述
  
  输出的维度和 h n h_n hn 的维度:

在这里插入图片描述
  
  那么什么是 numLayers 呢?

在这里插入图片描述
  
  接下来我们使用代码来实现:


  
  除此之外,在 RNN 里面还有一些其它参数,比如:batch_first,若设置为 True,即将 batch_size 作为第一个维度。

在这里插入图片描述
  
  接下来我们介绍一个小栗子:现在有一个序列到序列的任务,输入是 “hello”,输出是 ”ohlol“,我们想训练一个序列到序列的 RNN 的网络,来学习序列变换的规律。
  

  首先我们使用 RNN Cell 来实现,那么我们的输入分别是 " h " "h" "h" " e " "e" "e" " l " "l" "l" " l " "l" "l" " o " "o" "o",隐层的输出就是 " o " "o" "o" " h " "h" "h" " l " "l" "l" " o " "o" "o" " l " "l" "l"。但是这里有一个问题,这里的输入和输出并不是一个向量,所以第一步我们需要将字符进行向量化,

在这里插入图片描述
  
  一般来说,在做自然语言处理时,比如字符集,会先根据出现的字符构造一个词典,然后给每个字符分配一个索引(可以按照字母表,也可以随机)。然后根据索引,将每一个字符变成索引。

在这里插入图片描述
  
  转变成索引之后,我们把它变成向量,向量的宽度是和词典中字符个数是相同的。我们这个向量叫做 One-Hot Vectors(独热向量),然后把这个向量送到 RNN 中作为序列的输入。

在这里插入图片描述
  
  这就是把文本转换成向量的一种最简单的方式,那么它的 inputsize 等于 4。

在这里插入图片描述
  
  现在我们的输入字符已经变成一个个的独热向量了。那么输出我们只想知道你属于哪个类别,比如我们只有 4 个字符 h h h e e e l l l o o o,我们就像看输入的字符是属于哪一个,相应的这就是一个多分类问题,因为类别是 4 个,所以输出的就是长度为 4 的向量,然后再接一个交叉熵算出损失。所以我们这里要求输入也是四维的,将来将其变成一个分布。

在这里插入图片描述
  
  处理完数据之后,我们就开始使用 RNN Cell.

在这里插入图片描述
  
  我们再来看看代码中具体的参数。

在这里插入图片描述
  之后就是准备数据。

在这里插入图片描述

  准备好数据之后,就开始定义模型:

在这里插入图片描述
  
  构造完模型之后,就可以构建损失函数和优化器:
在这里插入图片描述
  
  最后就是训练的过程:

在这里插入图片描述
  
  以上就是使用 RNN Cell 的代码。如果我们想要使用 RNN,代码怎么怎么设计:

在这里插入图片描述
  
  然后模型设计这一块的代码有哪些改进:

在这里插入图片描述
  
  对于输入输出:

在这里插入图片描述

  以上就是使用 RNN 的方式。


接下来我们介绍一下在处理自然语言时,我们用的是独热向量。但是它有一些缺点:

  • The one-hot vectors are high-dimension(高维的)。比如字母级的,你可能需要 128 个;如果是词级的,这里面的维度就太高了,比如英语单词。
  • The one-hot vectors are sparse(稀疏)。
  • The one-hot vectors are hardcoded(硬编码)。比如说每一个字符对应哪个向量,是硬编码的,并不是学习出来的。

  那么我们能不能找到一种变换,是低维度的,稠密的,并且数据是学习出来的。一种比较流行的方式就是 EMBEDDING(嵌入层)。嵌入层就是将高维的,稀疏的数据映射到低维的,稠密的空间中。这就是常说的数据的降维。

在这里插入图片描述
  
  那么相应的代码做如下改变:

在这里插入图片描述
  
  然后我们用一下参数进行测试:

在这里插入图片描述
  
  然后构造输入和输出:

在这里插入图片描述
  
  然后构造模型,损失函数和优化器:

在这里插入图片描述
  
  最后进行训练:

在这里插入图片描述


具体代码见 15 循环神经网络(基础).ipynb

<think>我们正在处理一个关于如何使用循环神经网络(RNN)进行轨迹训练和预测的问题。根据用户的问题,我们需要提供实现方法。结合提供的引用,特别是引用[2]中详细描述了使用LSTM(一种RNN)进行车辆轨迹预测的步骤,我们可以以此为基础构建回答。 步骤概述: 1. 数据准备:收集轨迹数据,进行预处理(清洗、去噪、插值等),可能还需要特征提取。 2. 数据序列化:将轨迹数据转化为时间序列格式,定义输入序列和输出标签(如下一时刻的位置)。 3. 模型构建:选择RNN类型(如LSTM或GRU),构建网络结构。 4. 模型训练:划分训练集和验证集,使用训练数据训练模型。 5. 模型评估:使用验证集评估模型性能,进行可视化分析。 6. 模型部署:将训练好的模型应用于实际预测。 我们将按照这些步骤详细说明,并参考引用[2]的内容。同时,我们也会参考其他引用中提到的技术,如双向RNN(引用[3])和门控机制(引用[4])来丰富回答。 注意:由于用户要求使用中文,并且需要生成相关问题,我们在回答的最后会生成相关问题。 另外,根据引用[1],我们还可以提到RNN与其他技术的结合(如注意力机制、CNN)来提升模型性能,但这可能属于进阶内容,我们可以在优化部分提及。 下面开始组织回答。</think>### 如何使用RNN进行轨迹预测的实现方法 轨迹预测是自动驾驶、机器人导航等领域的核心任务。循环神经网络(RNN)因其能有效处理时序数据而成为主流解决方案,以下是具体实现步骤: #### 1. **数据准备与预处理** - **数据收集**:获取车辆/物体的轨迹数据(时间戳、经纬度坐标、速度、加速度等)[^2] - **数据清洗**: - 处理缺失值(如线性插值) - 剔除GPS定位异常点(如速度突变点) - 归一化坐标数据(缩放至$[0,1]$区间) - **特征工程**: - 计算衍生特征:移动方向角$\theta = \arctan(\frac{\Delta y}{\Delta x})$、曲率$c = \frac{\Delta \theta}{\Delta s}$ - 构建特征向量:$\mathbf{x}_t = [lat_t, lon_t, v_t, a_t, \theta_t]$ #### 2. **序列数据构建** - 将轨迹切分为固定长度的时间窗口: - 输入序列:$X = \{\mathbf{x}_{t-k}, \mathbf{x}_{t-k+1}, ..., \mathbf{x}_t\}$ - 输出标签:$y = \mathbf{x}_{t+1}$(单步预测)或$\{\mathbf{x}_{t+1}, ..., \mathbf{x}_{t+m}\}$(多步预测) - 数据集划分比例(示例): | 数据集 | 比例 | 作用 | |-------|------|------| | 训练集 | 70% | 模型训练 | | 验证集 | 15% | 超参数调优 | | 测试集 | 15% | 最终评估 | #### 3. **模型构建(以LSTM为例)** ```python from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense model = Sequential() # 输入形状: (时间步长, 特征维度) model.add(LSTM(128, return_sequences=True, input_shape=(timesteps, n_features))) model.add(LSTM(64)) model.add(Dense(32, activation='relu')) # 输出层: 预测下一时刻的经纬度坐标 model.add(Dense(2)) model.compile(loss='mse', optimizer='adam') # 使用均方误差损失 ``` **关键结构说明**: - **LSTM门控机制**:通过遗忘门$f_t$、输入门$i_t$、输出门$o_t$控制信息流,解决长程依赖问题[^4]: $$ \begin{aligned} f_t &= \sigma(W_f \cdot [h_{t-1}, x_t] + b_f) \\ i_t &= \sigma(W_i \cdot [h_{t-1}, x_t] + b_i) \\ \tilde{C}_t &= \tanh(W_C \cdot [h_{t-1}, x_t] + b_C) \\ C_t &= f_t \circ C_{t-1} + i_t \circ \tilde{C}_t \\ o_t &= \sigma(W_o \cdot [h_{t-1}, x_t] + b_o) \\ h_t &= o_t \circ \tanh(C_t) \end{aligned} $$ - **双向LSTM**:可捕获前后时序依赖(引用[3]技术): ```python from tensorflow.keras.layers import Bidirectional model.add(Bidirectional(LSTM(64))) # 自动拼接正向/反向输出 ``` #### 4. **模型训练与调优** - **训练配置**: - 批量大小:32-256(根据显存调整) - 早停机制:当验证集损失连续5轮不下降时终止训练 - 学习率调度:每10轮衰减为原来的0.8倍 - **进阶优化**: - 注意力机制:增强关键位置特征的权重[^1] - CNN-LSTM融合:用CNN提取空间特征后再输入LSTM[^1] - 损失函数改进:添加Huber损失减少异常值影响 #### 5. **评估与可视化** - **定量评估指标**: - 位移误差:$ADE = \frac{1}{T}\sum_{t=1}^{T} \| \hat{y}_t - y_t \|_2$ - 终点误差:$FDE = \| \hat{y}_T - y_T \|_2$ - **可视化方法**: ```python import matplotlib.pyplot as plt # 绘制真实轨迹 plt.plot(gt_lon, gt_lat, 'b-', label='Ground Truth') # 绘制预测轨迹 plt.plot(pred_lon, pred_lat, 'r--', label='Prediction') plt.legend(); plt.show() ``` #### 6. **部署应用** - 模型轻量化:通过知识蒸馏或量化压缩模型 - 实时预测流水线: ```mermaid graph LR A[传感器数据] --> B[数据预处理] B --> C[序列化输入] C --> D[RNN模型预测] D --> E[路径规划决策] ``` ### 典型应用场景 1. **自动驾驶**:预测周围车辆未来3秒轨迹(采样频率10Hz)[^2] 2. **无人机巡检**:强风环境下的路径偏差修正 3. **体育分析**:篮球运动员跑位预测 > 提示:实际部署时需考虑**在线学习机制**,持续用新数据更新模型以适应环境变化[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值