《动手学深度学习》-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))
相关推荐
MediaTea2 小时前
Python:_sentinel 命名约定
开发语言·python·sentinel
Pyeako2 小时前
opencv计算机视觉--图形透视(投影)变换&图形拼接
人工智能·python·opencv·计算机视觉·图片拼接·投影变换·图形透视变换
HZjiangzi2 小时前
怎么用三维扫描做数字孪生工厂?思看科技TrackScan-Sharp方案推荐
人工智能·科技·制造·三维扫描仪
视觉&物联智能2 小时前
【杂谈】-2026年人工智能发展趋势:智能体崛起、行业洗牌与安全挑战
人工智能·安全·llm·aigc·agi·智能体
老陈聊架构2 小时前
『AI编程工具』OpenCode 保姆级安装教程:开源 AI 编程代理入门教程
人工智能·部署·ai编程·安装·oepncode
开发者小天2 小时前
python返回随机数
开发语言·python
安全二次方security²2 小时前
CUDA C++编程指南(7.19&20)——C++语言扩展之Warp投票函数和Warp匹配函数
c++·人工智能·nvidia·cuda·投票函数·匹配函数·vote
Ftsom2 小时前
【4】kilo Task 类设计详解
人工智能·agent·ai编程·kilo
min1811234562 小时前
AI游戏开发:内容生成与智能NPC
人工智能·microsoft