
文档教程人工智能深度学习NLP计算机视觉强化学习【免费下载链接】d2l-enInteractive deep learning book with multi-framework code, math, and discussions. Adopted at 500 universities from 70 countries including Stanford, MIT, Harvard, and Cambridge.项目地址https://gitcode.com/gh_mirrors/d2/d2l-en点击查看免费下载机器翻译Machine Translation是推动现代循环神经网络RNN与序列到序列seq2seq模型走向主流的关键应用模型接收一种语言源语言的句子输出另一种语言目标语言的对应翻译。本篇文章以《动手学深度学习》d2l-en仓库中 chapter_recurrent-modern/machine-translation-and-dataset.md 为核心完整讲解从英法双语平行语料Tatoeba 项目数据的下载、清洗、分词到定长化截断与填充、双语文表构建、小批量加载的完整数据流水线。读完本文你将掌握 d2l-en 中MTFraEng数据集类的内部实现原理并能在 PyTorch、MXNet、TensorFlow 与 JAX 四个框架下复现同样的数据准备流程为后续 encoder-decoder 与注意力机制章节的模型训练打好数据基础。机器翻译从不对齐序列到 seq2seq 问题机器翻译是统计机器学习领域的经典任务模型被给定一种语言中的一句话必须预测另一种语言中对应的句子。这里有两个与语言模型见 chapter_recurrent-neural-networks/language-model.md截然不同的难点序列长度不同源句子与目标句子的长度通常不一致单词顺序不对齐由于两种语言语法结构不同源句中的词在译文中往往不按相同顺序出现。许多问题都具有这种在两个不对齐序列之间映射的性质例如从对话提示prompt到回复、从问题到答案的映射。这类问题统称为序列到序列sequence-to-sequence简称 seq2seq问题它是本章剩余部分以及注意力机制与 Transformer 章节见 chapter_attention-mechanisms-and-transformers/index.md的核心研究对象。历史上统计机器翻译方法曾长期流行后来基于神经网络的方法被统称为神经机器翻译Neural Machine Translation并催生了现代 RNN 的广泛应用。在 d2l-en 中本节的定位是引入机器翻译问题本身并构建一个贯穿后续若干章节encoder-decoder、GRU/LSTM 的 seq2seq 实现、注意力机制等的英法双语数据集。与语言建模中每个样本只有一条文本序列不同机器翻译的每个样本包含两条独立的文本序列一条源语言序列与一条目标语言序列翻译结果。下载与预处理数据集MTFraEng 类d2l-en 使用一个公开的英法双语平行语料数据来自Tatoeba 项目manythings.org/anki 提供的双语例句对。数据集中每一行是一个由制表符tab分隔的二元组英文文本序列源与对应的法语文本序列目标。需要注意每条文本序列可以只是一句话也可以是包含多句的段落。下载逻辑封装在MTFraEng类的_download方法中它继承自d2l.DataModule基类定义于 d2l/torch.py其他三个框架的实现位于d2l/mxnet.py、d2l/tensorflow.py、d2l/jax.py。实现如下%%tab all class MTFraEng(d2l.DataModule): #save The English-French dataset. def _download(self): d2l.extract(d2l.download( d2l.DATA_URLfra-eng.zip, self.root, 94646ad1522d915e7b0f9296181140edcf86a4f5)) with open(self.root /fra-eng/fra.txt, encodingutf-8) as f: return f.read()这里使用了 d2l 工具函数d2l.download与d2l.extract定义于 d2l/torch.pyd2l.download(url, folder, sha1_hash)从d2l.DATA_URL值为http://d2l-data.s3-accelerate.amazonaws.com/见 d2l/torch.py下载fra-eng.zip到数据根目录DataModule默认root../data并传入文件fra.txt的SHA-1 哈希值94646ad1522d915e7b0f9296181140edcf86a4f5做完整性校验。若本地已存在且哈希匹配则直接复用缓存文件不会重复下载。d2l.extract(filename)将 zip 压缩包解压到数据目录得到fra-eng/fra.txt文件。最后以 UTF-8 编码读取fra.txt全部内容并作为字符串返回。拿到原始文本后需要做若干预处理步骤封装在_preprocess方法中%%tab all d2l.add_to_class(MTFraEng) #save def _preprocess(self, text): # Replace non-breaking space with space text text.replace(\u202f, ).replace(\xa0, ) # Insert space between words and punctuation marks no_space lambda char, prev_char: char in ,.!? and prev_char ! out [ char if i 0 and no_space(char, text[i - 1]) else char for i, char in enumerate(text.lower())] return .join(out)具体来说该预处理完成三件事统一空白字符将窄不换行空格\u202f与不换行空格\xa0都替换为普通空格避免分词时产生异常 token统一大小写将整段文本转为小写缩小词表规模在单词与标点之间插入空格借助no_space判定——当当前字符属于逗号、句点、感叹号、问号,.!?且前一字符不是空格时在该标点前插入一个空格使标点符号独立成词方便后续按空格分词。分词Tokenization词级 token 与 标记与语言建模章节使用的字符级分词不同机器翻译在这里采用词级分词当今最先进的模型会使用更复杂的分词技术如 BPE、WordPiece 等本节从简单入手。_tokenize方法对前max_examples个文本序列对进行分词其中每个 token 要么是一个单词要么是一个标点符号%%tab all d2l.add_to_class(MTFraEng) #save def _tokenize(self, text, max_examplesNone): src, tgt [], [] for i, line in enumerate(text.split(\n)): if max_examples and i max_examples: break parts line.split(\t) if len(parts) 2: # Skip empty tokens src.append([t for t in f{parts[0]} eos.split( ) if t]) tgt.append([t for t in f{parts[1]} eos.split( ) if t]) return src, tgt该方法的要点逐行读取以\t切分源与目标只有恰好切出 2 个部分的行才被采纳跳过异常行在每条序列末尾追加特殊的eosend-of-sequencetoken用于标记序列结束。当模型逐 token 生成序列时一旦生成eos即可认为输出序列已经完成按空格切分并过滤空串得到 token 列表返回两个 token 列表的列表src[i]是第 i 条源语言英文序列的 token 列表tgt[i]是第 i 条目标语言法文序列的 token 列表。调用data._tokenize(text)后可以用直方图直观观察两条序列的长度分布。仓库提供的辅助函数show_list_len_pair_hist完整定义见 d2l/torch.py以斜线阴影区分源与目标序列的长度直方图。在该英法数据集中大多数文本序列的 token 数少于 20 个因此后续默认num_steps9的定长设置是合理的。加载定长序列截断、填充与三组特殊 token语言建模中每条样本序列的长度由参数num_steps时间步/token 数固定而机器翻译中同一小批量minibatch里的源序列与目标序列长度参差不齐。为了计算效率可以仍然在一个小批量中同时处理多条序列手段是截断truncation与填充padding若某条序列的 token 数少于num_steps则在末尾不断追加特殊padpaddingtoken直到长度达到num_steps若某条序列的 token 数多于num_steps则只保留前num_steps个 token丢弃其余部分。这样每条序列长度一致可以组成形状相同的小批量张量。此外还需要记录剔除填充 token 后的源序列真实长度src_valid_len这一信息将在后续某些模型如注意力机制中的有效长度掩码中用到。由于机器翻译数据集由语言对组成需要分别为源语言与目标语言构建两套词表。词级分词下词表规模会显著大于字符级分词为了缓解这一问题这里将出现次数少于 2 次的稀有 token 统一映射为未知 tokenunk。关于序列的起止标记这里出现了三组特殊 token各有分工特殊 token含义用途bosbeginning-of-sequence作为解码器预测目标序列时的第一个输入 tokeneosend-of-sequence追加到每条序列末尾标记序列结束padpadding填充短序列到统一长度num_stepsunkunknown替代出现次数 2 的稀有 token控制词表规模上述逻辑全部封装在_build_arrays方法中完整实现见 d2l/torch.py%%tab all d2l.add_to_class(MTFraEng) #save def __init__(self, batch_size, num_steps9, num_train512, num_val128): super(MTFraEng, self).__init__() self.save_hyperparameters() self.arrays, self.src_vocab, self.tgt_vocab self._build_arrays( self._download())%%tab all d2l.add_to_class(MTFraEng) #save def _build_arrays(self, raw_text, src_vocabNone, tgt_vocabNone): def _build_array(sentences, vocab, is_tgtFalse): pad_or_trim lambda seq, t: ( seq[:t] if len(seq) t else seq [pad] * (t - len(seq))) sentences [pad_or_trim(s, self.num_steps) for s in sentences] if is_tgt: sentences [[bos] s for s in sentences] if vocab is None: vocab d2l.Vocab(sentences, min_freq2) array d2l.tensor([vocab[s] for s in sentences]) valid_len d2l.reduce_sum( d2l.astype(array ! vocab[pad], d2l.int32), 1) return array, vocab, valid_len src, tgt self._tokenize(self._preprocess(raw_text), self.num_train self.num_val) src_array, src_vocab, src_valid_len _build_array(src, src_vocab) tgt_array, tgt_vocab, _ _build_array(tgt, tgt_vocab, True) return ((src_array, tgt_array[:,:-1], src_valid_len, tgt_array[:,1:]), src_vocab, tgt_vocab)构造函数的关键参数与默认值batch_size批量大小必填num_steps9每条序列统一后的长度同时充当截断与填充的基准num_train512训练集样本对数num_val128验证集样本对数。_build_arrays内部_build_array的执行流程值得逐行拆解截断/填充pad_or_trim对每条序列做定长化若序列更长则截取前num_steps个若更短则补pad至num_steps目标序列前置bos当is_tgtTrue时在每条目标序列最前面拼接bostoken作为解码器的起始输入 token对应 chapter_recurrent-modern/encoder-decoder.md 与 seq2seq 章节中解码器输出标签 token等于解码器输入目标 token右移一个 token的训练范式详见 chapter_recurrent-modern/seq2seq.md构建词表若未传入已有词表则用d2l.Vocab(sentences, min_freq2)新建——词表类定义于 d2l/torch.py其构造逻辑是统计 token 频率并按降序排列保留频率 ≥min_freq的 token并预留unk与保留 token 的索引min_freq2即上面所说的出现次数少于 2 次的 token 归为unk张量化把每条 token 序列映射为索引序列堆叠成形状为样本数,num_steps的整型张量计算有效长度valid_len d2l.reduce_sum(d2l.astype(array ! vocab[pad], d2l.int32), 1)——先将非pad位置转为 1/0再沿序列维度求和reduce_sum与astype在 d2l 中是sum与type的别名见 d2l/torch.py得到每条序列剔除填充后的真实长度。_build_arrays最终返回四元组(src_array, tgt_array[:, :-1], src_valid_len, tgt_array[:, 1:])这正是后续 seq2seq 训练时一个样本的四个组成部分source源语言序列英文decoder input目标序列去除最后一个 token去掉eos并已前置bos作为解码器的输入source length excluding pad剔除填充后的源序列有效长度label目标序列去除第一个 token去掉bos作为解码器要预测的标签与 decoder input 正好错位一个 token。读取数据集与自定义构建定义get_dataloader方法即可获得数据迭代器%%tab all d2l.add_to_class(MTFraEng) #save def get_dataloader(self, train): idx slice(0, self.num_train) if train else slice(self.num_train, None) return self.get_tensorloader(self.arrays, train, idx)trainTrue时取前num_train512条trainFalse时取从num_train开始的后续num_val128条即第 512 条到第 639 条self.get_tensorloader继承自d2l.DataModule见 d2l/torch.py将四元组张量切片封装为TensorDataset并交给框架的DataLoader训练集启用shuffleTrue打乱顺序验证集不打乱。读取第一个小批量batch_size3即可观察四个分量的实际形态与语义%%tab all data MTFraEng(batch_size3) src, tgt, src_valid_len, label next(iter(data.train_dataloader())) print(source:, d2l.astype(src, d2l.int32)) print(decoder input:, d2l.astype(tgt, d2l.int32)) print(source len excluding pad:, d2l.astype(src_valid_len, d2l.int32)) print(label:, d2l.astype(label, d2l.int32))最后build方法提供了一条便捷的自定义测试通路把任意手写的源/目标句子对拼回 tab 分隔的原始文本复用已构建好的两套词表走一遍_build_arrays从而方便地在后续章节中快速构造单条样本进行调试%%tab all d2l.add_to_class(MTFraEng) #save def build(self, src_sentences, tgt_sentences): raw_text \n.join([src \t tgt for src, tgt in zip( src_sentences, tgt_sentences)]) arrays, _, _ self._build_arrays( raw_text, self.src_vocab, self.tgt_vocab) return arrays例如用data.build([hi .], [salut .])构建单条样本再借助词表的to_tokens方法d2l/torch.py把索引张量还原为 token 字符串可以直观检查bos前置、定长填充等处理是否正确——source序列会被处理为hi . eos pad ...target则为bos salut . eos pad ...。小结机器翻译是指自动将源语言的文本序列映射为目标语言合理翻译序列的任务。词级分词下词表规模显著大于字符级分词但序列长度会短得多为缓解大词表问题可以把稀有 token 统一视为unk未知 token本数据集阈值为出现次数 2即min_freq2通过截断与填充所有文本序列被统一到num_steps长度从而可以按相同形状的小批量加载src_valid_len记录了剔除pad后的源序列真实长度供后续模型使用现代实现通常会按相似长度对序列分桶bucketing避免在大量填充上浪费计算本节为教学清晰性采用了统一长度方案MTFraEng类在 d2l-en 四个框架后端d2l/mxnet.py、d2l/torch.py、d2l/tensorflow.py、d2l/jax.py中均有等价的save实现本文以 d2l/torch.py 为准展开其余框架可直接对照阅读。思考与练习修改_tokenize中的max_examples参数如取 64、512、2048 等不同值观察源语言与目标语言词表规模如何随之变化这说明了什么中文、日文等语言的文本没有空格这类词边界指示符。对于这类语言词级分词是否仍是好选择为什么请结合unk机制与分词难度展开讨论。赞分享文档教程人工智能深度学习NLP计算机视觉强化学习【免费下载链接】d2l-enInteractive deep learning book with multi-framework code, math, and discussions. Adopted at 500 universities from 70 countries including Stanford, MIT, Harvard, and Cambridge.项目地址https://gitcode.com/gh_mirrors/d2/d2l-en点击查看免费下载相关推荐MOSS-TTS 技术报告核心思想梳理arXiv 论文训练策略与数据配方完整指南MOSS TTS 技术报告核心思想梳理arXiv 论文训练策略与数据配方完整指南 MOSS TTS 是由 OpenMOSS 团队开源的语音与声音生成模型家族人工智能深度学习机器学习教程PaddleNLP 机器翻译数据准备实战WMT14 平行语料下载、BPE 预处理与词表构建全流程PaddleNLP 机器翻译数据准备实战WMT14 平行语料下载、BPE 预处理与词表构建全流程 PaddleNLP 在 slm/examples/machi人工智能大模型预训练微调LoRARLHF强化学习分布式训练模型推理服务推理引擎模型量化模型压缩本地部署NLP如何3分钟构建AI视频生成系统面向新手的完整实战指南如何3分钟构建AI视频生成系统面向新手的完整实战指南 你是否曾为制作视频内容而烦恼写脚本、录音、找配图、剪辑合成……传统视频制作流程复杂耗时让许多内容创作AI 应用媒体生成语音上一篇终极指南如何永久防止微信、QQ、TIM消息被撤回开源工具RevokeMsgPatcher详细教程下一篇三步搞定微信聊天记录永久保存WeChatMsg让你的珍贵对话不再丢失创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考