一文读懂循环神经网络(RNN)—语言模型+读取长序列数据(2)

目录

读取长序列数据

为什么需要 “读取长序列数据”?

读取长序列数据的核心方法

1. 滑动窗口(Sliding Window)

2. 分段截取(Segmentation)

3. 滚动生成(Rolling Generation)

4. 关键信息采样

读取长序列数据的核心挑战

随机抽样(Random Sampling)

1.核心原理

2.具体操作

3.优缺点

4.适用场景

顺序分区(Sequential Partitioning)

1.核心原理

2.具体操作

3.优缺点

4.适用场景

4种核心方法的区别

完整代码

实验结果

第一次运行结果

第二次运行结果


读取长序列数据

读取长序列数据指的是对超出模型单次处理能力(或固定长度限制)的超长序列进行读取、拆分和预处理的过程。其核心目标是将长序列转换为模型可接受的格式,同时尽可能保留序列中的时序关系和上下文信息

为什么需要 “读取长序列数据”?

  1. 模型输入长度限制: 大多数序列模型(如 RNN、Transformer)对输入长度有固定限制(例如,早期 Transformer 的输入长度上限为 512 个词元)。若原始序列(如一篇万字文章、1 小时的语音)远超此限制,无法直接输入模型。

  2. 计算资源约束: 即使模型支持变长输入,超长序列会导致计算量和内存占用呈指数级增长(例如,自注意力机制的时间复杂度为 \(O(n^2)\),n 为序列长度),实际训练或推理时难以承受。

  3. 保留时序关系: 长序列的核心价值在于其内部的时序依赖(如文本中的上下文关联、时间序列中的长期趋势)。读取时需避免破坏关键依赖,否则会导致模型性能下降。

读取长序列数据的核心方法

处理长序列的核心思路是 “拆分”,但需根据任务需求选择合适的拆分策略,常见方法包括:

1. 滑动窗口(Sliding Window)
  • 原理:用固定长度的 “窗口” 在长序列上滑动,每次截取窗口内的子序列作为样本,窗口间可重叠(保留部分上下文)。
  • 示例:对长度为 1000 的文本,用长度为 100 的窗口,步长为 50 滑动,可得到 19 个样本(窗口位置:[0-99], [50-149], ..., [900-999])。
  • 适用场景:时间序列预测(如预测未来温度需保留近期趋势)、文本分类(需捕捉局部上下文)。
  • 优点:保留局部时序关系,样本数量多;
  • 缺点:窗口外的远距离依赖可能被割裂。
2. 分段截取(Segmentation)
  • 原理:将长序列按固定长度直接分割为不重叠的子序列(类似 “分块”)。
  • 示例:将 1000 个词的文本按 200 个词一段,分为 5 段(无重叠)。
  • 适用场景:对局部信息依赖较强的任务(如语音识别中的短句分割、长文档的段落级分类)。
  • 优点:简单高效,无冗余;
  • 缺点:可能切断段落中间的关键依赖(如句子被拆分为两段)。
3. 滚动生成(Rolling Generation)
  • 原理:对超长序列,每次用前序子序列的输出作为 “记忆”,辅助处理下一段子序列(类似人类 “分段阅读并记忆上下文”)。
  • 示例:用 RNN 处理 10000 词文本时,先处理前 1000 词并保存隐藏状态,再用该隐藏状态初始化模型,处理接下来的 1000 词,以此类推。
  • 适用场景:长文本生成(如小说续写)、实时数据流处理(如股票实时行情)。
  • 优点:可处理无限长序列,保留长期记忆;
  • 缺点:误差可能累积(前序处理的偏差会影响后续结果)。
4. 关键信息采样
  • 原理:对超长序列,只抽取关键部分(如摘要、峰值点),忽略冗余信息。
  • 示例:在长文本中提取关键词或句子组成短序列;在高频时间序列中保留峰值和谷值点。
  • 适用场景:对全局趋势而非细节敏感的任务(如长文档摘要、异常检测)。
  • 优点:大幅降低序列长度,保留核心信息;
  • 缺点:可能丢失重要细节,依赖有效的采样策略。

读取长序列数据的核心挑战

  1. 平衡长度与信息保留:拆分过短会丢失上下文,过长则增加计算负担。
  2. 处理时序断裂:拆分点可能位于关键依赖处(如句子中间、事件转折点),导致语义割裂。
  3. 动态适配模型:不同模型(如 RNN 对长距离依赖敏感,Transformer 对局部依赖更高效)需匹配不同的拆分策略。

随机抽样(Random Sampling)

1.核心原理
  • 用固定长度的 “窗口” 在长序列上随机滑动,截取不重叠(或少量重叠)的子序列作为样本。
  • 子序列的起始位置随机打乱,打破原始序列的连续性,降低样本间的相关性。
2.具体操作
  • 设定窗口长度(num_steps)和批量大小(batch_size)。
  • 从序列中随机选择起始点,生成多个子序列,组成批量数据。
  • 标签为子序列向右偏移 1 位的结果(预测下一个元素)。

示例

对序列 [0,1,2,...,34],用窗口长度 5 随机抽样,可能得到子序列:
[3,4,5,6,7][18,19,20,21,22][10,11,12,13,14]

3.优缺点
  • 优点:样本随机性高,训练时梯度波动小,适合并行计算
  • 缺点:破坏长距离时序依赖(如子序列前后的关联被割裂)。
4.适用场景

长期依赖要求不高的任务(如文本分类、短期时间序列预测)。

顺序分区(Sequential Partitioning)

1.核心原理
  • 将长序列按固定长度分割为连续的子序列,保留原始时序顺序,子序列间可连续拼接。
  • 按 “批次” 划分序列:先将序列均匀分为 batch_size 个连续片段,再从每个片段中按顺序截取子序列。
2.具体操作
  • 设定窗口长度(num_steps)和批量大小(batch_size)。
  • 将序列分为 batch_size 个并行的连续子序列(如序列分为 2 段:[0,1,...,17] 和 [18,19,...,34])。
  • 从每个子序列中按顺序截取窗口,组成批量(确保同批次样本在原始序列中位置对齐)。

示例

对序列 [0,1,2,...,34],分 2 个批次,窗口长度 5,可能得到:

  • 第 1 批:[0,1,2,3,4] 和 [18,19,20,21,22]
  • 第 2 批:[5,6,7,8,9] 和 [23,24,25,26,27]
3.优缺点
  • 优点:保留时序连续性,适合捕捉长期依赖(子序列可拼接为完整原始序列)。
  • 缺点:样本相关性高,训练时梯度可能震荡(同批次样本来自相邻区域)。
4.适用场景

时序依赖敏感的任务(如语言生成、长文本翻译、长期时间序列预测)。

4种核心方法的区别

方法核心逻辑关键特点典型场景
随机抽样随机截取子序列,打破顺序随机性高,丢失长期依赖文本分类、短期预测
顺序分区连续截取子序列,保留顺序时序完整,样本相关性高语言生成、长期预测
滑动窗口重叠截取,保留局部上下文平衡信息与效率语音识别、段落理解
滚动生成迭代处理,延续隐藏状态支持无限序列,误差累积实时数据流、超长文本处理

完整代码

"""
文件名: 8.4 读取长序列数据
作者: 墨尘
日期: 2025/7/14
项目名: dl_env
备注: 实现长序列数据的两种读取方式(随机抽样和顺序分区),将超长序列拆分为小批量子序列,适配序列模型的训练需求
"""
import random
import torch
import collections  # 备用:用于统计(本代码未直接使用)
import re  # 备用:用于文本处理(本代码未直接使用)
from d2l import torch as d2l  # 提供辅助功能(本代码未直接使用)
# 手动显示图像相关库(本代码未涉及绘图,仅保留配置)
import matplotlib.pyplot as plt
import matplotlib.text as text# -------------------------- 1. 随机抽样读取长序列 --------------------------
def seq_data_iter_random(corpus, batch_size, num_steps):  #@save"""使用随机抽样生成小批量子序列(打破原始序列顺序,适合并行训练)参数:corpus: 长序列数据(1D列表或数组,如[0,1,2,...,34])batch_size: 批量大小(每个批次包含的样本数)num_steps: 每个子序列的长度(模型单次处理的序列长度)生成器返回:X: 输入子序列(批量),形状为(batch_size, num_steps)Y: 标签子序列(批量),形状为(batch_size, num_steps),其中Y[i]是X[i]向右偏移1位的结果"""# 步骤1:随机偏移起始位置,避免总是从序列开头抽样(增加随机性)# 偏移范围为[0, num_steps-1],确保初始偏移不超过子序列长度corpus = corpus[random.randint(0, num_steps - 1):]# 步骤2:计算可生成的子序列总数# 减1是因为Y需要比X右移1位(最后一个元素没有标签)num_subseqs = (len(corpus) - 1) // num_steps  # 整数除法,确保子序列完整# 步骤3:生成所有子序列的起始索引# 从0开始,每隔num_steps取一个索引(如num_steps=5时,索引为0,5,10,...)initial_indices = list(range(0, num_subseqs * num_steps, num_steps))# 步骤4:随机打乱起始索引(核心:打破原始序列的顺序,避免样本相关性过高)random.shuffle(initial_indices)# 辅助函数:根据起始索引pos,返回长度为num_steps的子序列def data(pos):return corpus[pos: pos + num_steps]# 步骤5:按批量生成样本num_batches = num_subseqs // batch_size  # 总批次数 = 子序列总数 // 批量大小for i in range(0, batch_size * num_batches, batch_size):# 当前批次的起始索引列表(从打乱的索引中取batch_size个)initial_indices_per_batch = initial_indices[i: i + batch_size]# 生成输入X:每个元素是长度为num_steps的子序列X = [data(j) for j in initial_indices_per_batch]# 生成标签Y:每个元素是X中对应子序列右移1位的结果(预测下一个元素)Y = [data(j + 1) for j in initial_indices_per_batch]# 返回当前批次的X和Y(转换为张量)yield torch.tensor(X), torch.tensor(Y)# -------------------------- 2. 顺序分区读取长序列 --------------------------
def seq_data_iter_sequential(corpus, batch_size, num_steps):  #@save"""使用顺序分区生成小批量子序列(保留原始序列顺序,适合捕捉长期依赖)参数:corpus: 长序列数据(1D列表或数组)batch_size: 批量大小num_steps: 每个子序列的长度生成器返回:X: 输入子序列(批量),形状为(batch_size, num_steps)Y: 标签子序列(批量),形状为(batch_size, num_steps),Y是X右移1位的结果"""# 步骤1:随机偏移起始位置(与随机抽样类似,增加随机性)offset = random.randint(0, num_steps)# 步骤2:计算有效序列长度(确保能被batch_size整除,便于均匀分区)# 总有效长度 = ((原始长度 - 偏移 - 1) // batch_size) * batch_size# 减1是因为Y需要右移1位,确保X和Y长度相同num_tokens = ((len(corpus) - offset - 1) // batch_size) * batch_size# 步骤3:生成输入X和标签Y,并重塑为(batch_size, 总长度//batch_size)# X:从偏移开始,取num_tokens个元素Xs = torch.tensor(corpus[offset: offset + num_tokens])# Y:比X右移1位,同样取num_tokens个元素Ys = torch.tensor(corpus[offset + 1: offset + 1 + num_tokens])# 重塑为二维:每行是一个样本,列数为总长度//batch_sizeXs, Ys = Xs.reshape(batch_size, -1), Ys.reshape(batch_size, -1)# 步骤4:按顺序生成批次(保留序列顺序)num_batches = Xs.shape[1] // num_steps  # 总批次数 = 每行长度 // num_stepsfor i in range(0, num_steps * num_batches, num_steps):# 从每行中截取第i到i+num_steps列,作为当前批次的输入XX = Xs[:, i: i + num_steps]# 对应的标签Y(同样截取,与X对齐)Y = Ys[:, i: i + num_steps]yield X, Y# -------------------------- 3. 测试两种读取方法 --------------------------
if __name__ == '__main__':# 生成测试序列:0到34(长度35的序列)my_seq = list(range(35))print("测试序列:", my_seq)print("序列长度:", len(my_seq))# 超参数:批量大小=2,每个子序列长度=5batch_size = 2num_steps = 5# 测试1:随机抽样读取print("\n===== 随机抽样生成的批量 =====")for X, Y in seq_data_iter_random(my_seq, batch_size, num_steps):print("X(输入):")print(X)print("Y(标签,X右移1位):")print(Y)print("-" * 50)# 只打印3个批次(避免输出过长)break# 测试2:顺序分区读取print("\n===== 顺序分区生成的批量 =====")for X, Y in seq_data_iter_sequential(my_seq, batch_size, num_steps):print("X(输入):")print(X)print("Y(标签,X右移1位):")print(Y)print("-" * 50)# 只打印3个批次break

实验结果

第一次运行结果

第二次运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/88981.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/88981.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle Virtualbox 虚拟机配置静态IP

Oracle Virtualbox 虚拟机配置静态IP VirtualBox的网卡,默认都是第一个不能自定义,后续新建的可以自定义。 新建NAT网卡、host主机模式网卡 依次点击:管理->工具->网络管理器新建host主机模式网卡 这个网卡的网段自定义,创建…

Linux RAID1 创建与配置实战指南(mdadm)

Linux RAID1 创建与配置实战指南(mdadm)一、RAID1 核心价值与实战目标RAID1(磁盘镜像) 通过数据冗余提供高可靠性:当单块硬盘损坏时,数据不丢失支持快速阵列重建读写性能略低于单盘(镜像写入开销…

MySQL数据库----函数

目录函数1,字符串函数2,数值函数3,日期函数4,流程函数函数 1,字符串函数 MySQL中内置了很多字符串函数 2,数值函数 3,日期函数 4,流程函数

1.2 vue2(组合式API)的语法结构以及外部暴露

vue2 vue3中可以写vue2的语法&#xff0c;vue2的结构像一个花盆里的根&#xff08;根组件App.vue&#xff09;&#xff0c;根上可以插上不同的枝杈和花朵&#xff08;组件&#xff09;。 组件的结构&#xff1a; // 这里写逻辑行为 <script lang"ts"> export d…

Swift 解 LeetCode 324:一步步实现摆动排序 II,掌握数组重排的节奏感

文章目录摘要描述题解答案题解代码&#xff08;Swift&#xff09;题解代码分析步骤一&#xff1a;排序数组步骤二&#xff1a;左右指针分段步骤三&#xff1a;按位置交错插入示例测试及结果示例 1示例 2示例 3&#xff08;边界情况&#xff09;时间复杂度分析空间复杂度分析总结…

使用SQLMAP的文章管理系统CMS的sql注入渗透测试

SQLMAP注入演示&#xff1a;抓包拿到Cookie:召唤sqlmap&#xff1a;sqlmap -u "http://192.168.1.99:8085/show.php?id34" --cookie "pma_langzh_CN; kbqug_admin_username2621-PL_LxhFjyVe43ZuQvht6MI5q0ZcpRVV5FI0pzQ6XR8; kbqug_siteid2621-PL_LxhFjyVe4yA5…

I3C通信协议核心详解

一、物理层与电气特性双线结构 SCL&#xff08;串行时钟线&#xff09;&#xff1a;主设备控制&#xff0c;支持 推挽&#xff08;Push-Pull&#xff09;输出&#xff08;高速模式&#xff09;和 开漏&#xff08;Open-Drain&#xff09;&#xff08;兼容I2C模式&#xff09;。…

Docker搭建Redis哨兵集群

Redis提供了哨兵机制实现主从集群下的故障转移&#xff0c;其中包含了对主从服务的检测、自动故障恢复和通知。 1.环境 centos7、redis6.2.4、MobaXterm 目的&#xff1a; 搭建redis的主从同步哨兵集群&#xff08;一主一从三哨兵&#xff09; 2.步骤 1.主从集群的搭建 主从…

暑假Python基础整理 --异常处理及程序调试

异常概念 在程序运行过程中&#xff0c;经常会遇到各种各样的错误&#xff0c;这些错误统称为“异常”。如下表是Python常见的异常与描述&#xff1a; 异常描述NameError尝试访问一个未声明的变量引发错误IndexError索引超出序列范围引发错误IndentationError缩进错误ValueErr…

k8s-高级调度(二)

目录 Taint(污点)与Toleration(容忍) Taint&#xff08;污点&#xff09;&#xff1a;节点的排斥标记 Toleration&#xff08;容忍&#xff09;&#xff1a;Pod的适配声明 与节点亲和性的对比 警戒(cordon)和转移(drain) Cordon&#xff1a;节点隔离&#xff08;阻止新 Po…

基于OpenCV的深度学习人脸识别系统开发全攻略(DNN+FaceNet核心技术选型)

核心技术选型表 技术组件版本/型号用途OpenCV DNN4.5.5人脸检测FaceNet (facenet-pytorch)0.5.0人脸特征提取MiniConda最新版Python环境管理PyTorch1.8.0FaceNet运行基础OpenVINO2021.4模型加速(可选)SSD Caffe模型res10_300x300高精度人脸检测 一、环境准备与项目搭建 1.1 M…

【AI News | 20250714】每日AI进展

AI Repos 1、All-Model-Chat All Model Chat 是一款为Google Gemini API家族设计的网页聊天应用&#xff0c;支持多模态输入&#xff08;图片、音频、PDF等&#xff09;和多种模型&#xff08;如Gemini Flash、Imagen&#xff09;。它提供了丰富的自定义功能&#xff0c;包括高…

C 语言(二)

主要包括变量与常量、数据类型、存储方式、数制转换以及字符处理等内容一、变量与常量在 C 语言中&#xff0c;变量是用来存储数据的命名空间&#xff0c;它会在内存中分配地址。例如&#xff1a;int i; i 12345; 其中 i 是变量&#xff0c;12345 是常量。常量表示在程序运行过…

原型继承(prototypal inheritance)的工作原理

这是一个非常常见的 JavaScript 问题。所有 JS 对象都有一个__proto__属性&#xff0c;指向它的原型对象。当试图访问一个对象的属性时&#xff0c;如果没有在该对象上找到&#xff0c;它还会搜寻该对象的原型&#xff0c;以及该对象的原型的原型&#xff0c;依次层层向上搜索&…

OpenCV 视频处理与摄像头操作详解

1. 引言大家都来写OpenCV&#x1f60a;&#xff0c;学的好开心&#xff01;2. 视频基础与OpenCV简介2.1 视频的定义视频&#xff08;Video&#xff09;是由一系列静态图像&#xff08;帧&#xff09;以一定速率连续播放形成的动态影像。其本质是利用人眼的视觉暂留效应&#xf…

Agentic AI 的威胁与缓解措施

原文&#xff1a;https://www.aigl.blog/content/files/2025/04/Agentic-AI—Threats-and-Mitigations.pdf AI Agent 的定义 1. 定义与基础 智能代理&#xff08;Agent&#xff09;的定义&#xff1a; 智能代理是一种能够感知环境、进行推理、做出决策并自主采取行动以实现特定…

ArrayList列表解析

ArrayList集合 ArrayList 的底层是数组队列&#xff0c;相当于动态数组。与 Java 中的数组相比&#xff0c;它的容量能动态增长。在添加大量元素前&#xff0c;应用程序可以使用ensureCapacity操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。 ArrayList 继承…

《恋与深空》中龙和蛇分别是谁的代表

在《恋与深空》宏大而神秘的世界观中&#xff0c;每一个符号都蕴含着深意。当玩家们热议“龙”和“蛇”这两种强大而古老的生物究竟代表着谁时&#xff0c;所有的线索都默契地指向了同一个名字——秦彻。 他不仅是力量与权威的象征“恶龙”&#xff0c;也是背负着宿命与纠葛的“…

gitignore添加后如何生效?

清除 Git 缓存&#xff1a; git rm -r --cached .添加文件到 Git&#xff1a;git add .使用 git commit 命令提交这些更改git commit -m "Update .gitignore"

多尺度频率辅助类 Mamba 线性注意力模块(MFM),融合频域和空域特征,提升多尺度、复杂场景下的目标检测能力

在伪装物体检测领域&#xff0c;现有方法大多依赖空间局部特征&#xff0c;难以有效捕捉全局信息&#xff0c;而 Transformer 类方法虽能建模长距离依赖关系&#xff0c;却存在计算成本高、网络结构复杂的问题。同时&#xff0c;频域特征虽具备全局建模能力&#xff0c;可频繁的…