《动手学深度学习》-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))
相关推荐
AI人工智能+12 小时前
一种以深度学习与计算机视觉技术为核心的表格识别系统,实现了结构化、半结构化表格的精准文字提取、布局解析与版面完整还原
深度学习·计算机视觉·ocr·表格识别
unicrom_深圳市由你创科技12 小时前
做虚拟示波器这种实时波形显示的上位机,用什么语言?
c++·python·c#
小敬爱吃饭12 小时前
Ragflow Docker部署及问题解决方案(界面为Welcome to nginx,ragflow上传文件失败,Docker中的ragflow-cpu-1一直重启)
人工智能·python·nginx·docker·语言模型·容器·数据挖掘
宸津-代码粉碎机12 小时前
Spring Boot 4.0虚拟线程实战调优技巧,最大化发挥并发优势
java·人工智能·spring boot·后端·python
老兵发新帖12 小时前
Hermes:比openclaw更好用的智能体?
人工智能
俊哥V12 小时前
每日 AI 研究简报 · 2026-04-09
人工智能·ai
MicrosoftReactor12 小时前
技术速递|使用 Copilot SDK 构建 AI 驱动的 GitHub Issue 分类系统
人工智能·github·copilot
知行合一。。。12 小时前
Python--04--数据容器(集合)
python
AI成长日志12 小时前
【GitHub开源项目专栏】AI推理优化框架深度解析(上):vLLM架构设计与核心实现
人工智能·开源·github
数智前线12 小时前
三次“进窄门”,MiniMax走向AGI深处
人工智能