最近想做翻译,现在的好多开源框架师兄都说不错,因为想做的中英翻译发现fairseq
没有直接支持,而t2t
是直接可以中英翻译的,所以学习一波这个框架。
-
Trainer
:是training
,evaluation
和inference
的入口,更改模型是使用--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
,其中最后一种词表形式是默认的形式。指定我们近似有8k
个subwords
。
@property
def approx_vocab_size(self):
return 2**13 # ~8k
- 一个方法决定要不要切分
training set
和eval 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_lines
,poetry_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
的饱和bs
是7000
-
t2t-decoder
的时候从指定目录加载文件
--checkpoint_path=t2t_output/transformer_zhen_apk3/model.ckpt-40000 \