@Lenciel

Stable-Diffusion 试玩

目录

我一直挺关注 人工智能在内容合成(不管是图片、视频、文本,还是程序)方面的进展的1。最近发现 Stability 刚刚发布的 ISM(Image Synthesis Model) Stable Diffusion 可以直接跑在 M1 芯片的 MBP 上,赶紧试玩了一下。

一些结果

Don't touch me... Don't touch me... Don't touch me... Don't touch me... Don't touch me... Don't touch me... Don't touch me... Don't touch me...

各种风格各种题材手到擒来的感觉,是真好…那么 Stable-Diffusion 究竟做了什么呢?

一点历史

用深度学习进行图像合成,可以追溯到 2014 年的一些研究,到今年算是迎来了高峰:4 月份封在家里的时候,先是看到 OpenAI 发布了 DALL·E 2,然后 MetaGoogle 也立刻跟进;接下来 Midjourney 项目让你有一个 Discord 账号就能玩 TTI(Text-To-Image)。

然后就是 8 月 22 号 Stable-Diffusion 的发布。它和 DALL·E 2 最大的不同就是,虽然也有一个商业化的版本 DreamStudio,但是它的代码是开源的,任何人都可以修改和调试它。

因为使用门槛的降低,全世界人民,包括很多艺术家,都在疯狂试玩它。

一点原理

目前大部分 ISM 都是基于latent diffusion的。通俗点儿解释它的主要的过程,就是通过在纯噪声中去识别自己熟悉的形状,与你给它的输入(Stable-Diffusion 里面叫 prompt)里的单词进行匹配,然后强化这些元素,最后「画出」一副图片。

要完成这个过程,首先要在海量数据集上进行训练:比如 Stable-Diffusion 使用了 LAION-5B 的一个子集,包括了 50 多亿来自各种网站(比如 Getty Images、Pinterest、 DeviantArt)的图片。

接下来,使用 OpenAI 的 CLIP (Contrastive Language–Image Pre-training)技术,把单词与图像联系起来。值得注意的是 Stable-Diffusion 大概只花了60w 美金就完成了这部分工作。

通过训练,Stable-Diffusion 会关联一些有色像素点的组合跟某些特定主题之间的联系。然后,很多看了最终产出的人无法相信的是,模型虽然还谈不上对颜色、形状等要素与某个绘画风格或者主题之间深度的理解,仅仅是通过这些训练建立起来的联系,就可以在不复制原数据集中任何图像的基础上,完全从无到有在噪声中生成一副全新的图片

一点缺陷

目前看,最大的问题我感觉有三个2

  • 肢体异常

目前看来,它经常生成两个头,三只手,六根手指这类畸形的图片。所以很多人在生成图片的时候只好增加数量从里面挑选「正常」的。

我感觉这个问题应该是出在训练数据集的标注上。一个好的人体要标注清楚不容易,得按照类似 body>arm>hand>fingers>[sub digits + thumb]> [digit segments]>fingernails 的颗粒度逐一标注。

可以想象「人工智能」里面「人工」这部分的质量,在这里是比较低的。特别是当标注的图片有很多是艺术作品的时候,要非常清晰地标出哪里是手指哪里是手掌哪里是指甲,误差是相当大的。

这部分的问题解决,要靠 OpenAI 的内容过滤这种做法,或者是,更好的数据集了。

  • 分辨率受限

目前有很多 repo 开始把一些 upscaler,比如 txt2imghd,集成进去来解决这个问题。这种「先生成再整容」的做法,可以在一开始不要求那么奢侈的内存,基本上是现在唯一的办法。

  • 自定义程度低

Stable-Diffusion 最值得期待的是你可以在现有模型上进行一些自定义风格的增量的训练。但也可以想象,往现有的模型里面加入你自己的特征,是挺难的,因为这是一个基于 50 亿张图片的训练结果。

目前看比较成功的例子3开销也挺大的(比如 30GB 的显存你有吗?),能搞一搞的主要是对表面材质做一点贴膜,也就是 Textual Inversion。但同时,也可以看到这部分的进展也非常迅速,估计不久就可以用更低的算力实现。。

一点问题

Stable-Diffusion 目前面临了一些法律和道德上的问题。

法律上,因为索引了大量艺术家的图片,它模仿这些人的风格进行创作后,图片的版权怎么算?目前看,有一些艺术家表现得非常愤怒,但好像还找不到一条具体的法律可以去告 Stability。

道德上,如果用 AI 来生成色情的图片或者诽谤的图片会怎样?虽然现在 Stable-Diffusion 提供了一个 NSFW 的校验,把所有色情图片都处理掉,同时还在图片里面加了一个隐藏的水印,但,它是开源的…

  1. 包括 Disco Diffusion、DALL-E 2、Copilot 和 GPT-3 等等。 

  2. 小问题就太多了。首先 Stable-Diffusion 并不官方支持 M1 芯片,所以我自己也 fork 了一个 repo 解决一些 image-to-image 中遇到的问题。 

  3. 比如 waifu-diffusion,用了 56000 张动漫图片进行训练。再比如官方的一个例子。 

为什么数组下标从0开始?

又是个我不知道答案,但又不想用「历史原因」来糊弄的问题。

现成的答案质量都一般

如果用劣质搜索引擎,你会看到一堆下面这样的原因。

但实际上,不是这个原因,也不是这个原因,更不是这个原因

如果搜索手法稍微上档次一点,你可能会看到类似于这篇文章的观点:其实是讲解了 Mike Hoye ——用文章里的话来说——[追根刨地的科学精神]1(http://exple.tive.org/blarg/2013/10/22/citation-needed/)找到的答案。

但是我读了 Mike Hoye 这篇文章,是花了挺大功夫考据,但他的论证过程基本上是:

  1. 最初编程语言中的下标范围要不是从 1 开始,要不就是随意指定的(比如可以是-1:35)
  2. Martin Richards 为了设计一种 IBM 7094 上可以快速编译的专用语言,做了大量优化,其中一个就是让数组下标变成从 0 开始。
  3. 这种叫做 BCPL 的语言,启发了 B 语言,而 B 语言又启发了 C 语言。
  4. C 语言大流行后,这种从 0 开始的数组下标就变成了默认的规矩。

他还举了两个例子说明之前是没有 0 开始但是有 1 开始和任意指定的:

Algol 60 uses one-indexed arrays, and arrays in Fortran are arbitrarily indexed – they’re just a range from X to Y, and X and Y don’t even need to be positive integers.

首先,他弄反了。Algol 60 可以任意指定范围,而 Fortran 才是从 1 开始的。 其次,0 开始的数组也不是 BCPL 的发明:LISP 1.5 这些更早的语言都有从 0 开始的数组。 最后,这个论述方式让我读他有一段话的时候有点懵:

So if your answer started with “because in C…”, you’ve been repeating a good story you heard one time, without ever asking yourself if it’s true.

怎么说呢,你看,基本上他整篇文章浓缩一下,就是在说:

如果有人给你解释,这是因为 C 语言怎样怎样造成的,他就是没有好好研究。我经过了仔细研究才发现,这是因为 C 语言继承了 BCPL 的这种做法,然后流行了,造成的。

那么究竟是怎么回事?

我自己觉得,可能是计算机作为一个学科逐渐形成,里面的标准逐渐固化的一个体现2

对于蒙爷这代人,计算机作为一个学科存在的时间并不长是很反直觉的事情。但实际上,最早从事计算机领域的人,都来自于别的学科:数学、物理、心理学等等。

如果你看数学或者物理的材料,会发现从 0 开始和从 1 开始的索引很常见:比如多项式里大多是从 0 开始,而矩阵预算或者枚举大部分是 1 开始。

因此,在没有标准的阶段,0、1或者是任意指定的范围,都是被广泛使用的。

那么标准为什么逐渐往 0 收拢呢?

BCPL 的作者自己说过:

BCPL was essentially designed as typeless language close to machine code. Just as in machine code registers are typically all the same size and contain values that represent almost anything, such as integers, machine addresses, truth values, characters, etc.

也就是说,Richards 自己解释了,这样的设计更符合计算机的语义,而不是像 Mike 说的那样,仅仅是为了编译效率。

其实在更早的时间,1982 年,Dijkstra 就已经写文章批判了 ALGOL 60(他自己的宝贝)和 Pascal 使用 1 或者任意范围是错误的。

然后,可以看到也是在 C 语言之前, EBDIC 和 ASCII 等都已经是从 0 开始标记的。

再比如同一时期 APL 虽然同时支持 0 或者 1,但 Kenneth Iverson 在他的《A Programming Language》3里面举例时基本上都是 0 开始。

所以,可以看到,随着计算机承担的工作越来越多越来越复杂,大家开始逐渐往最符合机器语义的标准在聚拢:这也使得协作更加简单(你不需要知道引入的库的格式)。

References

  1. 实际上,科学的精神不应该仅仅是竭尽全力找支撑自己论点的论据,还要尽可能站在反方试试自己能不能驳倒自己的论点。 

  2. 但因为不是硬性的标准,所以还是有例外,比如 TLA+ 就仍然是从 1 开始的。 

  3. 《A Programming Language》是本好书。