前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >GPT-2的探究:对虚假新闻生成的恐惧,源于技术还是人?

GPT-2的探究:对虚假新闻生成的恐惧,源于技术还是人?

作者头像
AI科技评论
发布2019-09-10 16:08:25
6380
发布2019-09-10 16:08:25
举报
文章被收录于专栏:AI科技评论
也许,与其抗拒生成文本技术,不如去训练人类辩证思维!

作者:Vered Shwartz

编译:栗峰

今年年初,OpenAI发布了一个非常强大的语言模型,可以模拟生成类似人类创作出的文本。通常在公告发布之后就会面向公众发布模型,但这这次的公告不同以往,它表示这样一个强大的工具可能会构成危险,因此只发布了一个较小、功能较单一的模型。

很快,除了学术的热议之外,这则新闻还被传到了大众媒体上,在那里,人们用相当简单和夸张的方式描述它。在普通民众中引起了恐慌;其他NLP人士中也提出了批评意见;甚至连他们内部也提出了质疑。六个月后,OpenAI终于决定发布完整的模型。

那么这个模型是如何训练的?它们是如何使用的?它们真的那么好吗?真的具有危险吗?

本文将对以上问题做具体分析。

1. 我们讨论什么?

最近大多数人在谈论语言模型(language models,LMs)的原因并不是说他们都在进行文本生成研究,而是因为经过预先训练的LMs(比如OpenAI GPT-2或Google的BERT)可以用于在各种NLP应用程序中生成文本表征,大大提高了它们的性能。这种效果类似于2013年预先训练过的单词嵌入对NLP产生的影响。我推荐阅读SebastianRuder的文章《NLP的ImageNet时刻已经到来》,对此有很好的总结。本篇文章将侧重于文本生成。

在文本生成中有两种完全不同的应用:

1、开放式文本生成:其目的是可以生成任何文本。它可以是一个特定的主题,也可以续写上一段,该模型被赋予了生成任何文本的最好效果。

2、限制性文本生成:这个模型预期将生成一个特定的文本。更正式地说,就是给定一些输入,模型应该严格依据输入文本来生成。最好的例子是翻译:例如给出一个法语句子,模型必须用英语生成一个与法语句子的意思相同的句子。其他例子包括摘要(给定长文档,生成包含文档中重要细节的简短文本)、图像描述(给定图像,生成描述它的文本)、语音到文本(转换)、以及将文本转换为代码或SQL查询。

这篇文章的重点是开放式文本生成。

2. 语言模型

我之前曾经讨论过机器翻译的语言模型。简单来说,语言模型是在文本中给定一个单词来预测后续出现单词的概率分布。分布在词汇表上的所有单词在总量上通常非常庞大(可能是几十万或更多)。

例如,“I'mtired, I want to”这个句子中的下一个单词会是什么?一个好的语言模型会把高分分配给p(sleep|I'mtired, I want to)。像“bed”这样的词出现的概率应该很低,虽然它是一个相关的术语,但它并不构成语法句子;再者是“party”,虽然语法上正确但与逻辑相矛盾。整个句子的概率是每个单词条件概率的乘积,使用链式法则,给定前面的单词:

p(I'mtired, I want to sleep) = p(I'm|<s>) * p(tired|<s> I'm) *p(,|<s> I'm tired) * p(I|<s> I'm tired,) *p(want|<s> I'm tired, I) * p(to|<s> I'm tired, I want) *p(sleep|<s> I'm tired, I want to) * p(</s>|<s> I'mtired, I want to sleep)

其中<s>和</s>分别标记句子的开头和结尾。请注意,我在这篇文章中使用了基于单词的LM进行演示,但是,可以将基本标记定义为token或“Word部件”/“子词单元”。

3. 生成文本

虽然LMs可以用来对某一文本在通常语言逻辑中出现的可能性进行评分,但在这篇文章中,我们将讨论它们的另一个常见用法,即生成新文本。

假设我们已经训练了一个语言模型,我们如何生成文本呢?

我们用一个非常简单的玩具LM来演示,它的词汇量很小,仅有少量可能的话语:

代码语言:javascript
复制
import numpy as np
# Create a very simple unigram LM with a small vocabulary
vocab = ['<s>', 'This', 'LM', 'is', 'stupid', 'cool', '</s>']
word2index = {w: i for i, w in enumerate(vocab)}
probabilities = np.array([[0.01, 0.94, 0.01, 0.01, 0.01, 0.01, 0.01],
                          [0.01, 0.01, 0.94, 0.01, 0.01, 0.01, 0.01],
                          [0.01, 0.01, 0.01, 0.94, 0.01, 0.01, 0.01],
                          [0.01, 0.01, 0.01, 0.01, 0.47, 0.48, 0.01],
                          [0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.94],
                          [0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.94],
                          [0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.94]])
stupid_lm = lambda s: probabilities[word2index.get(s.split()[-1], -1), :]

要使用语言模型生成文本,必须逐个地生成,后面的符号由前面符号定义的分布决定。最基本的方法是在每一步简单地使用最可能的词。代码将如下所示:

代码语言:javascript
复制
def generate_most_probable(lm, index2word):
    """
    Generates a string, taking the most probable word at each time step.
    :param lm - the language model: a function that gets a string and returns a distribution on the next word
    :param index2word - a mapping from the index of a word in the vocabulary to the word itself
    """    
    generated_sentence = '<s>'
    curr_token = None

    while curr_token != '</s>':
        curr_distribution = lm(generated_sentence)  # vector of probabilities
        sorted_by_probability = np.argsort(curr_distribution)
        curr_token = index2word[int(sorted_by_probability[-1])] # last token is the most probable
        generated_sentence += ' ' + curr_token        

    return generated_sentence


generated_str = generate_most_probable(stupid_lm, vocab)
print(generated_str)

我们的玩具LM只生成句子“This LM is cool”。一般来说,这种生成方法是非常受限的,因为它的表现单一,尤其是它更倾向于出现概率大的单词,其中一些是虚词,如限定词(the,a,.),介词(on,in,of,.)。诸如此类。此外,据一些研究表明,最大概率生成的文本与人工生成的文本有很大不同。人们说话并不会考虑哪些单词出现的概率更大、哪些句子更常规,而是要告诉听众对他们最有帮助,或者是他们还不知道的信息(根据Grice's Cooperative原则)。

另一种方法是根据语言模型从分布中抽样,即从词汇表中随机选取一个单词,与先前给定的单词概率成正比。代码如下所示:

代码语言:javascript
复制
def generate_sample(lm, index2word, max_tokens=25):
    """
    Generates a string, sample a word from the distribution at each time step.
    :param lm - the language model
    :param index2word - a mapping from the index of a word in the vocabulary to the word itself
    """ 
    generated_sentence = '<s>'
    generated_tokens = 0
    curr_token = None

    while curr_token != '</s>' and generated_tokens < max_tokens:
        curr_distribution = lm(generated_sentence)  # vector of probabilities
        selected_index = np.random.choice(range(len(vocab)), p=curr_distribution)
        curr_token = index2word[int(selected_index)]
        generated_sentence += ' ' + curr_token
        generated_tokens += 1

    return generated_sentence


generated_str = generate_sample(stupid_lm, vocab)
print(generated_str)

你可能会注意到,多次运行这个代码,有时生成的LM并不符合常理,而有时这个LM是可用的。虽然这种抽样方法倾向于产生更多样化的文本,但它也不完美,因为现在有机会在每一个时间步中对一个生词或无关的单词进行采样,一旦模型完成,下一个单词的生成就取决于这个生词,这就是它可能会走下坡路的原因。

一个简单的解决方案是将这两种方法结合在一起,仅从分布中概率最大的top k 个单词中抽取样本。如下所示:

代码语言:javascript
复制
def generate_sample_top_k(lm, index2word, k=5, max_tokens=25):
    """
    Generates a string, sample a word from the top k probable words in the distribution at each time step.
    :param lm - the language model
    :param index2word - a mapping from the index of a word in the vocabulary to the word itself
    :param k - how many words to keep in the distribution
    """ 
    generated_sentence = '<s>'
    curr_token = None
    generated_tokens = 0

    while curr_token != '</s>' and generated_tokens < max_tokens:
        curr_distribution = lm(generated_sentence)  # vector of probabilities
        sorted_by_probability = np.argsort(curr_distribution) # sort by probability
        top_k = sorted_by_probability[-(k+1):] # keep the top k words

        # normalize to make it a probability distribution again
        top_k = top_k / np.linalg.norm(top_k)

        selected_index = np.random.choice(range(len(vocab)), p=top_k)
        curr_token = index2word[int(selected_index)]
        generated_sentence += ' ' + curr_token   
        generated_tokens += 1

    return generated_sentence


generated_str = generate_sample_top_k(stupid_lm, vocab)
print(generated_str)
view raw

注意,在分布中只保留k个单词之后,我们需要再次确保它们形成有效的概率分布,即每个数据在0到1之间,并且总和是1。

从分布顶端取样的另一种方法是top p:将符号根据从大到小的概率排序,然后抽取符号,直到概率之和(也就是生成这些符号的概率)达到0到1之间的某个预定义值p为止。如果p值接近 0,那么模型将始终采用概率最大的token,而如果p值接近1,那么将从完整的分布中进行采样。

显然这种方法相对于topk更加灵活,因为候选token的数量会根据所生成的前缀而改变。例如,对于像“I want to”这样的文本就会有更多的候选者,而像“The bride andthe groom got”可选的token就不多(“married”应该占很大一部分的概率)。

4. 训练语言模型

我之前讨论过N-gram语言模型,但是4年前它们就已经过时了,取而代之的是神经语言模型。神经LM的基本训练算法如下:

不同的神经LMs在基本token(即字、字符、字块)和编码器的选择上有所不同。编码器采用一系列单词嵌入并返回表示相应单词序列的单个向量(例如: tired, I want to)。我以后可能会再写一篇文章专门讨论将文本编码为向量的方法。本文我们仅将其视为黑匣子。下图说明了训练方法(尤其是基于RNN的编码器):

神经LMs相比于N-gram LMs,有两个重要的优势:

1)N-gram LM通常根据前一个单词预测下一个单词,例如, I'mtired, I want to,3-gram LM只会根据最后3个单词“I want to”来预测下一个可能出现的单词,完全忽略了“tired”这个关键词。N-gram LMs通常以小N(2 - 4个)为基础。(请参阅关于N-gram 语言模型的文章获得详细的解释)。

2)N-gram LM是基于文本数据中每个文本出现次数的统计,它必须是逐字逐句的,“I'mtired”的出现次数与“I'm exhausted”的出现次数是完全不相关的,而神经LMs却学习将文本片段表示为向量,并在此基础上预测下一个单词。它可以通过分配相似的向量表征来概括语义相似的文本(结果是相同的预测)。

一个重要的提示:当前的LM训练有不同的训练目标,即不再执着于猜测句子中可能出现的下一个单词。具体而言,BERT具有“掩蔽LM的目的”,即隐藏句子中的随机单词,并通过联系上下文对后面出现的单词进行预测,在这些隐藏单词的前后都用符号标记。文本GAN(生成对抗网络)由两个组件组成:生成类似人类文本的生成器和经过训练以区分人类生成文本和生成器生成文本的鉴别器。实际上,当前基于GAN的文本生成的表现不如语言模型的生成。

5. 评估文本生成

比较两个用于解决相同任务的分类器的性能很容易。有一个测试集,每个数据点带有真实标注;使用模型预测测试数据的标注,并计算每个模型与真实标注相比的准确度。我们会得到两个数值,精度越高模型就越好。

但这对于文本生成来说却并不奏效。

由于我们讨论的是开放式文本生成,并不存在黄金标准文本(gold standard text)来评判模型的准确度。

那么,我们该如何判断模型的质量呢?

目前最好的方法就是,我们手动去查看模型生成的部分文本的质量来评判一个模型是否足够优秀。

为了更系统地做到这一点,我们可以通过向人们展示由我们的模型生成的文本和由某个基础模型(或人类)生成的文本,让他们对比评分,并对这些评价汇总,总结出对这些文本最准确的评价。

但这种方法成本却极高,而且耗时很长。因此,在模型开发的最后阶段,它通常应用于相对较少的文本,而不是在中间步骤去验证文本(这可能有助于改进模型)。

另一种常用的方法是困惑度:根据定义,它是测试集的逆概率,由字数来量化。我们希望得到一个尽可能低的困惑评分,这意味着测试集的概率是最大化的。也就是说,LM学习了一个类似于“truth”的概率分布。测试集是LM从未见过的文本,它的概率是通过逐字逐句的检查并计算LM预测的每个单词的概率来计算的。好的LM会将大概率分配给“正确的”(实际的)下一个单词,而将小概率分配给其他单词。

困惑度虽然是最常见的文本生成评价指标,但由于种种原因也备受质疑。主要是因为困惑度的改善并不等同于语言模型的改进(它基本上不是象征质量好的指标)。另外,也是因为困惑度不能用来评估文本生成模型,这些模型不会像GAN一样产生单词分布。如果你认为限制性文本生成的评估指标更好,那就要仔细考虑清楚了!

6. 语言模型是否危险?

我之前讨论过机器学习模型滥用的风险,结论是:如果有人恶意使用LMs,那么可能会造成危险。

更具体地说,OpenAI的声明表达了这样一种担忧,就是如果发布这种模型,可能会被用于大规模地生成虚假新闻。

虽然这有可能会发生,但目前文本生成的两个限制可能会减少对LMs滥用风险的恐慌——至少暂时会。

人类发布假新闻通常有一定的目的,为了宣传或者为了点击量(扩大广告收益)。与人类不同,语言模型生成文本是没有目的性的。这里提到的语言模型是为了生成看起来更加真实、连贯、与主题相关的文本。因此想要用它们来产生大规模的假新闻事实上并没有那么简单。

Grover是一个例外,它的目的是生成可控文本。也可以说,它就是因为假新闻的产生而存在的,由几个参数控制:域(如“纽约时报”)、日期、作者和标题。然而,最重要的是,这个模型可以非常准确地区分假新闻和真实新闻。它能识别出机器生成的文本和人类生成的文本之间的细微差别,即使文本是由另一种语言模型生成的,它也能准确地区分它们。这其实说明了一点:机器生成的文本还不够好(如果是以人类生成的文本为标准的话)。

当然,今天生成文本已经令人印象深刻。它具有语法性,在大多数情况下不会偏离主题。但这并不是说它就具有事实意识(看看它是如何延续以下句子的:GPT-2 is a language model ___),它也没有什么常识(举个例子:she fell and broke her leg becausesomeone left a banana peel ____)。尽管有时人类无法判断出一段文字是否是由机器产生,但有一些模型却能很好地做到这一点。

一个机器人让我们失望,而另一个却没有。

害怕虚假信息可以理解,但至少在目前我更担心的是这些信息背后的人——那些使用模型制造虚假新闻的人,恶意传播它的人,以及那些完全不知情的人。

也许,与其抗拒虚假信息技术,不如去训练人类辩证思维!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI科技评论 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
NLP 服务
NLP 服务(Natural Language Process,NLP)深度整合了腾讯内部的 NLP 技术,提供多项智能文本处理和文本生成能力,包括词法分析、相似词召回、词相似度、句子相似度、文本润色、句子纠错、文本补全、句子生成等。满足各行业的文本智能需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档