首页 > 其他分享 >《动手学深度学习 Pytorch版》 8.2 文本预处理

《动手学深度学习 Pytorch版》 8.2 文本预处理

时间:2023-10-09 10:12:15浏览次数:44  
标签:8.2 词元 self token tokens Pytorch corpus 文本 预处理

import collections
import re
from d2l import torch as d2l

解析文本的常见预处理步骤:

  1. 将文本作为字符串加载到内存中。

  2. 将字符串拆分为词元(如单词和字符)。

  3. 建立一个词表,将拆分的词元映射到数字索引。

  4. 将文本转换为数字索引序列,方便模型操作。

8.2.1 读取数据集

本文从 H. G. Wells 的《时光机器》一书的英文原著 The Time Machine 中加载文本,它只有30000多个单词。

#@save
d2l.DATA_HUB['time_machine'] = (d2l.DATA_URL + 'timemachine.txt',
                                '090b5e7e70c295757f55df93cb0a180b9691891a')

def read_time_machine():  #@save
    """将时间机器数据集加载到文本行的列表中"""
    with open(d2l.download('time_machine'), 'r') as f:
        lines = f.readlines()
    return [re.sub('[^A-Za-z]+', ' ', line).strip().lower() for line in lines]

lines = read_time_machine()
print(f'# 文本总行数: {len(lines)}')
print(lines[0])
print(lines[10])
# 文本总行数: 3221
the time machine by h g wells
twinkled and his usually pale face was flushed and animated the

8.2.2 词元化

词元(token) 是文本的基本单位。tokenize 函数将文本行列表作为输入,列表中的每个元素是一个文本序列。每个文本序列又被拆分成一个词元列表,最后返回一个由词元列表组成的列表。

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

tokens = tokenize(lines)
for i in range(11):
    print(tokens[i])
['the', 'time', 'machine', 'by', 'h', 'g', 'wells']
[]
[]
[]
[]
['i']
[]
[]
['the', 'time', 'traveller', 'for', 'so', 'it', 'will', 'be', 'convenient', 'to', 'speak', 'of', 'him']
['was', 'expounding', 'a', 'recondite', 'matter', 'to', 'us', 'his', 'grey', 'eyes', 'shone', 'and']
['twinkled', 'and', 'his', 'usually', 'pale', 'face', 'was', 'flushed', 'and', 'animated', 'the']

8.2.3 词表

字符串类型的词元需要转换成模型需要的数字输入。

  • 首先构建一个词表(vocabulary),将字符串类型的词元映射到从 0 开始的数字索引中。

    • 先将训练集中的所有文档合并在一起进行唯一词元统计,得到的统计结果称之为语料(corpus)

    • 然后根据每个唯一词元的出现频率,为其分配一个数字索引。

  • 移除很少出现的词元通常以降低复杂性。

  • 将语料库中不存在或已删除的任何词元都映射到一个特定的未知词元“<unk>”。

  • 可以选择增加一个列表,用于保存那些被保留的词元,例如:填充词元(“<pad>”); 序列开始词元(“<bos>”); 序列结束词元(“<eos>”)。

class Vocab:  #@save
    """文本词表"""
    def __init__(self, tokens=None, min_freq=0, reserved_tokens=None):
        if tokens is None:
            tokens = []
        if reserved_tokens is None:
            reserved_tokens = []
        counter = count_corpus(tokens)
        self._token_freqs = sorted(counter.items(), key=lambda x: x[1],  # 按出现频率排序
                                   reverse=True)
        self.idx_to_token = ['<unk>'] + reserved_tokens  # 下标对应词源 未知词元的索引为0
        self.token_to_idx = {token: idx  # 词元对应下标
                             for idx, token in enumerate(self.idx_to_token)}
        for token, freq in self._token_freqs:
            if freq < min_freq:  # 跳过频率过低的词
                break
            if token 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):
        return len(self.idx_to_token)

    def __getitem__(self, tokens):
        if not isinstance(tokens, (list, tuple)):
            return self.token_to_idx.get(tokens, self.unk)
        return [self.__getitem__(token) for token in tokens]

    def to_tokens(self, indices):
        if not isinstance(indices, (list, tuple)):
            return self.idx_to_token[indices]
        return [self.idx_to_token[index] for index in indices]

    @property
    def unk(self):  # 未知词元的索引为0
        return 0

    @property
    def token_freqs(self):
        return self._token_freqs

def count_corpus(tokens):  #@save
    """统计词元的频率"""
    # 这里的tokens是1D列表或2D列表
    if len(tokens) == 0 or isinstance(tokens[0], list):
        # 将词元列表展平成一个列表
        tokens = [token for line in tokens for token in line]
    return collections.Counter(tokens)
vocab = Vocab(tokens)  # 使用时光机器数据集作为语料库来构建词表
print(list(vocab.token_to_idx.items())[:10])  # 打印前几个高频词元及其索引

for i in [0, 10]:  # 将每一条文本行转换成一个数字索引列表
    print('文本:', tokens[i])
    print('索引:', vocab[tokens[i]])
[('<unk>', 0), ('the', 1), ('i', 2), ('and', 3), ('of', 4), ('a', 5), ('to', 6), ('was', 7), ('in', 8), ('that', 9)]
文本: ['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]

8.2.4 整合所有功能

将所有功能打包到 load_corpus_time_machine 函数中,返回 corpus(词元索引列表)和 vocab(时光机器语料库的词表)。

在这里所做的改变是:

  • 使用字符(而不是单词)实现文本词元化以简化后面章节中的训练;

  • 时光机器数据集中的每个文本行不一定是一个句子或一个段落,还可能是一个单词,因此返回的corpus仅处理为单个列表,而不是使用多词元列表构成的一个列表。

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

corpus, vocab = load_corpus_time_machine()
len(corpus), len(vocab)
(170580, 28)

练习

(1)词元化是一个关键的预处理步骤,它因语言而异。尝试找到另外三种常用的词元化文本的方法。

  • BPE(Byte-Pair Encoding)

  • WordPiece

  • SentencePiece


(2)在本节的实验中,将文本词元化为单词并更改 Vocab 实例的 min_freq 参数。这对词表大小有何影响?

lines = read_time_machine()
tokens = tokenize(lines, 'word')
vocab = Vocab(tokens, min_freq=3)
corpus = [vocab[token] for line in tokens for token in line]
if -1 > 0:
    corpus = corpus[:-1]

len(corpus), len(vocab)
(32775, 1420)

标签:8.2,词元,self,token,tokens,Pytorch,corpus,文本,预处理
From: https://www.cnblogs.com/AncilunKiang/p/17750838.html

相关文章

  • windows下安装conda和安装GPU版本的tensorflow和pytorch
    windows下安装conda和安装GPU版本的tensorflow和pytorch驱动下载查看自己电脑的独立显卡型号如:NVIDIAGeForceRTX3060在查看自己电脑是否已经安装了显卡驱动,如果显卡可用,那么就是安装了驱动;否则就要到NVIDIA官网下载驱动NVIDIA驱动程序下载找到自己对应型号的显卡驱动下载......
  • 《动手学深度学习 Pytorch版》 8.1 序列模型
    到目前为止,我们遇到的数据主要是表格数据和图像数据,并且所有样本都是独立同分布的。然而,大多数的数据并非如此。比如语句中的单词、视频中的帧以及音频信号,都是有顺序的。简言之,如果说卷积神经网络可以有效地处理空间信息,那么本章的循环神经网络(recurrentneuralnetwork,RNN)则可......
  • pytorch(8-1) 循环神经网络 序列模型
    https://zh.d2l.ai/chapter_recurrent-neural-networks/sequence.html     #%matplotlibinlineimporttorchfromtorchimportnnfromd2limporttorchasd2lfromAPI_Drawimport*T=1000#总共产生1000个点#time[0,1...,999]time=torch.arange(......
  • pytorch训练模版
    train.pyimporttorchimportnumpyasnpimportosimportmathimportsysimportargparseimportpsutilimporttorchimporttorch.optimasoptimimporttorch.optim.lr_scheduleraslr_schedulerfromtorchvisionimporttransformsimporttorchvisionimportd......
  • pytorch 自定义dataset类
    实现模版classour_dataset(Dataset):def__init__(self,···):super(our_dataset,self).__init__()#初始化,可以自定义添加参数def__getitem__(self,index):···returnimg,label#根据索引(0,len(dataset)-1)获取......
  • pytorch F.grid_sample
    importtorchfromtorch.nnimportfunctionalasFinp=torch.ones(1,1,4,4)inp=torch.randint(1,10,(1,1,4,4)).float()#目的是得到一个长宽为20的tensorout_h=20out_w=20#grid的生成方式等价于用mesh_gridnew_h=torch.linspace(-1,1,out_h).v......
  • pytorch的四个hook函数
    训练神经网络模型有时需要观察模型内部模块的输入输出,或是期望在不修改原始模块结构的情况下调整中间模块的输出,pytorch可以用hook回调函数来实现这一功能。主要使用四个hook注册函数:register_forward_hook、register_forward_pre_hook、register_full_backward_hook、registe......
  • 为研究不同宽度,厚度,重量,车间温度,冷却方式下,物料温度随时间呈指数衰减的模型函数,
    为研究不同宽度,厚度,重量,车间温度,冷却方式下,物料温度随时间呈指数衰减的模型函数,请使用python按照下面的表格形式,生成模拟数据,数据预处理,选择模型,划分数据集,训练模型,调整超参数,预测和评估,并绘图谢谢您的反馈。我可以尝试改进模拟生成的df数据,以让它更加真实。......
  • 不同宽度,厚度,重量,车间温度,冷却方式下,物料温度随时间衰减,请使用python机器学习,
    生成模拟数据、数据预处理、选择模型、划分数据集、训练模型、调整超参数、预测和评估以及绘图是一个相对复杂的流程。下面是一个示例流程,涵盖了这些步骤:importnumpyasnpimportpandasaspdimportmatplotlib.pyplotaspltfromsklearn.model_selectionimporttrain_test_......
  • 不同宽度,厚度,重量,车间温度,冷却方式下,物料温度随时间呈指数衰减,,请使用python机
    生成模拟数据、数据预处理、选择模型、划分数据集、训练模型、调整超参数、预测和评估以及绘制图表是一个完整的机器学习项目流程。下面是一个用Python完成这些步骤的基本示例。请注意,这只是一个简单的示例,实际项目中可能需要更复杂的数据和模型选择。首先,确保你已经安装了必要的Py......