《动手学深度学习》-52文本预处理实现

原始文本 → 规范化文本 → token 序列 → 词表(token↔id) → 数字序列(id 序列)

核心:构建词表(Vocab)

词表是文本数字化的关键,它维护两种映射:

  1. token → index(token_to_idx):把词映射成数字 id

  2. index → token(idx_to_token):把数字 id 还原成词

构建词表时,一般要处理三个关键机制:

  1. 未知词 <unk>

现实中一定会遇到训练时没见过的词。因此词表会预留一个特殊 token:<unk>,代表"未知词"。

当查不到某个 token 时,用 <unk> 的 id 代替。常见约定:<unk> 的 id 是 0。

  1. 保留 token(reserved_tokens)

有些 token 是任务必需的特殊标记,比如:

  • <pad>:填充到固定长度

  • <bos>:句子开始

  • <eos>:句子结束

  • <mask>:掩码(BERT 类模型)

这些 token 通常放在词表最前面(紧跟 <unk>),确保它们有稳定的 id。

  1. 最小频次过滤(min_freq)

文本里有大量低频词,如果全部纳入词表:

  • 词表会非常大,占内存、训练慢

  • 很多低频词对模型帮助小,但会引入稀疏噪声

因此常设置 min_freq,只保留出现次数 ≥ min_freq 的 token。低频词统一用 <unk> 替代。

复制代码
2.代码

def read_time_machine(payh='D:/PycharmDocument/limu/data/timemachine.txt'):
    with open(payh,'r',encoding='utf-8') as f:
        lines=f.readlines()
    return [re.sub('[^A-Za-z]+',' ',line).strip().lower() for line in lines]
lines=read_time_machine()
# print(lines[10])
# print(len(lines))
def tokenize(lines,token='word'):
    if token=='word':
        return [line.split() for line in lines]
    elif token=='char':
        return [list(line) for line in lines]
    else:
        print('wrong token')
tokens=tokenize(lines,'word')
# for i in range(11):
#     print(tokens[i])
复制代码
#词汇表,将字符串映射到数字索引
class Vocab:
    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_cropus(tokens)
        self.token_freqs=sorted(counter.items(),key=lambda x:x[1],reverse=True)#讲词频排序
        self.unk,uniq_tokens=0,['<unk>']+reserved_tokens#初始化,uniq_tokens起始设置为unk和reserved_tokens
        uniq_tokens+=[token for token,freq in self.token_freqs#讲词频高且不在reserved_tokens里的token依次加载,此时为全部的token
                      if freq>=min_freq and token not in reserved_tokens]
        self.idx_to_token,self.token_to_idx=[],dict()
        for token in uniq_tokens:
            self.idx_to_token.append(token)
            self.token_to_idx[token]=len(self.idx_to_token)-1#构建词汇-数字索引,一一对应
    def __len__(self):
        return len(self.token_to_idx)
    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):#获取char
        if not isinstance(indices,(list,tuple)):
            return self.idx_to_token[indices]
        return [self.idx_to_token[index] for index in indices]
def count_cropus(tokens):
    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]])
复制代码
def load_crops_time_machine(max_tokens=-1):
    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_crops_time_machine()
print(len(corpus))
print(len(vocab))
相关推荐
CIO_Alliance6 分钟前
AI基础系列(1)| 向量、矩阵、张量在AI中分别扮演什么角色?
大数据·人工智能·线性代数·ai·矩阵·企业cio联盟·企业级ai化转型
通问AI15 分钟前
人形机器人量产技术笔记:从5500台出货看规模化路径
人工智能
让你三行代码QAQ16 分钟前
AI大模型开发核心名词速览
python
无凭23 分钟前
字节Agent框架 DeerFlow 的可观测性(二):运行中的中间事件是怎样到达前端的?
人工智能
2401_8685347828 分钟前
农商行分布式网络建设
python·pygame
XLYcmy29 分钟前
小红书 算法一面 四
深度学习·llm·sft·强化学习·多模态·grpo·奖励函数
doitnow200031 分钟前
2026淘宝运营机构课程体系怎么比较?
大数据·人工智能
网渡科技1 小时前
大模型推理成本优化实战:vLLM 与 KV Cache 调优指南
人工智能
土豆12501 小时前
半年 20 万 Star 的「反 Vibe Coding」:Matt Pocock 是如何用一套 Skill 驯服 AI 编程代理的
人工智能·ai编程
yuhulkjv3351 小时前
Gemini鸿蒙版导出word格式的终极解法:AI 导出鸭如何重构AI内容落地链路
人工智能·ai·word·harmonyos·ai导出鸭