Tensor2Tensor是谷歌基于TensorFlow开发的一个非常好用的深度学习库,该深度学习库包含了很多方面的功能,适用于很多模型,包括图片分类、图片生成、问答系统、情感分析、语言模型等。官方的介绍请看这里。本文将以一个具体例子去用通俗的语言详细地介绍如何去使用这个模型,因为自己在最开始看官方文档也是一知半解,很多地方都没有搞清楚,也是自己一步一步摸索才入的门,本文参考了这个博客,并将围绕这个博客中的例子进行更为详细的介绍。
首先在开始正式的操作之前还是要先安装一些包和创建一些文件夹。首先要安装的就是tensorflow和tensor2tensor包,由于tensorflow和tensor2tensor的兼容性不是特别好,有一些版本之间是不兼容的。最新的tensorflow2.0版本就和tensor2tensor不怎么兼容。跑这个模型的话建议使用GPU版的tensorflow,会比CPU版的tensorflow训练模型快很多,首先是CPU版的安装,推荐tf1.5和t2t1.6,这两个亲测是可以兼容的:
pip install tensorflow==1.5
pip install tensor2tensor==1.6
然后如果是GPU版的tensorflow的话还要注意tf和cuda的版本匹配,我之前安装的是tensorflow-gpu==1.13.1和CUDA 10.0,在GPU上的训练我是在Google Colab上进行的(需要科学上网,google colab使用方法自行百度)
假设你已经安装好了CPU版的tensorflow还有对应兼容版本的tensor2tensor,接下来我们需要创建一些文件夹。
假设你最开始创建了一个文件夹叫做seq2seq,其他操作都在这里面进行(这个话有点多余)
点击进入这个文件夹之后,还要创建几个文件夹,他们分别的作用我接下来会先简要介绍一下:
①rawdata:用于存放训练模型的数据,这个数据就是你手上整理成的原始数据,随后还需要使用脚本处理一下,变成模型可以直接读取使用的数据
②data:存放处理过后的数据的文件夹
③train:用来存放训练模型的文件夹
④user:用来放用户设置的文件夹,在tensor2tensor的官方文档中,官方文档给出了一些可以直接使用的模型,比如翻译模型,这些给出的常用模型官方是提供了数据的,也就是说你如果用这些模型,数据就不需要你操心了,直接按照官方的使用说明跑就完事了。但是很多情况下我们需要使用自己的数据进行模型训练,因此需要设置自己的一些配置,这个后面在具体介绍。
⑤decoder:这个文件夹里面放的是你要进行转换的数据,可以理解成这个文件里放了你想要测试的数据,模型训练好以后可以从这里面拿数据,然后跑出来看效果,具体的后面就知道了,当然这个文件夹也可以不叫这个名字,因为后面会指定文件夹的名字。
首先我们自己创建一些样本数据,然后目的是训练一个模型进行摘要。数据是参考了文章最开始提到的博客,这里要感谢一波原博客作者。
先是在rawdata文件夹下创建两个txt文件,首先是rawdata/q.txt下的数据,这个相当于样本:
内容很多很棒
好老师!有耐心!培养孩子兴趣!赞一个
课程很精彩,老师会结合自身作为案例进行分享
老师很幽默
老师的能力值得肯定
喜欢上老师的数学课
老师上课气氛特别好
每次听完老师的课都觉得让自己又丰富了许多
挺善于沟通的,比较容易接受
观点很新颖,谢谢老师
然后是rawdata/a.txt下的数据,相当于标签,也就是q.txt中话的摘要总结:
授课熟练
态度认真负责
授课熟练
幽默风趣
性价比高
幽默风趣
上课气氛活跃
内容新颖有用
性价比高
内容新颖有用
官方文档中提到我们在使用自己的数据进行模型训练的时候需要定义自己的problem是什么,通俗来说就是如果你要训练自己的数据,就需要在user文件夹下写两个python的脚本,分别是__init__.py和 my_problem.py,my_problem是你对你的问题的命名,可不叫my_problem,叫其他的名也行,我这里就叫它my_probem了,这里还涉及到一些命名的问题,后面会提到。下面就是如何编写自己的problem了:
下面这段代码来自原博客,其实拿官方给的代码改一改也不难,我纯粹就是懒得写了…以下为user/my_problem.py:
# coding=utf-8
from tensor2tensor.utils import registry
from tensor2tensor.data_generators import problem, text_problems
#自定义的problem一定要加该装饰器,不然t2t库找不到自定义的problem
@registry.register_problem
class MyProblem(text_problems.Text2TextProblem):
@property
def approx_vocab_size(self):
return 2**11
@property
def is_generate_per_split(self):
return False
@property
def dataset_splits(self):
# 把数据9:1分成训练集和验证集
return [{
"split": problem.DatasetSplit.TRAIN,
"shards": 9,
}, {
"split": problem.DatasetSplit.EVAL,
"shards": 1,
}]
def generate_samples(self, data_dir, tmp_dir, dataset_split):
del data_dir
del tmp_dir
del dataset_split
#读取原始的训练样本数据
q_r = open("./rawdata/q.txt", "r")
a_r = open("./rawdata/a.txt", "r")
comment_list = q_r.readlines()
tag_list = a_r.readlines()
q_r.close()
a_r.close()
for comment, tag in zip(comment_list, tag_list):
comment = comment.strip()
tag = tag.strip()
yield {
"inputs": comment,
"targets": tag
}
注意一下上面代码中类的命名,这个有相应的规则,如果你的py文件为this_is_problem,那么你的类命名就是ThisIsProblem,然后就是改一下文件读取的那两行代码,如果你的数据文件名不叫q.txt或者a.txt之类的。这样,你自己的problem设置就完成了,就可以进行下一步操作去生成数据了
生成数据的话只需要敲一条命令:
t2t-datagen \
--data_dir=data \
--problem=my_problem \
--t2t_usr_dir=user
不出意外的话生成完数据之后就可以进行模型的训练了
还是只需要敲一条命令就可以开始训练:
t2t-trainer \
--t2t_usr_dir=user \
--data_dir=data \
--problem=my_problem \
--model=transformer \
--hparams_set=transformer_small \
--hparams="batch_size=512" \
--schedule=continuous_train_and_eval\
--output_dir=train \
--train_steps=1000000 \
--worker-gpu=1 \
现在我来解释一下每个参数的含义:
①–t2t_usr_dir:这个参数只要是你使用自己的数据,基本上所有的命令都会要用到,对应的是你定义自己problem的文件夹
②–data_dir:很好理解,就是你之前上一步生成数据的文件夹
③–problem:就是你之前定义的问题的名字
④–model:这里是指你要是用什么模型去训练,我这里使用的transformer,还有lstm_attention等等等等很多其他模型,具体请参考tensor2tensor的官方文档
⑤–hparams_set:这里的transformer_small是指使用大中小里面哪种模型,不同的模型尺寸适合于不同规模的数据,一般的话small就够用了,模型越大训练的资源和时间开销也越大,当然如果你的机器足够nb那就随意好了
⑥–hparams:训练时候的一些参数,可以调一调batch_size,效果上基本是越大越好,当然训练起来也是越大越慢
⑦–schedule:意思应该是训练的模式,这里选择的是边训练边evaluate,也就是训练1000步保存一个模型的时候evaluate一下看看效果
⑧–output_dir:也就是保存模型的文件夹了
训练的时候你是可以看到训练效果的,因为每次保存模型都会进行一次评估,可以看到大致效果,可以中途去看看效果怎么样,那么怎么看效果呢?当然是拿一些样本看看
让我们看看解码的命令:
t2t-decoder \
--t2t_usr_dir=user \
--data_dir=self_data\
--problem=my_problem \
--model=transformer \
--hparams_set=transformer_small \
--output_dir=train \
--decode_hparams="beam_size=4,alpha=0.1" \
--decode_from_file="decoder/q.txt" \
--decode_to_file="decoder/a.txt"
主要解释一下decode_hparams这个参数,这个参数里的beam_size,这个需要各位看官去了解什么是beam search了,这里不对beam search作过多介绍,总之需要了解的是,对于一个输入,可能对应着多个输出的sequence,在解码的时候会返回那个作为结果可能性最大的sequence到输出文件里,当然,如果你还想要其他的结果就可以自行调节其中的参数,我在做一个项目的时候就需要知道Top-k accuracy,所以我需要输出多个解,比如要输出十个解,那么参数改成 “beam_size=10, alpha=0.1, return_beams=True” 就好了,这个在官方文档中是没有的…是我看源码的参数的时候发现的。
然后我们人为设置一下我们想要解码的内容,也就是decoder/q.txt:
老师很幽默
非常好 讲的很详细 还幽默哈哈哈
第一次听!讲得还挺清楚,只是bu清楚后面怎么安排呢
挺善于沟通的,比较容易接受
运行后可以看到结果,decoder/a.txt:
老师幽默
态度认真负责
态度认真负责
性价比高
虽然效果还不是很好,但是基本的意思还是出来了的。基本上就是这些啦~后面的部分我自己也还没有尝试过,就不写辽。