科学与艺术从来都不是两个互斥的主题。在「神经美学」的指引下,开发者兼艺术家 Leon Fedden 近日在 Medium 上发文介绍了使用 GAN 创造新艺术形式的过程。该项目本身并不复杂,但或许能为我们带来一些关于神经网络的美学思考。
我将在本文中介绍我在 1982 年的短动画《雪人(The Snowman)》上使用神经网络进行的一些实验。我将描述我的方法,提供可以得到类似结果的必要代码并且留下一些有关神经美学的思考。
顺便说一下,如果你已经对生成对抗网络(GAN)很熟悉了,那么可能就无法从本文得到一些技术上的新知识,但你也许会喜欢这些结果;我是以艺术家的身份来完成这个项目的,而不是作为科学家或工程师!
之前的成果
在神经网络中或使用神经网络来表征和渲染图像序列并不是什么新技术,之前也已经有很多艺术作品、论文和博客涉及到了从美学的角度重新合成视频的问题。
Terence Broad 是最早专门做这件事的人之一。和我一样,Terence 也在伦敦大学金史密斯学院做研究,他研究的是艺术实践和机器学习工程的交叉领域。他自动编码《银翼杀手(Blade Runner)》的作品广为人知,我有幸曾在韩国 Art Centre Nabi 看到过这项作品。你可以在他的论文中了解有关该作品的技术细节:https://www.academia.edu/25585807/Autoencoding_Video_Frames,也可阅读他的 Medium 博客了解大概:https://medium.com/@Terrybroad/autoencoding-blade-runner-88941213abbe。
经常写博客的 Arthur Juliani 曾经写了一篇关于使用 Pix2Pix 来重制经典电影的文章。他的关注重点是给经典电影上色以及通过扩大宽高比来填充不可见的空间。尽管他的很多模型都过拟合了,但我们其实并不在意,因为像我们这样的创意人士更关注的是每件作品的美学成果,而不是泛化到新的未曾见过的样本的能力。至少大多数时候是这样——但不要把这句话当成铁律!Arthur 的作品很有意思而且写得很好,你可以在这里读到:https://hackernoon.com/remastering-classic-films-in-tensorflow-with-pix2pix-f4d551fa0503。
Memo Akten 是一位备受赞誉的艺术家,他为使用代码进行创作的艺术家创造了很多有用的工具,我最喜欢的是:https://github.com/memo/ofxMSATensorFlow。他使用来自哈勃太空望远镜的图像过拟合了一个 GAN,让它能根据一个直播摄像头的输入预测图像。另外他的音乐品味也无可挑剔。
Gene Kogan 是我最喜欢的艺术家之一,尽管有时候我感觉他更像是一个机器学习策展人。他是一个非常好而且平易近人的人,他乐于分享他的代码而且经常为艺术机器学习创建高质量的教程,所以如果你之前没听说过他,我强烈建议你在谷歌上搜索一下他的名字。
他通过他安装的 Cubist Mirror 将风格迁移带进了现实世界。这是一个非常好的案例,让我们看到了我们可以如何隐藏整理数据和运行训练脚本的复杂技术过程,从而让其他人也能触及机器学习。这一主题值得再写一篇博客,但你可以查看 Cubist Mirror 的视频。
Parag Mital 有一个非常好的 Kadenze 课程,如果你想学习 TensorFlow,我强烈推荐你看看。他是一个非常棒的人,在用深度学习做很多有意思的工作。在 2013 年的时候,他曾和 Mick Grierson 与 Tim Smith 做了一些基于视觉语料的合成工作:http://pkmital.com/home/corpus-based-artistic-stylization/。尽管这和本博客所用的神经方法不同,但也仍然得到了非常出色的结果,值得一看。
Pix2Pix 是什么?
这篇文章的基础设定很简单:我有一张图像,我想让它看起来像是另一张图像。那么我怎么实现这一目标呢?我们可以使用神经网络来学习这些图像的表征,然后再将其扩展到图像序列(也就是视频)上。
有很多方法都可以做到这一点,但我们在这里关注的是一种特别的神经网络。这种神经网络来自于论文《(使用条件对抗网络的图像到图像转换)Image-to-Image Translation with Conditional Adversarial Networks》,地址:https://arxiv.org/pdf/1611.07004.pdf。但为了方便你了解,我在这里总结了 Pix2Pix 模型的要点。
那篇论文中的模型被称为条件生成对抗神经网络(conditional generative adversarial neural network)。名称确实有点冗长,让我们分解一下。我们知道神经网络是表征输入数据到输出数据之间的映射的一种方式。这些输入和输出因具体问题而各有不同,但其中的关键思想是我们无需明确编码具体的指令或算法,就可以训练一个神经网络来将某些事物表征为另外的事物。
神经网络有很多种类型,在图像领域尤其流行且成功的架构是卷积架构。处理和理解图像是一种非常艰巨的任务;在计算机眼里,图像都是一堆像素值,因此算法必须从这些像素密度值中推理出高度复杂的结构和概念。这些像素值共计这么多个:图像宽度*图像高度*颜色通道的数量(通常是红绿蓝)。如果你将整个图像向右移动一个像素并比较其与原始图像之间的像素差异,那就可能看到两者之间存在很大的不同!卷积神经网络(CNN)擅长处理图像,因为为图像识别设计的这种算法中具备一些先验知识,也就是卷积(convolution)。卷积在图像处理方面已经有很长的使用历史了,也是将一张图像变成另一张图像的方式。
我们可以在上图中看到卷积核(convolutional kernel)的示例。现在假设我们有具备学习能力的核,那么 CNN 更适合处理图像的原因就更清楚一点了。CNN 的学习方式是最小化一个目标函数,比如输入图像与目标输出图像之间的欧几里德距离。但是这可能会出现问题,因为使用欧几里德距离就意味着我们无意中就要求 CNN 求所有可能的输出的平均,因此可能会得到模糊不清的图像。设计目标函数需要很多专业的知识,要是我们的任意目标的目标函数可以自动学习到就好了。
使用生成对抗网络(GAN)允许实现高层面的目标——自动学习到与现实图像有明显区别的输出图像,以作为目标函数。GAN 使用了两个以博弈论的方式协同工作的网络,以某种竞赛的方式来训练彼此。构成 GAN 的两个网络分别是鉴别器和生成器。其中鉴别器必须成功鉴别哪些样本是真实的,哪些样本是伪造的——这些伪造的样本是生成器创建的。模糊图像会很容易被识别为伪造,因此生成器必须学会生成不模糊的图像!随着其中一个网络变得更强大,另一个网络也必须适应和提升。这就是 GAN 训练的难点所在,其训练过程的不稳定性可谓众人皆知。
Pix2Pix 使用了一个条件 GAN,这与传统的 GAN 有些不同。两者的差异是条件 GAN 的鉴别器的输入包含生成器的输入图像以及真实的或合成的输出图像,然后它必须确定该输出图像是真实的还是伪造的。
在经典的生成器和鉴别器网络的实现方式上存在一些修改方法,大部分是层之间的 skip 连接,这被称为 U-Net。这有很多好处,比如让低层面的卷积信息到达生成器解码器中的高层面的去卷积层。另外还有根据生成器和鉴别器的表现生成的梯度的 L1(绝对)损失,这有助于学习得到与输入图像有可感知的相关性的结果。
你可以在这里看到 Pix2Pix 的一个非常好的 TensorFlow 实现:https://github.com/affinelayer/pix2pix-tensorflow,而且和我在网上找到的很多代码不一样,这一个真的有效!
一些考虑
重要的深度学习论文经常忘记得到这些结果的计算机。我们经常通过社交网络或其它渠道了解炫酷的新型深度学习技术,我们看到生成式机器学习模型取得了巨大的成果。这些模型往往来自谷歌等有能力使用丰富的计算资源的组织机构。黑客、艺术家和实践者等却往往难以得到那样出色的结果,因为他们往往没有数以百计的并行 GPU。WaveNet、SampleRNN 和很多强化学习问题就是其中的部分例子。
因此,突出强调人们能在家里自己完成的实验是很重要的,而且还不能让我们因为租用或购买新硬件而破产。本项目的所有工作都能在我的台式机的老旧 GPU 上花几天时间完成,我对此是相当惊讶的,因为这是一个非常复杂的表征学习问题。
获取数据
神经网络革命的一大关键基础是丰富的数据。在当今这个信息时代,人类创造的数据源也越来越多。手机和软件不断产生大量不同格式和结构的数据,有创造力的技术人员和人工智能实践者需要想办法利用这一点。
使用 YouTube、Twitter 或你能想到的任何免费网络服务是为你的项目收集数据的好方法。youtube-dl 是我很喜欢的一个实用工具,能让视频下载更简单:https://github.com/rg3/youtube-dl
youtube-dl https://www.youtube.com/path/to/your/video/here
有了视频之后,你需要得到其中的帧。我们可以使用实用工具 ffmpeg 来做到这一点:https://www.ffmpeg.org/。我们可以使用比例参数来控制帧的大小——这里的视频宽度是 640 像素,高度是 360 像素。
ffmpeg -i downloaded_file.mp4 -vf scale=640x360 path/to/frames/folder/image_%04d.png
运行这行代码会在最后指定的位置创建很多来自你的视频的图像。
上色
我尝试的第一件事是给有雪人的帧自动上色。我让模型过拟合数据,结果基本上和源材料一样。尽管这本身也算是个成就,但这个神经网络输出的主观美学质量并不值得称道。
下面是该神经网络的输出。我向其馈送黑白的帧,然后让其返回图像。这是我得到的上色后的视频。
Canny 边缘检测
变换视频帧的方式有很多种,尤其是减少输入信号中存在的信息。这样做我们是在强迫我们的网络犯错,这在美学上是很有趣的。
如果我们还想让新的完全没见过线条具备《雪人》插画的风格,那在我们的视频帧上使用边缘检测器是一个完美的变换。原来的论文参考了创造了受欢迎的 edge2cat 的 Christopher Hesse。我前面提到过的 Memo Atken 也在他的工作中使用了边缘检测,你可以在下面看到:
我们也可以使用 OpenCV 做到类似的事情,其中有一个 Canny 边缘检测的优良实现。使用这个方法,我们可以将上色后动画中的雪人变成简单的线条。然后我们可以使用 Pix2Pix 来学习两者之间的映射。首先我们看看 Canny 边缘检测的结果:
要得到这些帧,我们可以写一个简单的 Python 脚本来生成图像。这个脚本是 Canny 边缘检测的无参数应用,代码基于这篇博客:https://www.pyimagesearch.com/2015/04/06/zero-parameter-automatic-canny-edge-detection-with-python-and-opencv/。你只需要将 images_directory 变量设置成你用 ffmpeg 制作的视频帧的文件夹即可,然后将 target_directory 变量设置成你希望保存得到的线边缘图像的路径。注意这些图像已经进行了反色处理(第 32 行),从而让黑色线条出现在白色背景上。
import numpy as np
import cv2
import os
def auto_canny(image, sigma=0.33):
median = np.median(image)
lower = int(max(0, (1.0 - sigma) * median))
upper = int(min(255, (1.0 + sigma) * median))
return cv2.Canny(image, lower, upper)
def preprocess(image_path):
image = cv2.imread(image_path)
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
return cv2.GaussianBlur(gray_image, (3, 3), 0)
images_directory = "snow2/images"
target_directory = "snow2/edges"
if not os.path.exists(target_directory):
os.makedirs(target_directory)
files = os.listdir(images_directory)
amount_images = len(list(images_directory))
counter = 0
for file_path in files:
if file_path.endswith(".png"):
image_path = os.path.join(images_directory, file_path)
image = preprocess(image_path)
edge = 255 - auto_canny(image)
target_path = os.path.join(target_directory, file_path)
cv2.imwrite(target_path, edge)
print(target_path, end="\r")
counter += 1
一旦我们根据图像生成了线条绘画,我们就可以使用 Pix2Pix 算法的 TensorFlow 实现中的实用功能来创造一个数据集。
cd pix2pix-tensorflow
python3 tools/process.py --input_dir path/to/edges/images --b_dir path/to/original/images --operation combine --output_dir edge2image
现在我们有了可以使用的图像数据集,我们就可以开始训练了!按照这个 TensorFlow 模型在 GitHub 上的指令办就行了。
组合到一起
为了实现这个模型的可视化,我使用下面的代码对内容进行了水平堆叠。这意味着结果得到的帧将由 3 张图像组成,其中左边的是输入的线条绘画,中间的是 Pix2Pix 生成的图像,右边的是来自原动画的帧。你需要将起始帧和最终帧设置成 ffmpeg 命令得到的结果。
start_frame =
end_frame =
for image in range(start_frame, end_frame):
file_name = 'edge2image_test/images/image_{num:04d}'.format(num=image)
input_file = cv2.imread(file_name + '-inputs.png')
output_file = cv2.imread(file_name + '-outputs.png')
target_file = cv2.imread(file_name + '-targets.png')
save_file = np.hstack((input_file, output_file, target_file))
save_name = file_name + '.png'
cv2.imwrite(save_name, save_file)
os.remove(file_name + '-inputs.png')
os.remove(file_name + '-outputs.png')
os.remove(file_name + '-targets.png')
现在我们将视频每一帧的三张图像(输入、输出、目标)都堆叠到了一起,然后我们可以使用 ffmpeg 将这些图片再聚合成一段新视频。-r 标签设置的是视频的帧率,-s 标签设置的是宽度和高度,其它还有处理编码方式和质量的——除非你别有需求,否则就不要动它们了。
ffmpeg -r 25 -f image2 -s 640x360 -i image_%04d.png -vcodec libx264 -crf 25 -pix_fmt yuv420p name_of_output_file.mp4
现在我们得到模型的视频了,现在我们可以查看这个模型的输出!对于这个项目而言,其它有用的 ffmpeg 命令还有将音频剥离视频,然后再将其添加回来,我将这个工作的代码分别放在下面的第一二行。
ffmpeg -i video.mp4 -f mp3 -ab 192000 -vn music.mp3
ffmpeg -i video.mp4 -i music.mp3 -codec copy -shortest video_with_audio.mp4
结果
在仅仅训练了 3 epoch 之后,结果就已经很有趣了。再次说明一下,最右边的图像是原始的动画帧,左边是右边图像的 Canny 边缘版本。中间的图像是由条件 GAN 在左边图像的基础上预测得到的图像。
该网络已经能成功涂绘它在动画中看见的常见物体,比如男孩的姜黄色头发和雪。有趣的是它在很多表面都犯错了,比如墙、地板和雪,它会在上面叠加静态的雪花图案。出现这种雪图案的原因可能是鉴别器学习到这是一个重要的现象,所以生成器需要将其放入到自己生成的图像中。
如果我们进一步训练,在 9 epoch 之后,结果是这样。这个视频添加了音乐:
我们还可以使用我们过拟合的模型做一件事。我们可以使用之前提到的 Canny 边缘检测处理新的视频源(比如我坐在沙发上),然后看它能预测得到怎样的结果。
对于这个视频,我最喜欢的一点是影片中的我也有了电影中男孩那样的姜黄色头发!很显然我们使用人工或传统技术难以创造出的这样的全新有趣的动图。
神经美学
Gene Kogan 有一个名为《神经美学(The Neural Aesthetic)》的演讲,尽管他通常亲自演讲,但你也可以在这里查看:https://www.youtube.com/watch?v=mr6ISQ33V9c。
在这些神经美学的演讲中,他展示了他正在制作和正在策展的作品,这些作品探索了机器学习在美学方面的意义。这种聚集反映了创造过程的人工智能技术的方法有助于理解本博客的背景;这篇博客文章仅仅是复制、解释和演示其他人已经完成过的事情,而且也只是沧海一粟而已。
美学是对艺术、美丽和品位的本质的探索,可以用不同形式的媒介创造。我们正处在一个激动人心的时代,可以用机器学习来处理媒体内容,探索我们可以如何使用连接主义神经过程来合成引人入胜的新型艺术材料。当然,在艺术过程中使用新技术不是什么新鲜事;曾经有个时候在洞壁上吹上矿物颜料是最先进的技术。
之前一种用于创造的技术
在当今的科学和艺术前沿,使用计算学习过程作为艺术媒介的有趣方式越来越多,质量也越来越来高;这方面的发展速度惊人,就像我们已经习以为常的机器学习领域的超快发展速度一样。我们这些富有创造力的技术宅可以使用这些方法来创造用于生成新形式美学材料的抽象的新方法。
作为创意人工智能社区的一员,要靠我们来设计应用这些神经模型的新方法以及思考新架构和数据集,以便进一步扩展我们能用计算过程完成的艺术的疆域。
(原文有很多视频,详情请查看原文。)
原文链接:https://medium.com/@LeonFedden/the-snowgan-8a97cd75338d