模型简介
模型特点
模型能力
使用案例
🚀 LibreFLUX:一个免费的、去蒸馏的FLUX模型
LibreFLUX是FLUX.1-schnell的Apache 2.0版本,它提供了完整的T5上下文长度,使用了注意力掩码,恢复了无分类器引导,并且大部分FLUX美学微调/DPO已被完全移除。这意味着它比基础的FLUX模型要“丑”得多,但它有可能更容易针对任何新的分布进行微调。它牢记开源软件的核心原则,即它应该比专有解决方案更难使用、更慢且更笨重,并且其美学风格被困在21世纪初的某个阶段。
图片中一名男子自信地站立着,穿着一件简单的T恤,T恤正面印着一条幽默又古怪的信息:“我把快速的FLUX模型去蒸馏成了一个缓慢又丑陋的模型,而我只得到了这件愚蠢的T恤。”男子的表情既透露出一丝自豪,又带有一丝讽刺,仿佛他意识到了这句话背后的复杂性,但又对这微不足道的回报感到好笑。背景色调中性,使人们的注意力集中在男子和他的T恤上,这件T恤以一种滑稽而低调的方式调侃了技术过程或复杂问题解决过程中令人沮丧且往往虎头蛇尾的本质。
🚀 快速开始
推理
要使用该模型,只需使用diffusers调用自定义管道即可。目前它适用于diffusers==0.30.3
版本,后续会更新以适配最新版本的diffusers。该模型在CFG比例为2.0到5.0时效果最佳,所以如果你生成的图像模糊或有奇怪的阴影,可以尝试降低CFG比例(在diffusers中为guidance_scale
)。或者,你也可以在最初的几个时间步关闭CFG(在自定义管道中设置no_cfg_until_timestep=2
),然后使用更高的CFG比例。
# ! pip install diffusers==0.30.3
import torch
from diffusers import DiffusionPipeline
pipe = DiffusionPipeline.from_pretrained(
"jimmycarter/LibreFLUX",
custom_pipeline="jimmycarter/LibreFLUX",
use_safetensors=True,
torch_dtype=torch.bfloat16,
trust_remote_code=True,
)
# 高显存情况
prompt = "Photograph of a chalk board on which is written: 'I thought what I'd do was, I'd pretend I was one of those deaf-mutes.'"
negative_prompt = "blurry"
images = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
return_dict=False,
# guidance_scale=3.5,
# num_inference_steps=28,
# generator=torch.Generator().manual_seed(42),
# no_cfg_until_timestep=0,
)
images[0][0].save('chalkboard.png')
# 如果你显存小于等于24GB,可以尝试:
# ! pip install optimum-quanto
# 然后
from optimum.quanto import freeze, quantize, qint8
# 量化和冻结操作需要一点时间,请耐心等待。
quantize(
pipe.transformer,
weights=qint8,
exclude=[
"*.norm", "*.norm1", "*.norm2", "*.norm2_context",
"proj_out", "x_embedder", "norm_out", "context_embedder",
],
)
freeze(pipe.transformer)
pipe.enable_model_cpu_offload()
images = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
device=None,
return_dict=False,
do_batch_cfg=False, # https://github.com/huggingface/optimum-quanto/issues/327
# guidance_scale=3.5,
# num_inference_steps=28,
# generator=torch.Generator().manual_seed(42),
# no_cfg_until_timestep=0,
)
images[0][0].save('chalkboard.png')
对于在ComfyUI中使用,这里提供了一个单一的transformer文件,但需要注意的是,ComfyUI目前不支持注意力掩码,因此生成的图像质量可能会下降。
微调
可以使用SimpleTuner和--flux_attention_masked_training
训练选项轻松对该模型进行微调,同时需要使用jimmycarter/LibreFlux-SimpleTuner中的模型。这是一个移除了自定义管道的相同模型,因为自定义管道目前会干扰SimpleTuner对其进行微调。除了全秩微调,SimpleTuner还通过LyCORIS对参数高效微调提供了广泛支持。进行推理时,请使用本仓库中的自定义管道,并按照SimpleTuner中的示例来合并你的LyCORIS权重。
from lycoris import create_lycoris_from_weights
pipe = DiffusionPipeline.from_pretrained(
"jimmycarter/LibreFLUX",
custom_pipeline="jimmycarter/LibreFLUX",
use_safetensors=True,
torch_dtype=torch.bfloat16,
trust_remote_code=True,
)
lycoris_safetensors_path = 'pytorch_lora_weights.safetensors'
wrapper, _ = create_lycoris_from_weights(1.0, lycoris_safetensors_path, pipe.transformer)
wrapper.merge_to()
del wrapper
prompt = "Photograph of a chalk board on which is written: 'I thought what I'd do was, I'd pretend I was one of those deaf-mutes.'"
negative_prompt = "blurry"
images = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
return_dict=False,
)
images[0][0].save('chalkboard.png')
# 可选操作,保存一个合并了LyCORIS权重的管道:
# pipe.save_pretrained('/path/to/output/pipeline')
✨ 主要特性
去蒸馏的FLUX模型
LibreFLUX是对FLUX.1-schnell进行去蒸馏处理后的模型。FLUX的蒸馏模型是通过使用教师模型(未蒸馏)的输出来训练学生模型(蒸馏),并结合一些技巧,如对抗网络而创建的。去蒸馏后的模型虽然图像生成时间比蒸馏模型长近一倍,但可以免费用于商业用途,训练也相对容易,并且可能更具创造性。
恢复原始训练目标
通过在正常的流匹配目标上使用均方误差(MSE)损失进行训练,模型可以重新学习如何实现原始的训练目标。不过,LibreFLUX和OpenFLUX.1似乎都未能完全去蒸馏该模型,当CFG比例大于4.0时,这两个模型生成的图像会出现奇怪的阴影或模糊现象。
注意力掩码
FLUX模型使用T5-XXL文本模型为文本到图像任务提供大部分条件信息。它们会将文本填充到256(schnell)或512(dev)个标记,填充标记会被模型用于存储信息。通过在注意力计算时屏蔽这些填充标记,可以避免长提示导致的性能下降。作者已经实现了注意力掩码,并在微调时启用了该功能,使得用户可以使用完整的512个标记序列长度。
快速去蒸馏并适配小显存GPU
为了避免对大型的FLUX模型进行全秩微调,作者最初使用quanto以int8精度训练模型,并使用了6亿参数的LoKr。通过自定义的初始化函数,使得LoKr的损失下降速度加快了一倍。
选择更好的层进行LoKr训练
FLUX模型的“norm”层具有特殊性,在微调时这些层的变化较大。同时,根据研究表明,Transformer网络的大部分计算工作通常在起始和结束层完成,因此作者向LyCORIS仓库提交了一个拉取请求,以便更轻松地选择单个层并为它们设置不同的系数,从而将LoKr的训练重点放在这些层上。
Beta时间步调度和时间步分层
扩散模型是多任务模型,不同的时间步被视为不同的任务,每个任务的梯度形状、大小和损失幅度都不同。为了解决这个问题,作者实现了一个近似原始Sigmoid采样的Beta调度,将采样时间步移向高噪声步骤;同时实现了多秩分层采样,在每个步骤中根据区域选择训练时间步,从而显著归一化梯度,就像使用更大的批量大小一样。
📚 详细文档
非技术报告:Schnell去蒸馏
原因
FLUX是一个优秀的文本到图像模型,但目前发布的版本都是经过蒸馏的。FLUX.1-dev经过蒸馏后,无需使用CFG(无分类器引导),生成速度比未蒸馏的模型快一倍。FLUX.1-schnell(德语意为“快速”)进一步蒸馏,只需4步条件生成即可得到图像,并且它采用Apache-2.0许可证,可免费使用。然而,schnell在使用CFG时,除非跳过前几个步骤,否则效果较差。
恢复原始训练目标
这部分实际上很简单,只需在正常的流匹配目标上使用MSE损失进行训练,模型就会重新学习如何实现该目标。但目前来看,LibreFLUX和OpenFLUX.1都未能完全去蒸馏该模型,可能是因为与原始模型的训练时长相比,它们的训练时间较短。
FLUX与注意力掩码
FLUX模型使用T5-XXL文本模型为文本到图像任务提供条件信息,会将文本填充到一定长度,填充标记会被模型用于存储信息。通过屏蔽这些填充标记,可以避免长提示导致的性能下降。作者在微调时启用了注意力掩码功能,使得用户可以使用完整的512个标记序列长度。
快速去蒸馏并适配小显存GPU
为了避免对大型的FLUX模型进行全秩微调,作者最初使用quanto以int8精度训练模型,并使用了6亿参数的LoKr。通过自定义的初始化函数,使得LoKr的损失下降速度加快了一倍。
选择更好的层进行LoKr训练
FLUX模型的“norm”层具有特殊性,在微调时这些层的变化较大。同时,根据研究表明,Transformer网络的大部分计算工作通常在起始和结束层完成,因此作者向LyCORIS仓库提交了一个拉取请求,以便更轻松地选择单个层并为它们设置不同的系数,从而将LoKr的训练重点放在这些层上。
Beta时间步调度和时间步分层
扩散模型是多任务模型,不同的时间步被视为不同的任务,每个任务的梯度形状、大小和损失幅度都不同。为了解决这个问题,作者实现了一个近似原始Sigmoid采样的Beta调度,将采样时间步移向高噪声步骤;同时实现了多秩分层采样,在每个步骤中根据区域选择训练时间步,从而显著归一化梯度,就像使用更大的批量大小一样。
数据集
作者使用了来自网络的开源数据集,这些数据集使用视觉语言模型(VLM)进行标注,每张图像有2 - 3个标注,包括至少一个短标注和一个长标注。这些数据集具有多样性,且大部分没有进行美学筛选,有助于引导模型避免传统文本到图像模型的过度优化。
训练
作者首先在5块3090显卡上使用6亿参数的LoKr对约50万张图像进行了一个多月的训练,批量大小为1(通过分布式数据并行,有效批量大小为5)。之后,作者获得了7块H100显卡的计算资源,将之前的参数高效微调(PEFT)模型合并,并开始使用32亿参数的LoKr进行训练,批量大小为6(通过分布式数据并行,有效批量大小为42)。
事后“指数移动平均(EMA)”
作者没有实现真正的事后EMA,如EDM2中的那样,而是通过保存H100训练过程中的所有检查点,并使用不同的alpha值对它们进行线性插值(LERP)来近似EMA。通过在不同的CFG比例下评估这些检查点,作者最终选择了alpha为0.9的模型。
结果
LibreFLUX和OpenFLUX各有优缺点。OpenFLUX是使用FLUX.1-schnell的输出进行去蒸馏的,这可能解释了为什么它在处理文本方面较差,但具有FLUX的超美学风格。由于文本到图像模型没有很好的评估指标,因此除了“模糊度”和个位数的FID值外,还需要直接观察模型生成的图像,看是否符合自己对“好图片”的定义。
这两个模型在生成绘画方面似乎都表现不佳。为了让人们看到非精选的结果,作者在这里提供了LibreFLUX和OpenFLUX.1的CFG扫描比较。作者并不认为这是有史以来最好的模型,但它可能为想要微调更好模型的人提供一个起点。
结束语
如果重新进行训练,作者可能会在H100训练时提高学习率。由于SimpleTuner中的一个bug,作者在使用H100时没有使用初始化技巧,而时间步分层进一步降低了梯度的幅度,导致模型在学习率为1e-5
时学习速度非常缓慢。作者在观察最终的FLUX.1-dev的EMA结果时才意识到这个问题。未来,作者会更加做好准备。
对于schnell的去蒸馏,作者认为可能需要超过1500个H100等效小时的训练时间。作者已经厌倦了训练FLUX模型,期待未来出现参数更少的更好模型。
联系作者与资助
如果你有任何问题,可以在该模型的讨论页面上创建一个问题进行提问。如果你想私下讨论资助事宜,希望作者继续训练该模型或进行可重复的研究,请留下你的电子邮件地址。
引用
@misc{libreflux,
author = {James Carter},
title = {LibreFLUX: A free, de-distilled FLUX model},
year = {2024},
publisher = {Huggingface},
journal = {Huggingface repository},
howpublished = {\url{https://huggingface.co/datasets/jimmycarter/libreflux}},
}
📄 许可证
本项目采用Apache 2.0许可证。









