最近在做生成式模型的一些工作,至今算是能有些总结的了,趁着还有些能记住的地方,赶紧记录下来,后面想到了再补充。
前期调研
1. 相关工作
目前我们在做的算是业界独创的,搜了一圈,没有相关的工作,所以我把PaddleNLP中generation相关的任务给看了一遍,比如question_generation
,用T5预训练模型或unimo-text项目,machine_translation
中的transformer部分,对于大致的实现思路以及各自在解码时采用的策略都作了些了解,所以整理实现起来并不复杂。
2. 预训练模型选择
这里反而是比较头疼和纠结的地方,从类型选择上有两大类:decoder和encoder-decoder。对于这部分在huggingface course上是怎么解释或者区分的呢,如果你用于文本生成,那你可以选择CTRL、GPT等相关模型,如果是文本摘要、翻译、生成问题的回答,那你就选择BART、T5等相关模型。这里思考了许久,最终选择使用encoder-decoder架构来做,因为做的任务是需要结合输入,对输入来做理解的,那么这么来看encoder-decoder架构是最合适不过的了。那反过来思考下,decoder难道就不适合了吗?比如GPT坚持的decoder这条路,不也已经能说明问题了吗。
语言选择,一个是我们是做中文领域的,首先必须支持中文,multi-language虽说支持,但是支持语言太多,带来相同模型容量的情况下就不如中-英这种效果更好,比如国内的erlangshen、mengzi、Randeng、PEGUES、gpt2-chinese等相关模型。
模型容量,首先不能太大,一是要能训练的起来,二是推理时也不能太慢,三是部署时模型体积也不能太大。看了些相关的generation模型,比如Llama2-chinese,BLOOM,简直是最想要尝试的,不过跑不起来。。OPT、CTRL、FLAN,也不太行,还不如前者。那只能退化到BART、T5、GPT2这类小点的。
后来想想,这里哪个最好,我觉得有许多可以尝试的点,不过当时试了下t5-small,感觉就不如国内一些模型效果好些,收敛起来也更快。另外一个,一定要选择一个有在multi-task上微调的模型,会少走弯路。
注意点
解码
如果非说哪里有额外需要着重注意的点,解码算是重中之重。解码有不同的策略,比如要不要做采样,不做采样那可以使用beam search,生成的结果是固定的,要采样可以使用top_p, top_k,temperature,这部分不着重介绍,huggingface上有相关的文章,以及国内也有翻译成中文版本的,都是很齐全的了。
对于解码策略,我觉得这里非常有必要多尝试尝试,网上一些文章介绍说比如做翻译或者说比较短文本的生成,使用beam search效果就比较好,如果需要文本更具有多样性以及连贯性,可使用采样,比如huggingface在介绍不同策略时,说GPT2为啥会取得成功,因为使用了top_p。各有各的好,不过说的也非常笼统。
至于超参怎么选择,beam search可看下上面介绍的项目以及huggingface上训练GPT2的流程或者其他相关的项目,采样可看看比如Llama2-chinese、BELLE等一些项目。
评估
由于是生成式任务,评估的标准与方式也有所不同,比如基于连贯性的BLEU、GLEU,一个侧重召回,一个侧重准确。基于词向量的评价指标,基于PPL等其他评价。每个任务目标不同,可采取的评估标准也可以不同,比如也可以采用输入和输出文本的相似度,输入和输出的核心词是否还在来作为评估方式,以及也可以使用打印出来输入输出,来人工进行评估。
另外一个点是一定要多看看标注的数据,因为每个标注人员的理解不同导致标注结果都或多或少有所不同,也可能直接导致了没有归一化的答案。
mutli-task
目前业界开源的预训练模型一般都在多个任务上微调过,那这里思路为是否可以基于目标任务来做层转换生成预训练模型已有的任务来进行提升目前任务效果。
比如做翻译任务,如果预训练模型已经有了,那自然更好。如果没有,比如你的目标任务是做input和output的转写,那核心意图是不能改变的,如果预训练模型已有意图识别能力,那这里也可以作为一种提升思路。
未来展望
这里算是埋个坑,由于目前大模型的崛起,对于加速推理也有不同的方式,比如Imdeploy,FasterTransformer,vLLM。
finish.
更新
上文也说道,decoder难道就不适合了吗?就目前开放的大模型,比如chatGLM、chatGPT、baichuan等,都是基于decoder架构来做的,所展示的能力也是有目共睹的,所以尝试使用几个不同的decoder架构的模型来进行尝试。
首先肯定是GPT2了,但是看了一圈,没找到比较好的支持中文的、并且不漏字的,然后才是容量大小之类的问题。emmmmm,或者是说,自从bert这种encoder架构出来的模型火了后,都在往这方面发力。可选择性并没有那么多。也有在做国产化这类的,比如IDEA-CCNL/Fengshenbang-LM,开源了一系列的模型,比如wenzhong-gpt2-110M。也有在做精简化的,比如澜舟科技的mengzi-GPT-neo-base。
对其做了些实验,发现text-generation的确也是能理解的,但是存在一直续写的问题,不知道何时截断会比较好。一开始我还以为是我用huggingface trainer的原因,也进行修改以及也调整了生成策略,发现这个问题还是存在。后来我人为在句子结尾添加了一个<end>
(GPT2 pad和eos是同一个,所以自己想了一个,并且tokenizer时不会将其分开)终结符,预测时遇到这个就截断,效果才正常。
比如原来:
1 | <input>\n\n输出:<output> |
现在:
1 | <input>\n\n输出:<output><end> |
但是这样就比较类似text2text generation这种做法了,看样子采用不同策略去解码,还是不如截断效果会更好。
果真如此吗?还是说可以增加容量大小来解决这个问题?
后面尝试了下Langboat/bloom-389m-zh,发现还是会存在这个问题,所以在有明显截断条件下的任务上,text2text generation可能会更好。
不过此处继续埋个坑~