美文网首页自然语言处理
T5(Transfer Text-to-Text Transfo

T5(Transfer Text-to-Text Transfo

作者: 晓柒NLP与药物设计 | 来源:发表于2022-06-12 06:48 被阅读0次

    论文链接:https://arxiv.org/abs/1910.10683

    代码链接:https://github.com/google-research/text-to-text-transfer-transformer

    导言:一个统一框架,靠着大力出奇迹,将所有 NLP 任务都转化成 Text-to-Text(文本到文本)任务

    T5多任务概述图

    比如英德翻译任务,只需将训练数据集的输入部分前加上translate English to German即可。假设需要翻译That is good,那么先转换成translate English to German:That is good.输入模型,之后就可以直接输出德语翻译Das ist gut.。对于需要输出连续值的STS(文本语义相似度任务),也是直接输出文本。通过这样的方式就能将NLP任务都转换成Text-to-Text形式,也就可以用同样的模型,同样的损失函数,同样的训练过程,同样的解码过程来完成所有NLP任务


    1.1 模型结构

    T5模型采用Transformer的encoder-decoder结构,GPT采用的是Transformer的decoder结构,BERT采用的是Transformer的encoder结构
    T5模型图

    T5模型和原始的Transformer结构基本一致,具体的做了如下几点改动:

    • 编码器和解码器仍保留在模型中。编码器和解码器层成为块(block),子层为包含自注意层和前馈网络的子组件(subcomponent)。像乐高一样,可以组装块和子组件来建立模型,例如图2中的ENCODER #1

    • Layer normalization层归一化应用于每个子组件的输入,使用一个简化版本的Layer normalization,其中激活只是重新调整,没有附加偏差被应用

      • 常规的Layer\_Normalization的计算公式为:y=\frac{x-\mu}{\sqrt{Var(x)+\varepsilon}},这里\mu为期望,Var(x)+\varepsilon为方差。

      • 而此处的Layer\_Normalization的计算公式为y=weight*\frac{x}{\sqrt{Var(x)+\varepsilon}},这里对应的weight参数初始化的时候全为1

    • Layer normalization之后,将一个residual的skip connection将每个子组件的输入添加到其输出中

    • 此处使用了简化的相对位置embedding,即每个位置对应一个数值而不是向量,原来的Transformer采用sin/cos习得position embeddings,而T5将(key和query)相对位置的数值加在attention softmax之前的logits上,每个head的有自己的position embeddings,所有的层共享一套position embeddings,每一层都计算一次,让模型对位置更加敏感

    1.2 数据来源:Colossal Clean Crawled Corpus (C4)

    T5作者选取了Common Crawl数据集,这个数据集每周大约爬取20TB的WEB数据。虽然数据集已经抽取了文本,但实际上并不干净,里面还包含了很多非自然语言的东西,比如错误消息、菜单、重复文本,于是对数据进行了比较细致的处理:
    • 只取结尾有标点的句子

    • 去掉包含脏话的网页

    • 有很多页面包含"enable Javascript"的提示,去掉包含Javascript的句子

    • "lorem ipsum"是一个测试网页排版的拉丁文,去掉包含这个占位符的网页

    • 去掉包含代码片段的网页

    • 以三句为一个片段进行去重

    • 去掉非英文的网页

    经过上述处理后最终生成了750GB的数据集C4,并且在TensorFlow Datasets进行开源

    1.3 任务以及训练格式

    1.3.1 输入输出模型

    • 输入:参考GPT2,直接把任务名称当作prefix和输入拼在一起,例如:"translate English to German: That is good."

    • 输出:分类任务(如推断),需要输出"entailment", "neutral", "contradiction"这三种文本,否则都算错;回归任务输出str(序列)类型的浮点数。还有其他任务,可前往附录A参考

    • 这里每个任务前缀的选择可以认为是一种超参,即通过人为设计前缀样式。作者发现不同的前缀对模型的影响有限,因此没有做大量实验比较选择不同前缀的结果。

    1.3.2 预训练过程

    之后是对预训练目标的大范围探索,具体做了哪些实验,下面这张图就能一目了然

    预训练模型的预训练范式总览

    总共从四个层面来进行比较:

    • 第一个方面,高层次方法(自监督的预训练方法)对比,总共三种方法:

      • 语言模型式,就是 GPT-2 那种方式,从左到右预测

      • BERT-style式,就是像BERT一样将一部分给破坏掉,然后还原出来,其效果最好

      • Deshuffling(顺序还原)式,就是将文本打乱,然后还原出来

    • 第二方面,对文本一部分进行破坏时的策略,也分三种方法:

      • Mask法,如现在大多模型的做法,将被破坏token换成特殊符如[M]

      • Replace span法,可以当作是把上面 Mask 法中相邻 [M] 都合成了一个特殊符,每一小段替换一个特殊符,提高计算效率,其效果最好

      • Drop法,没有替换操作,直接随机丢弃一些字符

    • 第三方面,对文本进行多大程度的破坏,挑了 4 个值:10%,15%,25%,50%,最后发现 BERT 的 15%效果最好

    • 第四方面,Replace Span需要决定对大概多长的小段进行破坏,于是对不同长度进行探索:2,3,5,10这四个值,最后发现3效果最好

    预训练模式输入输出样式举例

    1.3.3 模型参数量

    最后就是结合上面所有实验结果,训练了不同规模几个模型,由小到大:

    T5模型参数量表

    1.3.4 训练结论

    • Architectures

      • 原始的Transformer结构表现最好

      • encoder-decoder结构和BERT、GPT的计算量差不多

      • 共享encoderdecoder的参数没有使效果差太多

    • Unsupervised objectives

      • 自编码和自回归的效果差不多

      • 推荐选择更短目标序列的目标函数,提高计算效率

    • Datasets

      • 在领域内进行无监督训练可以提升一些任务的效果,但在一个小领域数据上重复训练会降低效果

      • Large、diverse的数据集效果最好

    • Training strategies

      • 精调时更新所有参数 > 更新部分参数

      • 在多个任务上预训练之后微调 = 无监督预训练

    • Scaling

      • 在小模型上训练更多数据 < 用少量步数训练更大的模型

      • 从一个预训练模型上微调多个模型后集成 < 分开预训练+微调后集成

    在本文中所有的实验,作者列出了一个给定实验的压缩结果的表格

    2.1 T5模型的使用

    • 首先安装需要的包:
    pip install transformers==4.2.0
    pip install sentencepiece==0.1.94
    
    • 下载并加载模型和分词器:
    model = T5ForConditionalGeneration.from_pretrained('t5-large')
    tokenizer = T5Tokenizer.from_pretrained('t5-large')</pre>
    
    • T5模型参数打印:
    # print(model.config)
    T5Config {
      "_name_or_path": "t5-large",
      "architectures": [
        "T5WithLMHeadModel"
      ],
      "d_ff": 4096,                      # 每个T5Block中feed forward layer的size
      "d_kv": 64,                        # 每个attention head的key、query、value的size。d_kv必须等于d_model/num_heads
      "d_model": 1024,                   # 每个encoder layers和pooler layer的大小
      "decoder_start_token_id": 0,       # 模型根据标签自动创建decoder_start_token_id,方法是将标签向右移动一个位置,并加上前缀
      "dropout_rate": 0.1,               # 所有dropout layers的比例
      "eos_token_id": 1,                 # eos_token的id
      "feed_forward_proj": "relu",       # 所有要使用的feed_forward类型
      "initializer_factor": 1.0,         # 初始化所有权重矩阵的系数
      "is_encoder_decoder": true,        # 同时使用encoder与decoder
      "layer_norm_epsilon": 1e-06,       # layer_norm使用的epsilon
      "model_type": "t5",                # 模型类型
      "n_positions": 512,                # positions数量
      "num_decoder_layers": 24,          # decoder中的隐藏层数。如果未设置,将使用与num_layers相同的值
      "num_heads": 16,                   # 每个attention layer的attention heads
      "num_layers": 24,                  # 每个encoder中的hidden layers
      "relative_attention_max_distance": 128, # bucket separation较长序列的最大距离
      "relative_attention_num_buckets": 32,   # 每个attention layers要使用的bucket数
      "task_specific_params": {
        "summarization": {
          "early_stopping": true,
          "length_penalty": 2.0,
          "max_length": 200,
          "min_length": 30,
          "no_repeat_ngram_size": 3,
          "num_beams": 4,
          "prefix": "summarize: "
        },
        "translation_en_to_de": {
          "early_stopping": true,
          "max_length": 300,
          "num_beams": 4,
          "prefix": "translate English to German: "
        },
        "translation_en_to_fr": {
          "early_stopping": true,
          "max_length": 300,
          "num_beams": 4,
          "prefix": "translate English to French: "
        },
        "translation_en_to_ro": {
          "early_stopping": true,
          "max_length": 300,
          "num_beams": 4,
          "prefix": "translate English to Romanian: "
        }
      },
      "transformers_version": "4.19.2",  # tranformers包支持版本
      "use_cache": true,                 # 模型是否应返回最后一个key/values attentions
      "vocab_size": 32128                # T5模型的词汇表
    }
    
    • T5模型结构打印(第N个block):
    T5Block(
        (layer): ModuleList(
          (0): T5LayerSelfAttention(
            (SelfAttention): T5Attention(
              (q): Linear(in_features=1024, out_features=1024, bias=False)
              (k): Linear(in_features=1024, out_features=1024, bias=False)
              (v): Linear(in_features=1024, out_features=1024, bias=False)
              (o): Linear(in_features=1024, out_features=1024, bias=False)
            )
            (layer_norm): T5LayerNorm()
            (dropout): Dropout(p=0.1, inplace=False)
          )
          (1): T5LayerCrossAttention(
            (EncDecAttention): T5Attention(
              (q): Linear(in_features=1024, out_features=1024, bias=False)
              (k): Linear(in_features=1024, out_features=1024, bias=False)
              (v): Linear(in_features=1024, out_features=1024, bias=False)
              (o): Linear(in_features=1024, out_features=1024, bias=False)
            )
            (layer_norm): T5LayerNorm()
            (dropout): Dropout(p=0.1, inplace=False)
          )
          (2): T5LayerFF(
            (DenseReluDense): T5DenseReluDense(
              (wi): Linear(in_features=1024, out_features=4096, bias=False)
              (wo): Linear(in_features=4096, out_features=1024, bias=False)
              (dropout): Dropout(p=0.1, inplace=False)
              (relu_act): ReLU()
            )
            (layer_norm): T5LayerNorm()
            (dropout): Dropout(p=0.1, inplace=False)
          )
        )
    )
    
    • 使用T5模型并创建prefix实现摘要任务:
    def summarize(text, max_length):
      '''
      text: 要生成摘要的文本
      max_length: 摘要的最大长度
      '''
      # 去掉多余的空格和换行符
      preprocess_text = text.strip().replace('\n','')
      # 准备前缀+文本
      t5_prepared_text = 'summarize: ' + preprocess_text
      print("Preprocessed and prepared text: \n", t5_prepared_text)
      # 分词
      tokenized_text = tokenizer.encode(t5_prepared_text, return_tensors="pt").to(device)
      # 进行文本摘要
      summary_ids = model.generate(tokenized_text,
                      num_beams=4,
                      no_repeat_ngram_size=2,
                      min_length=30,
                      max_length=max_length,
                      early_stopping=True)
      # 将id转换为输出 summary_ids.shape = [1, 50]
      output = tokenizer.decode(summary_ids[0], skip_special_tokens=True)
      return output
    

    相关文章

      网友评论

        本文标题:T5(Transfer Text-to-Text Transfo

        本文链接:https://www.haomeiwen.com/subject/uocgmrtx.html