NSDT工具推荐Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包

尽管基于 transformer 的模型近年来在一系列 NLP 任务上取得了不错的成绩,但文本生成仍然是一个奇怪的案例。 早在 2020 年 9 月,《卫报》就发表了一篇据称由 OpenAI 的 GPT-3 从零开始撰写的令人印象深刻的文章,并在主流媒体上广受好评,但许多人工智能专家仍持怀疑态度。

文本生成的一个问题是在其选择的方向上缺乏控制。 使用 GPT-3,你可以为模型提供介绍和说明,但即便如此,也需要人工编辑人员从多个输出中挑选文本并将其排列成具有内聚性的内容。 还有其他方法,例如 Salesforce 的 CTRL 和 UberAI 的 PPLM。

在本文中,我们将微调 Huggingface 预训练 GPT-2 并提出我们自己的解决方案:通过数据集的选择,我们可能更好地控制文本样式和生成的内容。

1、数据

我们将使用来自新闻聚合器数据集的样本。 它包含来自知名新闻出版商的超过 40 万篇新闻文章的标题和超链接。 为了减少训练时间,我从 4 个新闻类别中随机抽取了大约 10k 篇文章:商业、科学、娱乐和健康。 这些文章是预先下载的,以减少运行时间。

2、关键词提取

在训练过程中,我们需要每篇文章的关键词列表。 有多种方法可用,从 Rake 到使用 BERT 等等,但我们将在这里坚持使用简单的 TFIDF,因为这不是我们的主要关注点。 在我们的关键字选择中,我们还将允许构成专有名词短语的 2-gram 短语,例如“content creators”。 这个过程也是离线执行的,因为这只需要完成一次。

数据下载和关键词提取的代码可以在我的 GitHub 仓库中找到。

3、处理管道

管道设置包括定义分词器、模型和数据集,然后使用训练器类进行微调,最后是文本生成。 我假设你熟悉这种一般设置 — 如果你需要提醒,这篇文章提供了管道的详细演练。 我将专注于我为实现条件文本生成所做的不同之处。

你可以在我的 Colab notebook 中访问完整代码以了解更多详细信息,欢迎你复制并试验它。

4、模型

在这个实验中,我们将使用带有 12 层解码器的 GPT-2 的小型版本。 该模型在 800 万个网页上进行了训练,在语言任务上已经相当强大。 为了在采用我们的数据集的同时保留其在语言建模方面的一般能力,我们将通过将它们的 parameters.requires_grad 设置为 False 来冻结底部 6 层,并且只训练前 6 层。这也将加快训练速度,因为落后的数量 通过次数减少。

模型层的名称可以简单地通过 print(model) 找到。

model = AutoModelForPreTraining.from_pretrained('gpt2', config=config)

for parameter in model.parameters():
    parameter.requires_grad = False

for i, m in enumerate(model.transformer.h):        
    #Only un-freeze the last n transformer blocks
    if i >= 6:
        for parameter in m.parameters():
            parameter.requires_grad = True 

for parameter in model.transformer.ln_f.parameters():        
    parameter.requires_grad = True

for parameter in model.lm_head.parameters():        
    parameter.requires_grad = True

5、训练设置

在标准文本生成微调中,由于我们预测下一个标记给定的文本,我们到目前为止已经看到,标签只是移位编码标记化输入(请注意,如果我们设置 labels=input_ids,标签会自动在 模型——见下面的参考文献 1)。

但在这里我们想要有更多的控制——除了文章文本,我们还会给模型一个标题和一个微调的关键字列表。 我们在自定义数据集类中执行此操作。

class myDataset(Dataset):

    def __init__(self, data, tokenizer, randomize=True):

        title, text, keywords = [], [], []
        for k, v in data.items():
            title.append(v[0])
            text.append(v[1])
            keywords.append(v[2])

        self.randomize = randomize
        self.tokenizer = tokenizer 
        self.title     = title
        self.text      = text
        self.keywords  = keywords  

    @staticmethod
    def join_keywords(keywords, randomize=True):
        N = len(keywords)

        #random sampling and shuffle
        if randomize: 
            M = random.choice(range(N+1))
            keywords = keywords[:M]
            random.shuffle(keywords)

        return ','.join(keywords)


    def __len__(self):
        return len(self.text)


    def __getitem__(self, i):
        keywords = self.keywords[i].copy()
        kw = self.join_keywords(keywords, self.randomize)
        
        input = SPECIAL_TOKENS['bos_token'] + self.title[i] + \
                SPECIAL_TOKENS['sep_token'] + kw + SPECIAL_TOKENS['sep_token'] + \
                self.text[i] + SPECIAL_TOKENS['eos_token']

        encodings_dict = tokenizer(input,                                   
                                   truncation=True, 
                                   max_length=MAXLEN, 
                                   padding="max_length")   
        
        input_ids = encodings_dict['input_ids']
        attention_mask = encodings_dict['attention_mask']
        
        return {'label': torch.tensor(input_ids),
                'input_ids': torch.tensor(input_ids), 
                'attention_mask': torch.tensor(attention_mask)}

而不是我们在文本前加上 bos_token 并附加 eos_token 的标准设置:

input = SPECIAL_TOKENS['bos_token'] + self.text[i] + SPECIAL_TOKENS['eos_token']

我们还将在文本之前插入标题和关键字列表,用特殊的分隔符分隔:

input = SPECIAL_TOKENS['bos_token'] + self.title[i] + \
        SPECIAL_TOKENS['sep_token'] + kw + SPECIAL_TOKENS['sep_token'] + \
        self.text[i] + SPECIAL_TOKENS['eos_token']

为了帮助模型泛化,我们通过在训练期间使用函数 join_keywords() 对关键字列表进行采样和混洗来引入数据扩充。 但是在验证期间没有应用增强以保持跨时代的一致性。 然后,根据标准做法,训练器类用于训练少量时期(在我们的例子中为 4 个时期)的模型。

6、结果

为了测试我们新的假新闻生成器的能力,我从最近流行的 BBC 新闻中挑选了一篇轻松愉快的文章:“当我们的照片成为模因时,我们感到非常悲伤”。 通过使用相同的标题并(相当主观地)从文章中挑选几个关键词,让我们看看我们的模型可以对其进行什么样的调整。 要使用的关键词是:“train”、“lads”、“drinking”、“picture”、“funny”和“instagram”。

我们为语料库设置的关键字的大小相当大,但是如果我们要使用的关键字不在该集合中,我们总是可以使用该集合中的同义词,或者在某些单词相似性度量方面最接近的一个。

有几种方法可以从模型生成文本。 如果我们使用带采样的波束搜索,我们会得到这样的样本:

Unfortunately, all we have right now is an image that has gone viral.

The picture was taken by one of the boys on Instagram and quickly went viral after it appeared to show a group of friends getting drunk at a New York City bar.

As soon as the picture came out online, many people took to Twitter to express their disgust with the picture.

"What's wrong with this f**king train??," one user wrote.

Another said: "I can't believe my eyes didn't even open."

A third added: "Just saw some pictures of men being mugged in NYC... I'm so sick of these dumbasses."

This content is created and maintained by a third party, and imported onto this page to help users provide their email addresses. You may be able to find more information about this and similar content at piano.io

每一句语义连贯,前三句确实与标题相关,但随后文章出现了意想不到的转折。 “这该死的火车怎么了?” ……我也在想这个。 似乎我们有一些控制,但也许还不够,因为“思想”的列车慢慢地偏离了轨道。

一些关键字(“train”、“drinking”、“picture”和“instagram”,或者它们的同义词或内涵)按照指示在生成的文本中使用。 但是,没有使用“有趣”; 取而代之的是“厌恶”这个词,它有效地概括了这篇文章的基调,这很可能是因为我们选择的标题。

这与原始 GPT-2 相比如何? 使用标题作为第一句话,这里是原始模型的输出样本以供比较:

We got a lot of grief when our photo became a meme.

"I'm not going to lie, I don't know how many times we've been in that kind of situation," he said. "It's hard for me to put it into words."

He added: "There was no way this could have happened without the help of my family and friends who were there with us on Saturday night. We're all so proud of what they did as well."

这段开头还不错,但最后一句无意中的曲折暴露了游戏的意义。 毫不奇怪,关键字根本没有特色。

在某种程度上,我们正在尝试做的是文本摘要的反向——我们试图将一个标题扩展成一篇包含关键词的文章,希望标题的效果能够渗透到整篇文章中。 相比之下,原始 GPT-2 只是从第一句话开始继续,标题的记忆效果可能更短暂。

回到我们的模型,我们还可以使用 top-p(核心)抽样等方法生成文本,这往往会产生更多种类。 这里有一些有趣的,部分听起来很真实,但反过来又有趣又令人不安。 它们可能无法令人信服,但至少它们很有趣:

It was like we were being mugged and all over again.

“I think it's really sad that this happened to us because people are so used by the pictures on their Instagram feeds... they just want attention," said Dr Emily Loughner-Bullock from Kings College London in England who works as an epidemiologist at King Mungol University School Of Public Health (KMU). ‘When you look back through history there have been many examples where celebrities can make headlines for quite controversial things - such is how social media has affected public health research into mental illness or addiction."

The story spread online after one famous photograph emerged which showed two young men with guns talking about drug use while drinking together before another took off his shirt revealing something he had hidden under her skirt: "Nice impression but I wonder if girls don't understand what 'hooking up' looks exactly?" wrote Shilpa Khetrapal Singh Khalsa Mukherjee following Twitter users sharing similar images showing them laughing happily out loud without any justification whatsoever behind some sort action picture taken during dinner parties held between friends...

There will be no further comment here due today afternoon..

仔细审视了 AI 生成的写作的现状后,记者似乎不会很快被技术取代。

毕竟,这就是我最初发表这篇文章的原因——否则我在道德上如何证明我可以在互联网上轻松获得有效的假新闻生成器?


原文链接:Conditional Text Generation by Fine Tuning GPT-2

BimAnt翻译整理,转载请标明出处