模型概述
模型特點
模型能力
使用案例
🚀 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許可證。









