使用预训练模型自动续写文本的四种方法

作者:皮皮雷 来源:投稿
编辑:学姐

这篇文章以中文通用领域文本生成为例,介绍四种常用的模型调用方法。在中文文本生成领域,huggingface上主要有以下比较热门的pytorch-based预训练模型:

使用预训练模型自动续写文本的四种方法_第1张图片

本文用到了其中的uer/gpt2-chinese-cluecorpussmall和hfl/chinese-xlnet-base,它们都是在通用领域文本上训练的。

但是要注意有些模型(如CPM-Generate共有26亿参数)模型文件较大,GPU有限的情况下可能会OOM。

依赖包:transformers 4

本文使用的例句来源于豆瓣爬下的部分书评。

方法1:transformers.pipline

简介:

直接调用transformers里面的pipline。

源码及参数选择参考:

https://huggingface.co/docs/transformers/v4.17.0/en/main_classes/pipelines#transformers.pipeline

缺点:不能以batch形式生成句子,不能并行,大规模调用的时候时间复杂度较高。

from transformers import pipeline

#this pipline can only generate text one by one
generator = pipeline(
    'text-generation', 
    model="uer/gpt2-chinese-cluecorpussmall",  #可以直接写huggingface上的模型名,也可以写本地的模型地址
    device = 1)

text_inputs = ["客观、严谨、浓缩",
                "地摊文学……",
                "什么鬼玩意,",
                "豆瓣水军果然没骗我。",
                "这是一本社会新闻合集",
                "风格是有点学古龙嘛?但是不好看。"]

sent_gen = generator(text_inputs, 
                        max_length=100, 
                        num_return_sequences=2,
                        repetition_penalty=1.3, 
                        top_k = 20) 
#返回的sent_gen 形如#[[{'generated_text':"..."},{}],[{},{}]]

for i in sent_gen:
    print(i)

方法2:transformers中的TextGenerationPipeline类

源码及参数选择参考:

https://huggingface.co/docs/transformers/v4.17.0/en/main_classes/pipelines#transformers.TextGenerationPipeline

优点:相较方法1,可以设置batch size。

from transformers import BertTokenizer, GPT2LMHeadModel, TextGenerationPipeline

tokenizer = BertTokenizer.from_pretrained("uer/gpt2-chinese-cluecorpussmall")
model = GPT2LMHeadModel.from_pretrained("uer/gpt2-chinese-cluecorpussmall")

text_generator = TextGenerationPipeline(model, tokenizer, batch_size=3, device=1)
text_inputs = ["客观、严谨、浓缩",
                "地摊文学……",
                "什么鬼玩意,",
                "豆瓣水军果然没骗我。",
                "这是一本社会新闻合集",
                "风格是有点学古龙嘛?但是不好看。"]

gen = text_generator(text_inputs, 
                    max_length=100, 
                    repetition_penalty=10.0, 
                    do_sample=True, 
                    num_beams=5,
                    top_k=10)

for sent in gen:
    gen_seq = sent[0]["generated_text"]
    print("")
    print(gen_seq.replace(" ",""))

方法3:transformers通用方法,直接加载模型

源码及参数选择参考:

https://github.com/huggingface/transformers/blob/c4d4e8bdbd25d9463d41de6398940329c89b7fb6/src/transformers/generation_utils.py#L101

缺点:封装度较差,代码较为冗长。

优点:由于是transformers调用模型的通用写法,和其他模型(如bert)的调用方式相似,(如tokenizer的使用),可以举一反三。

from transformers import AutoTokenizer, AutoModelWithLMHead
import torch, os

os.environ["CUDA_VISIBLE_DEVICES"] = "2"
tokenizer = AutoTokenizer.from_pretrained("uer/gpt2-chinese-cluecorpussmall")
model = AutoModelWithLMHead.from_pretrained("uer/gpt2-chinese-cluecorpussmall")
config=model.config

print(config)

device = 'cuda' if torch.cuda.is_available() else 'cpu'
model = model.to(device)
texts = ["客观、严谨、浓缩",
                "地摊文学……",
                "什么鬼玩意,",
                "豆瓣水军果然没骗我。",
                "这是一本社会新闻合集",
                "风格是有点学古龙嘛?但是不好看。"]
#用batch输入的时候一定要设置padding
encoding = tokenizer(texts, return_tensors='pt', padding=True).to(device)

with torch.no_grad():
    generated_ids = model.generate(**encoding, 
    max_length=200, 
    do_sample=True, #default = False
    top_k=20, #default = 50
    repetition_penalty=3.0 #default = 1.0, use float
    ) 
generated_texts = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)

for l in generated_texts:
    print(l)

方法4:Simple Transformers

简介:Simple Transformers基于HuggingFace的Transformers,对特定的NLP经典任务做了高度的封装。在参数的设置上也较为灵活,可以通过词典传入参数。模型的定义和训练过程非常直观,方便理解整个AI模型的流程,很适合NLP新手使用。

simple transformers 指南:

https://simpletransformers.ai/docs/language-generation-model/

优点:这个包集成了微调的代码,不仅可以直接做生成,进一步微调也非常方便。

缺点:有些中文模型不能直接输入huggingface上的模型名称进行自动下载,会报错找不到tokenizer文件,需要手动下载到本地。

$ pip install simpletransformers

下载中文生成模型到本地文件夹 models/chinese-xlnet-base

使用预训练模型自动续写文本的四种方法_第2张图片

from simpletransformers.language_generation import LanguageGenerationModel
# import logging

# logging.basicConfig(level=logging.INFO)
# transformers_logger = logging.getLogger("transformers")
# transformers_logger.setLevel(logging.WARNING)

model = LanguageGenerationModel("xlnet", #model type
"models/chinese-xlnet-base", #包含 .bin file的文件路径
args={"max_length": 50, "repetition_penalty": 1.3,"top_k":100})
prompts =["客观、严谨、浓缩",
                "地摊文学……",
                "什么鬼玩意,",
                "豆瓣水军果然没骗我。",
                "这是一本社会新闻合集",
                "风格是有点学古龙嘛?但是不好看。"]
for prompt in prompts:
    # Generate text using the model. Verbose set to False to prevent logging generated sequences.
    generated = model.generate(prompt, verbose=False)
    print(generated)

观察:用gpt2-chinese-cluecorpussmall生成的文本

参数设置:

max_length=100
repetition_penalty=10.0
do_sample=True
top_k=10

注:每一段文字的开头(标蓝)是预先给定的prompt

使用预训练模型自动续写文本的四种方法_第3张图片

PS:乍一看生成语句的流利度和自然度都较好,还挺像人话的;而且有些句子能够按照“书评”的方向写。但仔细看就会发现噪音较多,而且容易“自由发挥”而跑题。这就是自由文本生成的常见问题:因为过于自由而不可控。

那么如何将生成的文本限定在想要的格式或领域中呢?这就是可控文本生成的研究范围了。一个较为常见的做法是对GPT-2作增量训练,让模型熟悉当前的语境。

总结

本文列举和比较了四种使用pytorch调用生成式模型做文本生成的方式。分别是:

① transformers自带的pipline

② transformers中的TextGenerationPipeline类

③ transformers通用方法,直接加载模型

④ Simple Transformers

这些方法各有优缺点。如果需要后续微调,建议使用③或④。如果只是简单地体验生成效果,建议使用①和②,但是方法①不能以batch形式输入,速度较慢。

关注下方《学姐带你玩AI》

回复“ACL”免费获取NLP顶会必读高分论文

包含文本生成等20个细分方向

码字不易,欢迎大家点赞评论收藏!

你可能感兴趣的:(粉丝的投稿,人工智能干货,深度学习干货,人工智能,深度学习,预训练模型)