CoTyle 论文阅读记录
同事让我有空看看这个,我就简单读了一下。
项目地址
概况
这个模型做到了使用 code(编码而非代码)控制图像风格。也就是说,在 code 相同的情况下,改变 prompt 和种子可以生成一组风格相似的图片。
粗略看了下 GitHub 首页,不过它对不同风格之间似乎并没有一种可以查表的方式,让人自己选择需要什么风格;code 的数值也非常大,看起来和 seed 一样需要”抽卡”。所以我怀疑它的侧重点并不在于引导单张图片风格化生成,而是维持一组图片保持同样的风格(同样的 code)。
好奇的问题
- 这看起来似乎就是一个类似 CLIP 的东西。
- 同事好奇的问题:Figure 4 中用红框圈出了 “suboptimal style consistency.”,这个一致性是怎么判断的?
- 有没有办法优雅地上线?
后来又花时间把论文完整读了一遍,一些当初的疑问也有了答案。
它是为了解决什么问题
要让 AI 画一组图,要求”风格一致”。传统做法有几种:
- 写很长的 prompt 描述风格 —— 但每次理解都不太一样,一致性差
- 扔一张参考图 —— 可以,但你只能复现已有风格,创造不了新风格
- 训一个 LoRA —— 得分享权重文件,麻烦
CoTyle 的想法很简单:风格这东西,能不能就用一个数字来代表?
你给我数字 12345,我就知道你要什么风格。换个数字 67890,就是另一种风格。同一个数字,不管画猫还是画城市,风格都一样。
听起来很神奇,但问题来了:这个数字和风格之间,有什么对应关系?
答案是:没有对应关系。
这才是关键。这个数字不是”风格索引”,不能像查字典一样说”我要赛博朋克风格,给我 code=XXX”。它更像一个掷骰子的方式——同一个掷法,每次都落在同一个风格上;但你看了掷骰子的参数,猜不出会落在哪里。
所以实际生成图片时还是得抽卡,试不同的 code,看看哪个风格喜欢。但一旦找到喜欢的,就能用这个 code 生成任意内容的图,风格始终一致。
它是怎么做到的?
整体思路分三步。
第一步,造一本”风格词典”
论文先收集一堆图片,训练一个 Style Codebook。这个码本里有几万个”风格词”,每个词是一个向量,代表某种风格特征。
但在说这个码本之前,得先解释一下 VQ-VAE,因为 CoTyle 的 Style Codebook 其实是从 VQ-VAE 借来的概念。
先说说 VQ-VAE 是什么
普通的自编码器(AE)大家应该都见过:
1
图片 → 编码器 → 连续向量 z → 解码器 → 重建图片
问题是这个向量 z 是连续的,可以是任意小数,空间无限大。你想随机生成一张图,根本不知道从哪里采样。
VQ-VAE 的想法是:把连续向量”量化”成离散编码。
它加了一个”码本”(codebook),就是一个查找表:
1
2
3
4
5
索引 0 → [向量 A]
索引 1 → [向量 B]
索引 2 → [向量 C]
...
索引 K-1 → [向量 Z]
流程变成:
1
2
3
4
5
6
7
8
9
图片 → 编码器 → 连续向量 z
↓
在码本里找最近的向量
↓
返回那个向量的索引(比如索引 42)
↓
用索引 42 查码本,得到量化向量 z_q
↓
解码器 → 重建图片
这样图片就变成了一串”离散编码”。这些编码可以像语言一样处理——你就能用 GPT 这样的模型来生成新图片了。
VQ-VAE 的码本是怎么训练的?目标是重建得越像越好。所以码本学到的每个向量,都是重建图像需要的”视觉元素”——比如某个向量代表”一条横线”,另一个代表”某个颜色的圆弧”。
CoTyle 的 Style Codebook 有什么不同?
结构一样,都是一个查找表。但目标完全不同。
VQ-VAE 想重建图像,所以同一只猫和同一只狗会被编码成不同的向量——因为它们的视觉元素不同。
CoTyle 想提取风格,所以同一只猫和同一只狗,如果风格相同(比如都是水彩画),会被编码成相似的向量。
训练方式也不一样。VQ-VAE 用重建损失,CoTyle 用对比损失:
1
2
两张图风格相同 → 让它们的编码距离近
两张图风格不同 → 让它们的编码距离远
论文原话:
“its purpose is to encode images with identical styles but different content into the same distribution, while encoding images with divergent styles into different distributions” — Sec 3.1
有个细节:光用对比损失的话,码本会”塌缩”——所有图片都被映射到同一个索引,因为这样”同风格”的约束永远满足,loss 最低。论文发现必须加一个重构损失,强制风格 embedding 不要离原始特征太远,这样码本的每一行才会学到有意义的东西。
第二步:学一个”风格写诗机”
有了码本之后,每张图片都能转换成一串”风格词”。
为什么要这一步?因为我们不想只能从已有图片里提取风格,我们要生成全新的风格。
论文用一个自回归模型来学这些风格词的分布。比如它可能发现:”风格词 A 经常和风格词 B 一起出现”、”风格词 C 后面很少跟风格词 D”。学会了这些”语法”之后,就能自己写出没见过的风格组合。
还有个细节:码本里某些索引被用得特别频繁,论文发现这些高频索引代表的是”普通、没特色”的风格信息。所以在推理时会用 suppression coefficient 把这些高频索引的概率压下去,鼓励采样更独特的风格组合。
第三步:推理
1
2
3
4
5
6
7
8
9
10
11
输入一个数字 code(比如 12345)
↓
这个数字作为随机种子
↓
从码本里随机采样第一个风格词(种子固定,结果就固定)
↓
自回归模型生成后续的风格词
↓
查码本,把风格词拼成风格 embedding
↓
喂给扩散模型,生成图片
关键:同一个 code,每次都会采样到同样的风格词序列。所以风格是复现的。
但你看 code 的数字,完全猜不出对应什么风格。这就是为什么说是”抽卡”。
回答当初的疑问
问题 1:这看起来类似 CLIP?
读完论文发现不一样。CLIP 是图文对齐,CoTyle 是纯图片的”风格聚类”。而且 CoTyle 输出的是离散的”风格词”,不是连续向量,这样才能用自回归模型生成。
直觉”侧重批量一致风格生成”倒是对的——论文自己也把 consistency 放在第一位。
问题 2:那个 “suboptimal style consistency” 怎么判断的?
论文用了一个叫 CSD 的指标。简单说就是:同一个 code 生成多张图,用预训练的风格编码器提取特征,算这些特征的相似度。如果 variance 太大,说明一致性不够。
图里红框标注的是 Midjourney 的失败案例——同一个 code,生成的图风格跑偏了。
一点想法
这个工作的核心贡献是把”风格”从文本描述、参考图、LoRA 这些复杂的形式里抽象出来,变成一个简单的数字。
代价是这个数字本身没有语义——你不能像选 Pantone 色卡那样选风格,只能试。但对应用场景来说,这可能反而是优势:用户只管记住喜欢的数字,不需要懂风格的专业术语。
有意思的想法,但估计被 nano banana 干碎了,毕竟用提示词就能得到风格保证。可能这也是过了半年 kwai-kolors还没有 release the commercial version of CoTyle 的原因,这么看来做基座压力也很大,不是 sota 就没有意义了。
参考资料
- 论文: arXiv:2511.10555
- 代码: GitHub
- Demo: HuggingFace Spaces
