返回列表

12th place solution - GPUs go Brrr

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

开始: 2023-02-13 结束: 2023-05-15 AIGC与多模态 数据算法赛

12th place solution - GPUs go Brrr

作者:Javier Martín
发布时间:2023-05-16
比赛排名:第12名

太棒了!这是我第一次 solo 获得金牌!感谢 Kaggle 组织这场比赛!和以往一样,这是一次充满乐趣但也极具挑战的比赛。也非常感谢我的雇主 freepik.com 提供的计算资源。仅靠我自己的设备绝对无法完成!

我的策略始终是在比赛的3个月时间里尽可能多地收集图像并训练尽可能多的模型。

数据

我生成了大约440万张图像。最初我使用了组织者提到的脚本,但在比赛进行几周后,我采用了 pytorch 2.0 和 diffusers 库的若干优化,例如内存高效注意力和 torch.compile,并基于 Pedro Cuenca 的 加速版 diffusers 博客文章 推出了自己的生成器。我使用了与组织者相同的生成流程(至少公开的部分):生成768px图像,然后缩放到512px,使用相同的 CFG、噪声采样器等。虽然直接生成512px图像会快得多,但我推测前者能更好地近似测试集的域特征。我将图像以无损格式(WebP)保存。使用 JPG 更节省空间,但会导致 LB 分数略有下降。

我尝试收集尽可能多样化的提示,包括来自 LAION、CoCo 等数据集的真实图像说明和爬取的提示(DB2, OP, MP):

  • 概念说明 (~200万)
  • 开放提示 (~120万)
  • CoCo (~40万)
  • Magic Prompt (~40万)
  • DiffusionDB2 (~40万)
  • LAION 美学 (~10万)

我采用了 @xiaozhouwang 提出的 过滤余弦相似度 >0.9 的图像 的方法,因为许多提示(特别是从 discord 等渠道爬取的)只是对另一个提示的重新表述。我还丢弃了超过77个 token 的长提示。去重对 CV 和 LB 都有显著提升。

2023-08-14 更新:完整训练/验证数据集链接

单模型

我用来自开放提示数据库的10万个均匀分布样本尝试了许多架构,然后选出以下模型进行最终训练:

  • eva_giant_patch14_336 (10亿参数)
  • eva02_large_patch14_448 (3亿参数)
  • eva02_large_patch14_448.mim_m38m_ft_in22k (3亿参数)
  • vit_huge_patch14_clip_224.laion2b (6.3亿参数)
  • vit_large_patch14_clip_336.openai_ft_in12k_in1k (3亿参数)

我使用 timm 的预训练权重,搭配一个简单的 Linear(x, 384) 输出层和负余弦相似度损失。其中一些模型在比赛期间才发布,非常感谢 Ross Wightman 的杰出贡献。

我使用 OneCycleLR 调度器训练了3个 epoch,大多数模型的学习率为 lr=1e-6,优化器使用 Adam、bitsandbytes 的8位 Adam 或8位 Lion(取决于模型和 deepspeed stage 2 分布式训练)。总体而言8位训练效果良好,但某些模型只有在使用常规 Adam + AMP (bfloat16) 时才具有竞争力。每个架构使用不同的随机种子训练。在最后几周,我重新训练了10个较弱的模型,采用恒定学习率+预热策略,因为某些模型相比 OneCycleLR 版本在 CV 和 LB 上都有提升,但并非总是如此,因此我保留了 OneCycleLR 中表现更好的检查点。

训练全部25个模型的总计算量约为215 gpu*天,另有约85 gpu*天用于失败/次优/中断的训练。使用的GPU主要是 RTX 3090。

验证策略

为了改善 CV/LB 相关性,我使用 KMeans 将嵌入向量聚类为100个簇,并按簇分组进行20%留出样本的 K-fold 验证。我的 CV 分数始终比单折模型的 LB 高9%到17%,平均高出13%。

集成

对于最终集成,我训练了一个非常简单的 nn.Linear(5, 1, bias=False) 来寻找最优的融合系数。我尝试过更复杂的样本级策略,如带架构提示的 transformer 编码器或 MLP,但线性融合效果更好。

在最后几个小时,我多出一个提交名额,因此只提交了 EVA 模型(去掉了两个较弱的 ViT 模型),结果证明这是得分最高的提交。

痛点

对我来说最困难的部分是管理如此多的模型,因为我不是一个很有条理的人。此外,某些模型的训练长达9天!墨菲定律经常应验,我经历了各种中断:

  • 停电
  • NVMe 错误
  • 检查点保存时磁盘已满(哎哟)
  • Linux OOM 杀手进程
  • GPU 过热降频
  • 高优先级 GPU 任务(例如其他人想用电脑做实际工作)
  • 甚至 tmux 也两次崩溃

如果必须选一个最讨厌的崩溃,那大概是 tmux 的。

难以想象训练大型 LLM 数月时间会遇到什么困难!

我使用了 pytorch lightning 并在每个 epoch 和每小时设置检查点回调。但遗憾的是,每小时检查点(或任何中期检查点)无法正确恢复,因为数据加载器无法确定性地快进到完全相同的位置。这会导致某些图像被重复处理,而另一些则完全跳过,从而降低 CV 分数。

未奏效的方法

  • LORA(训练快但竞争力不足)
  • 许多其他架构(ConvNext XL, XXL, efficientnet v2, 更小 ViT, BEiT, BEiTv2, 普通 resnets 等)
  • Patch dropout(训练很快但竞争力不足)
  • Tensor-rt(简直是噩梦)
  • 对比损失替代负余弦相似度损失
  • GPT-3.5/-4 提示生成(存在提示服从性和主题重复问题,但我没太深入研究)

致谢

再次感谢 Ross Wightman(timm)、pytorch 论坛的 @ptrblck、我的雇主 freepik.com(目前在招人,顺便提一下!)以及比赛组织者。

同比赛其他方案