SameTime WMT 专题:Phase 0 底座骨架

"千里之行,始于足下。用最简模型跑通全流程,才能洞察系统的每一寸肌理。"

专题介绍

本专题聚焦 holds/SameTime/benchmark/wmt/ 目录下的渐进式 WMT 学习路线。 从 Phase 0 开始,逐级深入翻译模型的构建与演化。

Phase 0 是什么

Phase 0 (phase0_skeleton/) 是整套 WMT Benchmark 的实验底座骨架——用最简单的 DummyModel(复制模型)跑通数据加载、训练循环、评估评测的完整管线。

核心组件

组件 说明
数据 IWSLT14 De-En,word-level tokenizer,Vocab 统一管理
模型 DummyModel(Embedding → Linear),不做翻译,仅验证管线
评估 sacreBLEU
训练 Teacher Forcing,CrossEntropyLoss

学习要点

  1. IWSLT14 的数据格式(translation 字段)
  2. word-level vocab 的构建与 OOV 处理
  3. collate_fn 如何对齐 batch 长度
  4. BLEU 的数值范围与意义

提问环节

在深入代码之前,我想先了解你对以下几个问题的看法,以此确立学习起点:

Q1: 整体认知

你如何理解 Phase 0 在整个 WMT 渐进路线(Phase 0 → RNN → Attention → BPE → Transformer)中的定位?它只是一个调试工具,还是另有更深层的工程哲学意义?

从0开始一般都是从简单开始,一则搭建环境,二则明白任务。即是工具的熟练,也是技能的开始。

从环境来说,有以下的几个概念:

  1. 数据集,IWSLT14,数据集分为三部分 train+valid+test。其中主要语言是德语和英语。其中德语→英语(de-en) 是最受研究者欢迎的基准方向。
  2. 拿到数据该干嘛。
    1. 数据转换,xml转你需要的格式,json text等等
    2. 分词 Tokenization ,没错,token大概就是这个词的缩写,就是"我一把把把把住了"-> "我 一把 把 把 把住 了"。分词的方式有很多,最简单的就是空格分词,当然还有更复杂的BPE分词,WordPiece分词等等。
    3. 过滤,我也没看懂为啥要过滤
    4. 分集,就是训练集和验证集划分,很多技巧,比如抽样划分等等,可按需使用
    5. BPE Byte-Pair Encoding 处理,BPE是一种基于统计的分词方法,主要用于处理未登录词(OOV)问题。它通过将频率较高的子词组合成新的词来减少词汇表的大小,从而提高模型的泛化能力。HM:用颗粒度小的词来组成颗粒度大的词,这样可以减少原子量。这也告诉我们,也许本来的向量化过程,已经被向量复合过一次了
    6. 格式化,把数据转换成模型需要的输入格式,比如很多,这里就不多说了
    7. 写代码,写代码,写代码...
  3. 代码的开车步骤是什么? 这个可以看看西瓜书的原理说明,一般来说是这样的:
    1. 建立词表
      • 先读训练集合train_raw
      • 从训练集json中抽取de语和en语文本list,de是src,en是target
      • Vocab构建词表。就是量化的前一步,把文本转成数字的过程。这个过程会把文本中的每个词映射到一个唯一的整数ID上,这样模型就可以处理这些数字了。
    2. DataLoader
      • 加载数据,我的理解,就是每次不能处理全量数据,内存放不下,所以要分批加载,每次加载一部分数据进行训练,这就是batch的概念。
      • collate_fn的作用是把每个batch的数据进行处理,使得它们的长度一致,方便模型进行训练。比如说,句子长度不一样,那么就需要进行padding,collate_fn就可以帮我们完成这个工作。
      • 然后选是否shuffle,打乱数据的顺序,这样可以增加模型的泛化能力。我的理解,这里存在较大性能问题,因为句序可能影响句子含义,shuffle可能会打乱句子顺序,导致模型学习到错误的语义关系。
    3. 选模型
      • 选模型,选个简单的模型,DummyModel,Embedding层和Linear层组成的简单模型,不做翻译,仅验证管线。
      • 详细内容Q2记录
    4. 训练
      • 可参考西瓜书,训练过程一般包括前向传播、计算损失、反向传播和参数更新。前向传播是指将输入数据通过模型进行计算,得到输出结果;计算损失是指将模型的输出结果与真实标签进行比较,得到一个数值来衡量模型的性能;反向传播是指根据损失值计算梯度,并将梯度传递回模型的参数;参数更新是指根据计算得到的梯度来调整模型的参数,以使得损失值最小化。内容机器生成
      • 这里的训练过程使用了 Teacher Forcing,Teacher Forcing 是一种训练技巧,在训练过程中,模型在每个时间步都会使用真实的目标输出作为输入
    5. 验证 内容机器生成
      • 验证,验证过程一般包括评估模型的性能和调整模型的参数。评估模型的性能可以使用各种指标,如准确率、精确率、召回率、F1分数等;调整模型的参数可以使用各种优化算法,如随机梯度下降(SGD)、Adam等。
      • 这里的评估使用了 sacreBLEU,sacreBLEU 是一种用于评估机器翻译系统性能的指标,它通过比较机器翻译输出与参考翻译之间的 n-gram 重叠来计算得分。sacreBLEU 的得分范围通常在 0 到 100 之间,得分越高表示翻译质量越好。

Q2: DummyModel 的设计

DummyModel 使用 teacher forcing + next-token prediction。如果错误地将 tgt[:, :-1] 改为 tgt(即直接预测整句而非 next-token),训练会如何崩溃?这对理解自回归模型的因果结构有什么启示?如果去掉 teacher forcing 中的 shift 操作(即用 tgt 同时作为输入和输出),模型会学到什么?为什么这违背了自回归模型的自回归假设?

先学习:

  1. teacher forcing 的概念,teacher forcing 是一种训练技巧,在训练过程中,模型在每个时间步都会使用真实的目标输出作为输入,而不是使用模型之前预测的输出。这种方法可以加速训练过程,并帮助模型更快地收敛。内容机器生成

  2. 我的理解

    1. 首先,DummyModel和src语言无关,就是分析target语言而已,请注意,输入的训练数据是target语言,对实验来说,是用自己翻译成自己。
    2. 如果没有相位移动,直接原相位计算,应该和shift差别很大,自己翻译成自己,误差应该是0。因为依然是target语言到target语言的信息分布,相位差0等于没有丢失或者差异,但相位差大于0带来的差别应该很大,尤其是距离越远差距越大。

    ```shell logits = model(src, tgt[:, :-1]) # (B, T, V) loss = criterion(logits.reshape(-1, logits.size(-1)), tgt[:, :-1].reshape(-1)) [Phase 0] device=cuda building vocab... |vocab_src|=74360 |vocab_tgt|=56652 epoch=0 loss=1.483 BLEU=91.23 epoch=1 loss=0.292 BLEU=97.32 [Phase 0] done

    logits = model(src, tgt[:, :-1]) # (B, T, V) loss = criterion(logits.reshape(-1, logits.size(-1)), tgt[:, 1:].reshape(-1)) [Phase 0] device=cuda building vocab... |vocab_src|=74360 |vocab_tgt|=56652 epoch=0 loss=7.006 BLEU=1.80 epoch=1 loss=5.777 BLEU=1.88 [Phase 0] done

    logits = model(src, tgt[:, :-2]) # (B, T, V) loss = criterion(logits.reshape(-1, logits.size(-1)), tgt[:, 2:].reshape(-1)) [Phase 0] device=cuda building vocab... |vocab_src|=74360 |vocab_tgt|=56652 epoch=0 loss=7.559 BLEU=0.00 epoch=1 loss=6.696 BLEU=0.00 [Phase 0] done ``` 如上测试数据,分别是相位差0 1 2的数据结果

Q3: BLEU 的意义

Phase 0 的 BLEU 会极低(接近 0),你如何看待"明知 BLEU 很低仍要跑评估"的行为?这在工程验证中是否必要?

  1. 对于DummyModel的相位0的情况,BLEU会很高。因为DummyModel的设计就是让模型直接复制输入的文本作为输出,所以在相位0的情况下,模型的输出与目标文本完全一致,因此BLEU得分会非常高,接近100。

  2. 本质上,翻译问题是一个hash碰撞的问题。可以这样认为,一个语言模型描述世界模型的过程,是一次hash运算,将世界知识hash存储到一个矩阵中。而翻译问题,是找到一个算法,可以实现一次巧妙的hash碰撞,使得两个语言模型的hash值,获得同一个矩阵中的存储知识。一般来说,embedding的相似性搜索,就是找到hash碰撞的算法之一。但算法并不唯一,且并不高明。找到hash碰撞的算法,也就是找到一个翻译算法,使得输入和输出的hash值相同,这样就实现了翻译。

  3. 问题中说,BLEU很低,这个过程,在上述实验结果中可以看出。0相位 1相位 2相位,BLUE快速降低。我们知道0相位很高是因为自己和自己发生hash碰撞是很容易的,属于同一个语言模型。而1相位,是整个语言模型做了一次相位位移,可以认为,如果存在一个客观知识矩阵,整体距离偏移了1,那么hash碰撞的概率就会大幅降低。2相位,距离偏移了2,hash碰撞的概率就更低了。请注意,如果存在客观知识矩阵的说法并不是已知问题,这里有巨大的危险性,需要慎重对待。

  4. 工程必要性,是必须的,因为我们需要验证整个评测流程的正确性。即使我们知道BLEU得分会很低,但如果评测流程有任何错误,我们可能会得到一个不合理的BLEU得分,这会误导我们对模型性能的评估。因此,运行评测是必要的,以确保我们的评测流程是正确的,并且能够正确地反映模型的性能。内容机器生成

Q4: 数据管线

IWSLT14 的 word-level vocab 用了 min_freq=2 过滤低频词,这意味着什么?OOV 词在编码时被映射为 UNK token——在后续 Phase 中这个问题会如何被解决?

Q5: 代码结构

base/dataset.pybase/eval.pybase/utils.py 被所有 Phase 共享。这种设计模式叫什么?它给后续递增式开发带来了哪些好处与风险?


请逐一回答上述问题。你的回答将作为本专题的第一篇学习记录,在后续 Phase 中被持续引用和迭代。

May the Code be with us.