Albert

Albert(A Lite Bert For Self-Supervised Learning Of Language Representations)是对 Bert 的改进,其主要思想就是用更少的参数,取得更好的效果。所以, 可以理解 Albert 是对 Bert 的改进版本,其主要的一些改进如下:

  1. 分解词嵌入矩阵
  2. 跨层参数共享

Paper:https://arxiv.org/pdf/1909.11942.pdf

1. 嵌入矩阵分解(Factorized embedding parameterization)

在 Bert 模型的词嵌入矩阵包含了大量的参数,但是在训练过程中,这些参数可能只存在稀疏的更新。我们以 transformres 库的代码实现为例,例如:Bert 模型中会构建一个 21128×768 的词嵌入矩阵,用来独立的表示输入字,每个词嵌入向量中并不包含词与词之间的关系。即:此时需要学习的参数就有 21128×768=2100万多。Albert 通过改进这个矩阵,就使得这一部分的参数量下降了 80%,但是性能只有很小的下降。

Albert 中是如何改进的?

Albert 通过降低词嵌入层的维度,从 768 改成 128,然后增加 embedding_hidden_mapping_in 线性层将 128 再映射为 768 维度。

我们看下 Bert 和 Albert 在 tramsformers 库的具体实现来看下这个变化。Bert Embedding 实现代码部分如下:

class BertEmbeddings(nn.Module):
    """Construct the embeddings from word, position and token_type embeddings."""

    def __init__(self, config):
        super().__init__()
        # config.vocab_size 21128
        # config.hidden_size 768
        self.word_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id)
        ......

Albert 的 Embedding 实现代码部分如下:

class AlbertEmbeddings(nn.Module):
    """
    Construct the embeddings from word, position and token_type embeddings.
    """

    def __init__(self, config):
        super().__init__()
        # config.vocab_size 21128
        # config.embedding_size 128
        self.word_embeddings = nn.Embedding(config.vocab_size, config.embedding_size, padding_idx=config.pad_token_id)
        ......

Albert 的 Encoder 的实现代码中,将传入进来的 128 维度的词向量,通过 embedding_hidden_mapping_in 进行了维度变换,如下代码所示:

self.embedding_hidden_mapping_in = nn.Linear(config.embedding_size, config.hidden_size)
hidden_states = self.embedding_hidden_mapping_in(hidden_states)

2. 跨层参数共享(Cross-layer parameter sharing)

Paper 中提到共享参数的方法很多,比如只共享 FF 层的参数,或者只共享注意力层的参数等等,Albert 默认是跨层共享所有参数,即:注意力、FF 等整个层的参数。

3. SOP 预训练任务(Sentence Order Prediction)

Bert 模型中使用 NSP 预训练任务,Paper 中认为该任务缺乏难度,对模型性能没有更好的提升。所以将其改为 SOP 预训练任务。

Bert NSP 在训练前,从语料中构建输入句子 A,50% 从使用原始语料中选择连续的下一个句子 B 组成输入正样本,标记为 IsNext。 50% 从语料中随机挑选一些不挨着的句子 B 组成负样本,标记为 NotNext。最终,使用 [CLS] 对应的输出计算概率句子B是句子A 的 IsNext 和 NotNext 的概率。

Albert SOP 在训练前,也是从语料中采样连续的两个句子 A 和 B 作为正样本,预测 B 是否是 A 的下一句。但是负样本则是将句子 A 和 B 交换顺序,即:预测 A 是不是 B 的下一句。

4. N-gram Mask

Bert 中对字进行随机掩码,对被掩码的字之间做了独立性假设。而 Albert 则使用 n-gram mask,掩码一个相关的字词,避免了这个独立性假设问题。Albert 中 n-gram 最大值为 3,即:随机从 1-gram、2-gram、3-gram 中随机选择,选择概率为:

因为Bert 没有出现过拟合的现象,所以,Albert 去掉 Dropout,在 Albert 默认的配置参数中,dropout 这一项都是 0,如下:

AlbertConfig {
  "attention_probs_dropout_prob": 0,
  "bos_token_id": 2,
  "classifier_dropout_prob": 0.1,
  "embedding_size": 128,
  "eos_token_id": 3,
  "hidden_act": "gelu_new",
  "hidden_dropout_prob": 0,
  "hidden_size": 4096,
  "initializer_range": 0.02,
  "inner_group_num": 1,
  "intermediate_size": 16384,
  "layer_norm_eps": 1e-12,
  "max_position_embeddings": 512,
  "model_type": "albert",
  "num_attention_heads": 64,
  "num_hidden_groups": 1,
  "num_hidden_layers": 12,
  "pad_token_id": 0,
  "position_embedding_type": "absolute",
  "transformers_version": "4.22.2",
  "type_vocab_size": 2,
  "vocab_size": 30000
}

其实,从 Albert 干的这些事,也大体了解其就是尽量的给 Bert 瘦身,减少参数量、减少不必要的计算。所以,也可以把 Albert 理解为一个性能还不错,但是轻量级的 Bert 模型。

  • 1-gram:6/11
  • 2-gram:3/11
  • 3-gram:2/11

1-gram 概率最大,3-gram 概率最低。

AlbertForSequenceClassification.from_pretrained('model/albert_chinese_tiny')
未经允许不得转载:一亩三分地 » Albert