人工智能python实现-生成式深度学习

8.1 使用 LSTM生成文本
8.1.1 生成式循环网络简史
8.1.2 如何生成序列数据
8.1.3 采样策略的重要性
8.1.4 实现字符级的 LSTM文本

第 8 章 生成式深度学习

本章包括以下内容:

  • 使用  LSTM生成文本
  • 实现   DeepDream
  • 实现神经风格迁移
  • 变分自编码器
  • 了解生成式对抗网络

人工智能模拟人类思维过程的可能性,并不局限于被动性任务(比如目标识别)和大多数反应性任务(比如驾驶汽车),它还包括创造性活动。我曾经宣称,在不远的未来,我们所消费的大部分文化内容,其创造过程都将得到来自人工智能的实质性帮助。当时是  2014年,人们完全不相信我,即使是长期从事机器学习的人也不信。但仅三年的时间,质疑声就以惊人的速度减弱了。2015年夏天,我们见识了   Google的  DeepDream算法,它能够将一张图像转化为狗眼睛和错觉式伪影(pareidolic artifact)混合而成的迷幻图案。2016年,我们使用  Prisma应用程序将照片变成各种风格的绘画。2016年夏天发布了一部实验性短片  Sunspring,它的剧本是由长短期记忆(LSTM)算法写成的,包括其中的对话。最近可能你听过神经网络生成的实验性音乐。

的确,到目前为止,我们见到的人工智能艺术作品的水平还很低。人工智能还远远比不上人类编剧、画家和作曲家。但是,替代人类始终都不是我们要谈论的主题,人工智能不会替代我们自己的智能,而是会为我们的生活和工作带来更多的智能,即另一种类型的智能。在许多领域,特别是创新领域中,人类将会使用人工智能作为增强自身能力的工具,实现比人工智能更加强大的智能。

很大一部分的艺术创作都是简单的模式识别与专业技能。这正是很多人认为没有吸引力、甚至可有可无的那部分过程。这也正是人工智能发挥作用的地方。我们的感知模式、语言和艺术作品都具有统计结构。学习这种结构是深度学习算法所擅长的。机器学习模型能够对图像、音乐和故事的统计潜在空间(latent  space)进行学习,然后从这个空间中采样(sample),创造出与模型在训练数据中所见到的艺术作品具有相似特征的新作品。当然,这种采样本身并不是艺术创作行为。它只是一种数学运算,算法并没有关于人类生活、人类情感或我们人生经验的基础知识;相反,它从一种与我们的经验完全不同的经验中进行学习。作为人类旁观者,只能靠我们的解释才能对模型生成的内容赋予意义。但在技艺高超的艺术家手中,算法生成可以变得非常有意义,并且很美。潜在空间采样会变成一支画笔,能够提高艺术家的能力,增强我们的创造力,并拓展我们的想象空间。此外,它也不需要专业技能和练习,从而让艺术创作变得更加容易。它创造了一种纯粹表达的新媒介,将艺术与技巧相分离。

Iannis Xenakis是电子音乐和算法音乐领域一位有远见的先驱,   20世纪  60年代,对于将自动化技术应用于音乐创作,他表达了与上面相同的观点:

作曲家从繁琐的计算中解脱出来,从而能够全神贯注于解决新音乐形式所带来的一般性问题,并在修改输入数据值的同时探索这种形式的鲜为人知之处。例如,他可以测试所有的乐器组合,从独奏到室内管弦乐队再到大型管弦乐队。在电子计算机的帮助下,作曲家变成了一名飞行员:他按下按钮,引入坐标,并监控宇宙飞船在声音空间中的航行,飞船穿越声波的星座和星系,这是以前只能在遥不可及的梦中出现的场景。

本章将从各个角度探索深度学习在增强艺术创作方面的可能性。我们将介绍序列数据生成(可用于生成文本或音乐)、DeepDream以及使用变分自编码器和生成式对抗网络进行图像生成。我们会让计算机凭空创造出前所未见的内容,可能也会让你梦见科技与艺术交汇处的奇妙可能。让我们开始吧。

8.1 使用 LSTM生成文本

本节将会探讨如何将循环神经网络用于生成序列数据。我们将以文本生成为例,但同样的技术也可以推广到任何类型的序列数据,你可以将其应用于音符序列来生成新音乐,也可以应用于笔画数据的时间序列(比如,艺术家在  iPad上绘画时记录的笔画数据)来一笔一笔地生成绘画,以此类推。

序列数据生成绝不仅限于艺术内容生成。它已经成功应用于语音合成和聊天机器人的对话生成。Google于  2016年发布的  Smart  Reply(智能回复)功能,能够对电子邮件或短信自动生成一组快速回复,采用的也是相似的技术。

8.1.1 生成式循环网络简史

截至 2014年年底,还没什么人见过  LSTM这一缩写,即使在机器学习领域也不常见。用循环网络生成序列数据的成功应用在 2016年才开始出现在主流领域。但是,这些技术都有着相当长的历史,最早的是 1997年开发的  LSTM算法。这一新算法早期用于逐字符地生成文本。

2002年,当时在瑞士  Schmidhuber实验室工作的 Douglas Eck首次将  LSTM应用于音乐生成,并得到了令人满意的结果。Eck现在是  Google Brain(谷歌大脑)的研究人员,2016年他在那里创建了一个名为 Magenta的新研究小组,重点研究将现代深度学习技术应用于制作迷人的音乐。有时候,好的想法需要 15年才能变成实践。

在 20世纪末和  21世纪初,Alex  Graves在使用循环网络生成序列数据方面做了重要的开创性工作。特别是他在 2013年的工作,利用笔触位置的时间序列将循环混合密度网络应用于生成类似人类的手写笔迹,有人认为这是一个转折点。在那个特定时刻,神经网络的这个具体应用中,能够做梦的机器这一概念适时地引起了我的兴趣,并且在我开始开发    Keras时为我提供了重要的灵感。Graves在  2013年上传到预印本服务器  arXiv上的  LaTeX文件中留下了一条类似的注释性评论:“序列数据生成是计算机所做的最接近于做梦的事情。”几年之后,我们将这些进展视作理所当然,但在当时看到 Graves的演示,很难不为其中所包含的可能性感到惊叹并受到启发。

从那以后,循环神经网络已被成功应用于音乐生成、对话生成、图像生成、语音合成和分子设计。它甚至还被用于制作电影剧本,然后由真人演员来表演。

8.1.2 如何生成序列数据

用深度学习生成序列数据的通用方法,就是使用前面的标记作为输入,训练一个网络(通常是循环神经网络或卷积神经网络)来预测序列中接下来的一个或多个标记。例如,给定输入the cat  is on the ma,训练网络来预测目标 t,即下一个字符。与前面处理文本数据时一样,标记(token)通常是单词或字符,给定前面的标记,能够对下一个标记的概率进行建模的任何网络都叫作语言模型(language  model)。语言模型能够捕捉到语言的潜在空间(latent space),即语言的统计结构。

一旦训练好了这样一个语言模型,就可以从中采样(sample,即生成新序列)。向模型中输入一个初始文本字符串[即条件数据(conditioning  data)],要求模型生成下一个字符或下一个单词(甚至可以同时生成多个标记),然后将生成的输出添加到输入数据中,并多次重复这一过程(见图 8-1)。这个循环可以生成任意长度的序列,这些序列反映了模型训练数据的结构,它们与人类书写的句子几乎相同。在本节的示例中,我们将会用到一个   LSTM层,向其输入从文本语料中提取的 N个字符组成的字符串,然后训练模型来生成第  N+1个字符。模型的输出是对所有可能的字符做 softmax,得到下一个字符的概率分布。这个 LSTM叫作字符级的神经语言模型(character-level neural language model)。

图 8-1 使用语言模型逐个字符生成文本的过程

8.1.3 采样策略的重要性

生成文本时,如何选择下一个字符至关重要。一种简单的方法是贪婪采样(greedy sampling),就是始终选择可能性最大的下一个字符。但这种方法会得到重复的、可预测的字符串,看起来不像是连贯的语言。一种更有趣的方法是做出稍显意外的选择:在采样过程中引入随机性,即从下一个字符的概率分布中进行采样。这叫作随机采样(stochastic   sampling,stochasticity在这个领域中就是“随机”的意思)。在这种情况下,根据模型结果,如果下一个字符是 e的概率为0.3,那么你会有 30%的概率选择它。注意,贪婪采样也可以被看作从一个概率分布中进行采样,即某个字符的概率为 1,其他所有字符的概率都是 0。

从模型的 softmax输出中进行概率采样是一种很巧妙的方法,它甚至可以在某些时候采样到不常见的字符,从而生成看起来更加有趣的句子,而且有时会得到训练数据中没有的、听起来像是真实存在的新单词,从而表现出创造性。但这种方法有一个问题,就是它在采样过程中无法控制随机性的大小。

为什么需要有一定的随机性?考虑一个极端的例子——纯随机采样,即从均匀概率分布中抽取下一个字符,其中每个字符的概率相同。这种方案具有最大的随机性,换句话说,这种概率分布具有最大的熵。当然,它不会生成任何有趣的内容。再来看另一个极端——贪婪采样。贪婪采样也不会生成任何有趣的内容,它没有任何随机性,即相应的概率分布具有最小的熵。从“真实”概率分布(即模型  softmax函数输出的分布)中进行采样,是这两个极端之间的一个中间点。但是,还有许多其他中间点具有更大或更小的熵,你可能希望都研究一下。更小的熵可以让生成的序列具有更加可预测的结构(因此可能看起来更真实),而更大的熵会得到更加出人意料且更有创造性的序列。从生成式模型中进行采样时,在生成过程中探索不同的随机性大小总是好的做法。我们人类是生成数据是否有趣的最终判断者,所以有趣是非常主观的,我们无法提前知道最佳熵的位置。

为了在采样过程中控制随机性的大小,我们引入一个叫作 softmax温度(softmax temperature)的参数,用于表示采样概率分布的熵,即表示所选择的下一个字符会有多么出人意料或多么可预测。给定一个 temperature值,将按照下列方法对原始概率分布(即模型的   softmax输出)    进行重新加权,计算得到一个新的概率分布。

代码清单 8-1 对于不同的 softmax温度,对概率分布进行重新加权

更高的温度得到的是熵更大的采样分布,会生成更加出人意料、更加无结构的生成数据,而更低的温度对应更小的随机性,以及更加可预测的生成数据(见图 8-2)。

图 8-2 对同一个概率分布进行不同的重新加权。更低的温度 =更确定,更高的温度 =更随机

8.1.4 实现字符级的 LSTM文本生成

下面用 Keras来实现这些想法。首先需要可用于学习语言模型的大量文本数据。我们可以使用任意足够大的一个或多个文本文件——维基百科、《指环王》等。本例将使用尼采的一些作品,他是 19世纪末期的德国哲学家,这些作品已经被翻译成英文。因此,我们要学习的语言模型将是针对于尼采的写作风格和主题的模型,而不是关于英语的通用模型。

1.准备数据

首先下载语料,并将其转换为小写。

代码清单 8-2 下载并解析初始文本文件

import keras
import numpy as np

path = keras.utils.get_file(
    'nietzsche.txt',
    origin='https://s3.amazonaws.com/text-datasets/nietzsche.txt')
text = open(path).read().lower()
print('Corpus length:', len(text))

接下来,我们要提取长度为 maxlen的序列(这些序列之间存在部分重叠),对它们进行one-hot编码,然后将其打包成形状为(sequences,  maxlen, unique_characters)的三维Numpy数组。与此同时,我们还需要准备一个数组 y,其中包含对应的目标,即在每一个所提取的序列之后出现的字符(已进行 one-hot编码)。

代码清单 8-3 将字符序列向量化

2.构建网络

这个网络是一个单层LSTM,然后是一个Dense分类器和对所有可能字符的    softmax。但要注意,循环神经网络并不是序列数据生成的唯一方法,最近已经证明一维卷积神经网络也可以成功用于序列数据生成。

代码清单 8-4 用于预测下一个字符的单层 LSTM模型

from keras import layers

model = keras.models.Sequential()
model.add(layers.LSTM(128, input_shape=(maxlen, len(chars))))
model.add(layers.Dense(len(chars), activation='softmax'))

目标是经过  one-hot编码的,所以训练模型需要使用  categorical_crossentropy作为损失。

代码清单 8-5 模型编译配置

optimizer = keras.optimizers.RMSprop(lr=0.01)
model.compile(loss='categorical_crossentropy', optimizer=optimizer)

3.训练语言模型并从中采样

给定一个训练好的模型和一个种子文本片段,我们可以通过重复以下操作来生成新的文本。

(1)给定目前已生成的文本,从模型中得到下一个字符的概率分布。

(2)根据某个温度对分布进行重新加权。

(3)根据重新加权后的分布对下一个字符进行随机采样。

(4)将新字符添加到文本末尾。

下列代码将对模型得到的原始概率分布进行重新加权,并从中抽取一个字符索引[采样函数(sampling function)]。

代码清单 8-6 给定模型预测,采样下一个字符的函数

def sample(preds, temperature=1.0):
    preds = np.asarray(preds).astype('float64')
    preds = np.log(preds) / temperature
    exp_preds = np.exp(preds)
    preds = exp_preds / np.sum(exp_preds)
    probas = np.random.multinomial(1, preds, 1)
    return np.argmax(probas)

最后,下面这个循环将反复训练并生成文本。在每轮过后都使用一系列不同的温度值来生成文本。这样我们可以看到,随着模型收敛,生成的文本如何变化,以及温度对采样策略的影响。

代码清单 8-7 文本生成循环

这里我们使用的随机种子文本是 new  faculty, and the  jubilation reached its  climax when kant。第 20轮时,temperature=0.2的输出如下所示,此时模型还远没有完全收敛。

第 60轮时,模型已几乎完全收敛,文本看起来更加连贯。此时temperature=0.2的结果

如下所示。

cheerfulness, friendliness and kindness of a heart are the sense of the spirit is a man with the sense of the sense of the world of the

可见,较小的温度值会得到极端重复和可预测的文本,但局部结构是非常真实的,特别是所有单词都是真正的英文单词(单词就是字符的局部模式)。随着温度值越来越大,生成的文本也变得更有趣、更出人意料,甚至更有创造性,它有时会创造出全新的单词,听起来有几分可信(比如 eterned和  troveration)。对于较大的温度值,局部模式开始分解,大部分单词看起来像是半随机的字符串。毫无疑问,在这个特定的设置下,0.5的温度值生成的文本最为有趣。一定要尝试多种采样策略!在学到的结构与随机性之间,巧妙的平衡能够让生成的序列非常有趣。

注意,利用更多的数据训练一个更大的模型,并且训练时间更长,生成的样本会比上面的结果看起来更连贯、更真实。但是,不要期待能够生成任何有意义的文本,除非是很偶然的情况。你所做的只是从一个统计模型中对数据进行采样,这个模型是关于字符先后顺序的模型。语言是一种信息沟通渠道,信息的内容与信息编码的统计结构是有区别的。为了展示这种区别,我们来看一个思想实验:如果人类语言能够更好地压缩通信,就像计算机对大部分数字通信所做的那样,那么会发生什么?语言仍然很有意义,但不会具有任何内在的统计结构,所以不可能像刚才那样学习一个语言模型。

8.1.5 小结

  • 我们可以生成离散的序列数据,其方法是:给定前面的标记,训练一个模型来预测接下来的一个或多个标记。
  • 对于文本来说,这种模型叫作语言模型。它可以是单词级的,也可以是字符级的。
  • 对下一个标记进行采样,需要在坚持模型的判断与引入随机性之间寻找平衡。‰处理这个问题的一种方法是使用   softmax温度。一定要尝试多种不同的温度,以找到合适的那一个。

作者:

喜欢围棋和编程。

 
发布于 分类 编程标签

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注