返回列表

4th Place Solution

549. Stable Diffusion - Image to Prompts | stable-diffusion-image-to-prompts

开始: 2023-02-13 结束: 2023-05-15 AIGC与多模态 数据算法赛
作者: Gerwyn(第4名)
发布时间: 2023-05-16

祝贺所有获奖者!感谢 Kaggle 举办如此有趣的竞赛(为提出 1.6 万条提示词点赞)!同时也向数据科学社区中所有的开源贡献者致敬。

最终提交笔记本

概要

方案 公开榜 私有榜 运行时间
(1+2+3) 文本候选生成 0.614X 0.612X 6 小时
(4) ViT 编码器 0.644X 0.641X 3 小时
加权集成(CV 最佳:0.4, 0.6) 0.646X 0.643X 9 小时
加权集成(LB 最佳:0.25, 0.75) 0.648X 0.645X 9 小时

文本候选生成

  • 文本检索:使用预训练的 CLIP-bigG 对 5600 万个预计算的文本嵌入进行 top-k 穷尽搜索,随后使用预训练的 CLIP-H14 进行余弦相似度过滤。
  • CLIP 询问器:对 160 万个“提示组件”的预计算 CLIP-bigG 文本嵌入进行 top-k 穷尽搜索。将检索到的字符串组件拼接成提示。
  • CoCa:使用 LAION 的实现

ViT 编码器

两阶段微调过程:1. DDB;2. 生成的 700 万张图像。从以下检查点初始化:CLIP-ViT L、H(同上)、G、bigG(同上)。

数据集

标题集(文本检索 + 图像生成)

总计:约 520 万,生成图像:约 520 万张

WIT(文本检索 + 图像生成)

总计:约 250 万,生成图像:约 100 万张

生成的提示(文本检索 + 图像生成)

总计:约 1000 万以上,生成图像:约 100 万张

我还使用 text2image-prompt-generatorMagicPrompt 生成了更多提示。

YFCC 100M 开放子集(仅文本检索)

总计:约 400 万

Laion CoCo(仅文本检索)

总计:2700 万(随机抽样)

Datacomp Small(仅文本检索)

总计:500 万

提示组件(仅询问器使用)

总计:160 万个组件

文本预处理

大多数 stable-diffusion 提示都非常混乱,包含许多不可读/不必要的单词和标点符号。我手动查看了样本并尝试进行清理。(此笔记本中的函数

  • 去除近重复项(使用句子变换器的余弦相似度)对文本检索解决方案效果很好;在保持得分相近的同时,数据集大小减少了 10-20%。

交叉验证

从标题集中抽取了 3.2 万个提示。在允许某些提示因生成不同图像而重复出现后,总数约为 3.4 万。

解决方案与训练

文本检索

此步骤未进行训练。

我通过计算图像 CLIP-bigG 嵌入与预计算文本嵌入之间的余弦相似度,选择了前 60 个候选。然后,对每个候选使用 CLIP-H14 重新计算余弦相似度,并过滤掉相似度 ≤ 0.29 的候选。

为了在推理时对 5600 万个嵌入进行穷尽搜索,我采用了以下技术:

  • 将我的数据集按上述列出的不同部分进行划分(数据集分块)。
  • 对所有部分使用 PCA 降维至 768 维,Laion CoCo 部分使用 512 维。
  • 内存映射的 float16 格式 numpy 数组。
  • 双层分块方法。外层循环将 1.6 万个测试图像嵌入拆分为 768 个块,内层循环将文本图像嵌入拆分为 1024×1024 个块。
  • 在 GPU 上使用 `torch.mm` 计算余弦相似度。

CLIP 询问器

我设计了 14 种从组件构建提示的模板。例如,['adjectives', 'nouns', 'verbs', 'openprompts_modifiers', 'adverbs', 'movements']。对于每个模板,我从每个组件中选取前 8 个候选,总共得到 112 个文本候选。

最初,我尝试使用随机搜索,结合提示组件的排列组合以及组件数量进行实验。然而,我发现这种方法会导致在 CV 集上过快过拟合。因此,我决定使用从 EDA 中手动筛选出的 14 个模板。

CoCa 模型

这部分影响较小。我尝试对其进行微调,但相比预训练版本并未带来显著提升。

ViT 编码器

我将批量大小保持在约 160,然后根据模型大小解冻相应的层:

  • L:从第 2 层开始解冻
  • H:从第 14 层开始解冻
  • G:从第 24 层开始解冻
  • bigG:从第 36 层开始解冻

第一阶段:DDB(经过文本预处理后剩余约 190 万张,使用其原始图像)
第二阶段:自生成的 700 万张图像
两者均使用学习率:4/5e-5,训练 3/4 个周期,使用 CosineEmbeddingLoss。

未奏效的方法:添加 dropout(/ 空间 dropout)、增加全连接层、周期集成、改变 patch 大小。

测试时增强(TTA)

在最后的努力中,我通过采用不同的图像均值和标准差归一化作为测试时增强(TTA),成功实现了 0.02X 的提升。我使用了预训练统计信息以及根据 32K 测试集计算出的统计信息(此处是如何计算的 notebook)。我进行了两次推理并取结果的平均值,然后在四个 ViT 编码器之间进行简单平均。

加权平均(文本候选 + ViT 编码器)

  • 在进行加权平均之前,我对 ST 嵌入(来自文本候选)和 ViT 嵌入进行了归一化。
  • 我的 CV 仅依赖于一个折。作为风险缓解策略,我提交了一次基于最高 CV 得分的权重(文本候选:0.4,ViT:0.6),以及另一次基于最高 LB 得分的权重(文本候选:0.25,ViT:0.75)。
同比赛其他方案