tensor2tensor

最近想做翻译,现在的好多开源框架师兄都说不错,因为想做的中英翻译发现fairseq没有直接支持,而t2t是直接可以中英翻译的,所以学习一波这个框架。

  • Trainer:是training , evaluationinference的入口,更改模型是使用--model参数,更改数据集是使用--problem参数,更改超参是使用--hparams_set参数,特定的超参数可以使用--hparams进行替换,--schedule用于控制是分布式训练或者评估.
  • 如果要添加新的数据集那么就在Problem的子类中使用@registry.register_problem注册这个数据集。
  • 一个小例子:
# Test the quick-start on a Workspace's Terminal with this command
t2t-trainer \
  --generate_data \
  --data_dir=./t2t_data \
  --output_dir=./t2t_train/mnist \
  --problem=image_mnist \
  --model=shake_shake \
  --hparams_set=shake_shake_quick \
  --train_steps=1000 \
  --eval_steps=100

数据处理

假如我们有一个新的任务和新的数据集,新任务是给一句诗,然后再给出一些候选的诗句,接着预测出诗句的下一句是什么,这可以看做是一个文本分类任务,因此我们可以继承两个类一个是text classification tasks,一个是Text2TextProblem这两个类中有很多处理文本的方法和文本分类的方法。

  • 首先创造一个新的类,然后注册这个类,这样这个类就可以在命令行被选用。
import re

from gutenberg import acquire
from gutenberg import cleanup

from tensor2tensor.data_generators import problem
from tensor2tensor.data_generators import text_problems
from tensor2tensor.utils import registry

@registry.register_problem
class PoetryLines(text_problems.Text2TextProblem):
  """Predict next line of poetry from the last line. From Gutenberg texts."""
  • Text2TextProble中有三种词汇表:第一种是token级别的就是最普通的,第二种的character级别的,第三种的subword级别的,第三种不像第一种有OOV问题,因此是一个比理想的词汇表形式,通过设置Text2TextProblem.vocab_type,其中最后一种词表形式是默认的形式。指定我们近似有8ksubwords
  @property
  def approx_vocab_size(self):
    return 2**13  # ~8k
  • 一个方法决定要不要切分training seteval set,一个方法决定切分的比例。

By setting is_generate_per_split=False, the generate_samples method will only be called once and the data will automatically be split across training and evaluation data for us. This is useful because for our dataset we don’t have pre-existing “training” and “evaluation” sets. If we did, we’d set is_generate_per_split=True so that generate_samples was called once per data split.

  @property
  def is_generate_per_split(self):
    # generate_data will shard the data into TRAIN and EVAL for us.
    return False

  @property
  def dataset_splits(self):
    """Splits of data to produce and number of output shards for each."""
    # 10% evaluation data
    return [{
        "split": problem.DatasetSplit.TRAIN,
        "shards": 9,
    }, {
        "split": problem.DatasetSplit.EVAL,
        "shards": 1,
    }]
  • generate_samples:是生成训练数据对的大部分代码都在这个函数里面,训练数据对是(inputs,targets),类似于翻译中的源语言和目标语言。如果是一些需要下载东西的任务,那么被下载的东西存放在tmp_dir文件夹下面,如果是想用自己的词典那么就把自己的词表放在data_dir文件夹下面。
  def generate_samples(self, data_dir, tmp_dir, dataset_split):
    del data_dir
    del tmp_dir
    del dataset_split

    books = [
        # bookid, skip N lines
        (19221, 223),
        (15553, 522),
    ]

    for (book_id, toskip) in books:
      text = cleanup.strip_headers(acquire.load_etext(book_id)).strip()
      lines = text.split("\n")[toskip:]
      prev_line = None
      ex_count = 0
      for line in lines:
        # Any line that is all upper case is a title or author name
        if not line or line.upper() == line:
          prev_line = None
          continue

        line = re.sub("[^a-z]+", " ", line.strip().lower())
        if prev_line and line:
          yield {
              "inputs": prev_line,
              "targets": line,
          }
          ex_count += 1
        prev_line = line
  • 产生数据:需要创建一个文件夹叫USR_DIR,这个文件夹里面有个__init__.py,然后在这个文件里面from . import poetry_linespoetry_lines.py是在这个文件夹下面有PoetryLines这个类的文件。
USR_DIR=...
PROBLEM=poetry_lines
DATA_DIR=$HOME/t2t_data
TMP_DIR=/tmp/t2t_datagen
mkdir -p $DATA_DIR $TMP_DIR

t2t-datagen \
  --t2t_usr_dir=$USR_DIR \
  --data_dir=$DATA_DIR \
  --tmp_dir=$TMP_DIR \
  --problem=$PROBLEM
  • train的话命令在下面:只要指定了--problem=poetry_lines--t2t_usr_dir=$USR_DIR即可。
t2t-trainer \
  --data_dir=$DATA_DIR \
  --problem=$PROBLEM \
  --model=$MODEL \
  --hparams_set=$HPARAMS \
  --output_dir=$TRAIN_DIR

T2T教程

Overview

  • t2t的设计是被用于方便的执行命令行程序的。
  • 只用定义相关的子类就可以方便的使用的数据集超参,或者自己编写的简单模型框架。
  • t2t不仅可以使用命令行,也可以使用Python的脚本
t2t-datagen \
  --data_dir=$DATA_DIR \
  --tmp_dir=$TMP_DIR \
  --problem=$PROBLEM
from tensor2tensor import problems

PROBLEM = '{Tensor2Tensor_problem_name}
TMP_DIR = '{/Tmp_Dir_Path}' # Where data files from internet stored
DATA_DIR = '{/Data_Dir_Path}' # Where pre-prcessed data is stored

# Init problem T2T object the generated training data
t2t_problem = problems.problem(PROBLEM)
t2t_problem.generate_data(DATA_DIR, TMP_DIR) 
  • 首先下载了tensor2tensor源码之后先创建几个我们要用到的文件夹
mkdir -p t2t_data t2t_datagen t2t_train t2t_output
  • 生成训练数据
t2t-datagen --data_dir=t2t_data --tmp_dir=t2t_datagen/ \
--problem=translate_envi_iwslt32k
  • 训练
t2t-trainer --data_dir=t2t_data --problem=translate_envi_iwslt32k \
--model=transformer --hparams_set=transformer_base --output_dir=t2t_output
  • 进行checkpoint averaging,是将保存的5个到10个checkpoint里面的参数取平均,可以获得大约0.2个bleu值的提升。
t2t-avg-all --model_dir t2t_output/ --output_dir t2t_avg
  • t2t做预测是运行t2t-decoder
t2t-decoder --data_dir=t2t_data --problem=translate_envi_iwslt32k \
--model=transformer --decode_hparams="beam_size=4,alpha=0.6"  \
--decode_from_file=tst2013.en --decode_to_file=system.output  \
--hparams_set=transformer_base --output_dir=t2t_avg
  • 计算bleu
t2t-bleu --translation=system.output --reference=tst2013.vi
  • 如果是要加载预训练的模型进行预测,那么就使用--checkpoint_path即可
t2t-decoder --data_dir=t2t_data --problem=translate_envi_iwslt32k \
--model=transformer --decode_hparams="beam_size=4,alpha=0.6" \
--decode_from_file=tst2013.en --decode_to_file=system.output \
--hparams_set=transformer_base --checkpoint_path t2t_avg/model.ckpt-50000
  • 虽然指定了hparams_set,如果要更改里面的参数可以使用--hparams='batch_size=1024'进行大力调参,
# Train
# *  If you run out of memory, add --hparams='batch_size=1024'.
t2t-trainer \
  --data_dir=$DATA_DIR \
  --problem=$PROBLEM \
  --model=$MODEL \
  --hparams_set=$HPARAMS \
  --output_dir=$TRAIN_DIR

# Decode

DECODE_FILE=$DATA_DIR/decode_this.txt
echo "Hello world" >> $DECODE_FILE
echo "Goodbye world" >> $DECODE_FILE
echo -e 'Hallo Welt\nAuf Wiedersehen Welt' > ref-translation.de

BEAM_SIZE=4
ALPHA=0.6

t2t-decoder \
  --data_dir=$DATA_DIR \
  --problem=$PROBLEM \
  --model=$MODEL \
  --hparams_set=$HPARAMS \
  --output_dir=$TRAIN_DIR \
  --decode_hparams="beam_size=$BEAM_SIZE,alpha=$ALPHA" \
  --decode_from_file=$DECODE_FILE \
  --decode_to_file=translation.en
  • 官方的小例子
pip install tensor2tensor

# See what problems, models, and hyperparameter sets are available.
# You can easily swap between them (and add new ones).
t2t-trainer --registry_help

PROBLEM=translate_ende_wmt32k
MODEL=transformer
HPARAMS=transformer_base_single_gpu

DATA_DIR=$HOME/t2t_data
TMP_DIR=/tmp/t2t_datagen
TRAIN_DIR=$HOME/t2t_train/$PROBLEM/$MODEL-$HPARAMS

mkdir -p $DATA_DIR $TMP_DIR $TRAIN_DIR

# Generate data
t2t-datagen \
  --data_dir=$DATA_DIR \
  --tmp_dir=$TMP_DIR \
  --problem=$PROBLEM

# Train
# *  If you run out of memory, add --hparams='batch_size=1024'.
t2t-trainer \
  --data_dir=$DATA_DIR \
  --problem=$PROBLEM \
  --model=$MODEL \
  --hparams_set=$HPARAMS \
  --output_dir=$TRAIN_DIR

# Decode

DECODE_FILE=$DATA_DIR/decode_this.txt
echo "Hello world" >> $DECODE_FILE
echo "Goodbye world" >> $DECODE_FILE
echo -e 'Hallo Welt\nAuf Wiedersehen Welt' > ref-translation.de

BEAM_SIZE=4
ALPHA=0.6

t2t-decoder \
  --data_dir=$DATA_DIR \
  --problem=$PROBLEM \
  --model=$MODEL \
  --hparams_set=$HPARAMS \
  --output_dir=$TRAIN_DIR \
  --decode_hparams="beam_size=$BEAM_SIZE,alpha=$ALPHA" \
  --decode_from_file=$DECODE_FILE \
  --decode_to_file=translation.en

# See the translations
cat translation.en

# Evaluate the BLEU score
# Note: Report this BLEU score in papers, not the internal approx_bleu metric.
t2t-bleu --translation=translation.en --reference=ref-translation.de
  • 一个小例子
t2t-trainer \
  --model=transformer \
  --hparams_set=transformer_librispeech_tpu \
  --hparams=max_length=295650,max_input_seq_length=3650,max_target_seq_length=650,batch_size=6 \
  --problem=librispeech_train_full_test_clean \
  --train_steps=230000 \
  --eval_steps=3 \
  --local_eval_frequency=100 \
  --data_dir=$DATA_DIR \
  --output_dir=$OUT_DIR \
  --use_tpu \
  --cloud_tpu_name=$TPU_NAME

参考,感谢!

  • tmp_dir就是t2t-datagen里面的文件夹是存放未经处理的数据的,把所有未经处理过的数据放在这个文件夹里面,其他任务也可以重用。
  • data_dir用来存放已经预处理完毕的数据,tmp_dir可以理解为是刚从网络上下载的.zip等压缩文件,data_dir是预处理完成的文件夹,比如说是在NLP的任务中预处理完成的文件就是将人可读的句子分词并构建词表转并将句子中的单词转换成对应的数字。t2t-datagen就是进行数据预处理的代码。
t2t-datagen \
  --data_dir=$DATA_DIR \
  --tmp_dir=$TMP_DIR \
  --problem=$PROBLEM

参考,感谢!

  • 如果句子长度过长,导致OOM,可以设置最大长度,以及在评估的时候丢弃掉长的句子。
--hparams="max_length=60,eval_drop_long_sequences=True"
  • 设置四卡训练
python3 t2t-trainer \
    --data_dir=$DATA_DIR \
    --problem=$PROBLEM \
    --model=$MODEL \
    --hparams_set=$HPARAMS \
    --hparams='batch_size=4096' \
    --worker_gpu=4 \
    --worker_gpu_memory_fraction = 0.98 \
    --train_steps=$TRAIN_STEP \
    --eval_steps=$EVAL_STEP \
    --output_dir=$TRAIN_DIR \
    --schedule=train
  • 默认设置的是两次evaluate的最大时间间隔是600秒,我们通过设置eval_throttle_seconds参数上间隔小一点(因为不知道学习率和步长设置多少合适,所以只能先设置一个值然后看approx_bleu的变化进行调整)
elif [[ $1 == 'train' ]]; then
    # Train
    # *  If you run out of memory, add --hparams='batch_size=1024'.
    python3 src/t2t-trainer \
        --data_dir=$DATA_DIR \
        --problem=$PROBLEM \
        --model=$MODEL \
        --hparams_set=$HPARAMS \
        --train_steps=$TRAIN_STEP \
        --eval_steps=$EVAL_STEP \
        --output_dir=$TRAIN_DIR \
        --hparams='batch_size=20480' \
        --eval_throttle_seconds=100
  • 2080ti上的transformer的饱和bs7000
  • t2t-decoder的时候从指定目录加载文件
--checkpoint_path=t2t_output/transformer_zhen_apk3/model.ckpt-40000 \

你可能感兴趣的:(tensor2tensor)