news 2026/7/9 9:46:04

循环神经网络与文本处理:文本预处理基础与实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
循环神经网络与文本处理:文本预处理基础与实践

文本预处理

学习目标

通过本课程的学习,学员将理解文本预处理的基本步骤,包括将文本加载到内存中、拆分为词元、构建词表将词元映射为数字索引,并能够将文本数据转换为词元索引序列以供模型操作。

相关知识点

  • 文本预处理

学习内容

对于序列数据处理问题,这样的数据存在许多种形式,文本是最常见例子之一。
例如,一篇文章可以被简单地看作一串单词序列,甚至是一串字符序列。
本课程将解析文本的常见预处理步骤。
这些步骤通常包括:

  1. 将文本作为字符串加载到内存中。
  2. 将字符串拆分为词元(如单词和字符)。
  3. 建立一个词表,将拆分的词元映射到数字索引。
  4. 将文本转换为数字索引序列,方便模型操作。
%pip install d2l import collections import refromd2l import torch as d2l

1 文本预处理

1.1 读取数据集

首先,我们从H.G.Well的时光机器中加载文本。这是一个相当小的语料库,只有30000多个单词,但足够我们小试牛刀,而现实中的文档集合可能会包含数十亿个单词。下面的函数将数据集读取到由多条文本行组成的列表中,其中每条文本行都是一个字符串。为简单起见,我们在这里忽略了标点符号和字母大写。

#下载数据集!wget https://model-community-picture.obs.cn-north-4.myhuaweicloud.com/ascend-zone/notebook_datasets/2a455d7c0ea211f085e8fa163edcddae/timemachine.txt
defread_time_machine(file_path):#@save"""将时间机器数据集加载到文本行的列表中"""withopen(file_path,'r')asf:lines=f.readlines()return[re.sub('[^A-Za-z]+',' ',line).strip().lower()forlineinlines]file_path='./timemachine.txt'lines=read_time_machine(file_path)print(f'# 文本总行数:{len(lines)}')print(lines[0])print(lines[10])
1.2 词元化和词表
1.2.1 词元化

下面的tokenize函数将文本行列表(lines)作为输入,列表中的每个元素是一个文本序列(如一条文本行)。每个文本序列又被拆分成一个词元列表,词元(token)是文本的基本单位。最后,返回一个由词元列表组成的列表,其中的每个词元都是一个字符串(string)。

def tokenize(lines,token='word'):#@save"""将文本行拆分为单词或字符词元"""iftoken =='word':return[line.split() for line in lines]elif token =='char':return[list(line) for line in lines]else: print('错误:未知词元类型:'+token)tokens = tokenize(lines)fori in range(11): print(tokens[i])
1.2.2 词表

词元的类型是字符串,而模型需要的输入是数字,因此这种类型不方便模型使用。现在,让我们构建一个字典,通常也叫做词表(vocabulary),用来将字符串类型的词元映射到从0 00开始的数字索引中。我们先将训练集中的所有文档合并在一起,对它们的唯一词元进行统计,得到的统计结果称之为语料(corpus)。然后根据每个唯一词元的出现频率,为其分配一个数字索引。很少出现的词元通常被移除,这可以降低复杂性。另外,语料库中不存在或已删除的任何词元都将映射到一个特定的未知词元“<unk>”。我们可以选择增加一个列表,用于保存那些被保留的词元,例如:填充词元(“<pad>”);序列开始词元(“<bos>”);序列结束词元(“<eos>”)。

classVocab:#@save"""文本词表"""def __init__(self,tokens=None,min_freq=0,reserved_tokens=None):iftokens is None: tokens =[]ifreserved_tokens is None: reserved_tokens =[]# 按出现频率排序counter = count_corpus(tokens)self._token_freqs = sorted(counter.items(),key=lambda x: x[1],reverse=True)# 未知词元的索引为0self.idx_to_token =['<unk>']+reserved_tokens self.token_to_idx ={token: idxforidx,token in enumerate(self.idx_to_token)}fortoken,freq in self._token_freqs:iffreq < min_freq:breakiftoken not in self.token_to_idx: self.idx_to_token.append(token)self.token_to_idx[token]= len(self.idx_to_token)-1 def __len__(self):returnlen(self.idx_to_token)def __getitem__(self,tokens):ifnot isinstance(tokens,(list,tuple)):returnself.token_to_idx.get(tokens,self.unk)return[self.__getitem__(token) for token in tokens]def to_tokens(self,indices):ifnot isinstance(indices,(list,tuple)):returnself.idx_to_token[indices]return[self.idx_to_token[index] for index in indices]@property def unk(self):# 未知词元的索引为0return0 @property def token_freqs(self):returnself._token_freqs def count_corpus(tokens):#@save"""统计词元的频率"""# 这里的tokens是1D列表或2D列表iflen(tokens)== 0 or isinstance(tokens[0],list):# 将词元列表展平成一个列表tokens =[token for line in tokens for token in line]returncollections.Counter(tokens)

我们首先使用时光机器数据集作为语料库来构建词表,然后打印前几个高频词元及其索引。

vocab=Vocab(tokens)print(list(vocab.token_to_idx.items())[:10])

out:

[('<unk>', 0), ('the', 1), ('i', 2), ('and', 3), ('of', 4), ('a', 5), ('to', 6), ('was', 7), ('in', 8), ('that', 9)]

现在,我们可以将每一条文本行转换成一个数字索引列表。

foriin[0,10]:print('文本:',tokens[i])print('索引:',vocab[tokens[i]])

out:

文本:['the','time','machine','by','h','g','wells']索引:[1,19,50,40,2183,2184,400]文本:['twinkled','and','his','usually','pale','face','was','flushed','and','animated','the']索引:[2186,3,25,1044,362,113,7,1421,3,1045,1]
1.3 整合所有功能

在使用上述函数时,我们将所有功能打包到load_corpus_time_machine函数中,该函数返回corpus(词元索引列表)和vocab(时光机器语料库的词表)。我们在这里所做的改变是:1.本课程使用字符(而不是单词)实现文本词元化;2. 时光机器数据集中的每个文本行不一定是一个句子或一个段落,还可能是一个单词,因此返回的corpus仅处理为单个列表,而不是使用多词元列表构成的一个列表。

defload_corpus_time_machine(max_tokens=-1):#@save"""返回时光机器数据集的词元索引列表和词表"""lines=read_time_machine(file_path)tokens=tokenize(lines,'char')vocab=Vocab(tokens)# 因为时光机器数据集中的每个文本行不一定是一个句子或一个段落,# 所以将所有文本行展平到一个列表中corpus=[vocab[token]forlineintokensfortokeninline]ifmax_tokens>0:corpus=corpus[:max_tokens]returncorpus,vocab file_path='./timemachine.txt'corpus,vocab=load_corpus_time_machine()len(corpus),len(vocab)

out:

(170580, 28)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/30 1:09:06

AI看懂世界的第一步|基于MiDaS镜像实现图像深度可视化

AI看懂世界的第一步&#xff5c;基于MiDaS镜像实现图像深度可视化 概述&#xff1a;让AI“感知”三维空间的起点 在计算机视觉的发展历程中&#xff0c;单目深度估计&#xff08;Monocular Depth Estimation, MDE&#xff09; 是一项极具挑战又充满潜力的技术。它试图解决一个…

作者头像 李华
网站建设 2026/7/1 1:57:17

Java SpringBoot+Vue3+MyBatis 购物推荐网站系统源码|前后端分离+MySQL数据库

摘要 随着电子商务的快速发展&#xff0c;个性化购物推荐系统成为提升用户体验和商家销量的关键技术。传统的购物网站往往缺乏精准的用户行为分析能力&#xff0c;导致推荐结果与用户需求匹配度不高。基于大数据和机器学习算法的智能推荐系统能够有效解决这一问题&#xff0c;通…

作者头像 李华
网站建设 2026/7/8 12:30:58

深度估计新选择|AI单目深度估计-MiDaS镜像原生集成PyTorch模型

深度估计新选择&#xff5c;AI单目深度估计-MiDaS镜像原生集成PyTorch模型 [toc]引言&#xff1a;从2D图像到3D空间感知的技术跃迁 在计算机视觉领域&#xff0c;如何让机器“看懂”三维世界一直是核心挑战之一。传统方法依赖双目立体视觉或多传感器融合&#xff08;如LiDAR&am…

作者头像 李华
网站建设 2026/7/1 1:34:42

ResNet18激活函数对比:云端快速完成ab测试

ResNet18激活函数对比&#xff1a;云端快速完成ab测试 引言 作为一名AI研究员&#xff0c;你是否遇到过这样的困惑&#xff1a;在构建ResNet18模型时&#xff0c;面对ReLU、LeakyReLU、Swish等多种激活函数&#xff0c;不知道哪个最适合你的任务&#xff1f;手动逐个测试不仅…

作者头像 李华
网站建设 2026/6/30 18:12:17

高精度深度热力图生成指南|基于AI 单目深度估计 - MiDaS镜像实践

高精度深度热力图生成指南&#xff5c;基于AI 单目深度估计 - MiDaS镜像实践 1. 方案背景与技术价值 在计算机视觉领域&#xff0c;从单张2D图像中恢复三维空间结构一直是极具挑战性的任务。传统方法依赖多视角几何&#xff08;如SfM、SLAM&#xff09;或激光雷达等主动传感设备…

作者头像 李华
网站建设 2026/7/5 7:53:06

Rembg部署监控:服务健康检查与报警设置

Rembg部署监控&#xff1a;服务健康检查与报警设置 1. 引言 1.1 智能万能抠图 - Rembg 在图像处理和内容创作领域&#xff0c;自动去背景技术已成为提升效率的核心工具之一。Rembg 作为一款基于深度学习的开源图像分割工具&#xff0c;凭借其强大的 U-Net 模型架构&#xff…

作者头像 李华