这里的资料参考https://github.com/bghira/SimpleTuner/https://youtu.be/Q5mo7bziSkU?si=Sd4jbFwwgOY5ZzGD

FLUX发布了一段时间,网络上也陆续出现了一些LoRa(比如X-LAB发布的几个)。算是打破了之前说不可以训练lora的传言。恰好最近沉迷于某款游戏,因此决定训练一个该角色的FLUX LORA。

然而,这却成为了噩梦的开始......由于FLUX的生态极不完善,我刚开始琢磨训练LORA时,只能参照Youtube视频使用SimpleTunner。下面就是我结合自身遭遇到的各种报错,提出的可能可以规避一些问题的训练流程。这里的所有内容仅基于我自身的认知以及当前(2024年8月15日)的公开互联网资料所撰写,不能保证时效性,因此仅供参考。

I. 硬件准备

准备一张显存大于等于16GB(官方建议大于20GB,实测对于模型进行int8量化训练时,显存占用不超过14GB。当然对于我来说,这是一张不用来处理系统显示的外接显卡,如果需要负责系统显示,那么显存占用会更高)的显卡(图灵以上架构)和32GB及以上的系统内存(用于装卸t5文本编码器)。如果你的显卡不支持fp16运算,那么建议换一张。

由于训练FLUX的LoRa并不需要持续7x24h,因此散热和供电效能一般的家庭PC也可以进行训练。但是如果不具备这个条件,还是建议选择租用云端GPU(这里强烈推荐境外的GPU服务器,为了方便后续从huggingface上下载文件/安装依赖不再出现网络错误)。

参考SimpleTunner的官方说明,AMD显卡和MAC平台不支持训练FLUX Lora,但是你或许可以去试试kohya-ss的sd3分支?。

II. 系统安装

官方说明提到了,他们只支持Linux,但是我个人测试,使用WSL(Windows的Linux子系统)也可以正常训练。

如果你需要重新安装系统,那么我个人建议为训练留出至少60G的空间(这部分空间用于依赖和模型下载,以及训练缓存)。同时,避开使用centos7、ubuntu16.04这些老旧的发行版(官方并没有提到,但是老旧的Linux内核通常导致意外的错误,而你很难排除由它引发的bug并更换内核)。

III. 驱动安装

我自己的WSL是Ubuntu22.04,所以我在这儿贴上Ubuntu安装驱动的相关命令:

1、安装依赖

sudo apt-get update   #更新软件列表
sudo apt-get install g++ gcc make
sudo apt-get install dkms 

2、卸载原先的nVidia驱动

sudo apt remove --purge nvidia*

3、禁用nouveau(开源驱动)

sudo nano /etc/modprobe.d/blacklist.conf #打开黑名单文件

添加以下两行,然后Ctrl+O保存,Ctrl+C退出

blacklist nouveau
options nouveau modeset=0

4、下载并安装驱动与开发套件

重启,下载Nvidia cuda开发套件(里面自带驱动),按照官网的提示下载并安装。

这里我个人最推荐runfile,简单两条命令即可。

5、检查与确认

安装完成后,依次使用下面的三条命令来检查驱动和cuda套件是否已经被安装,环境变量是否被正确设置。

nvidia-smi
nvcc -V
echo $CUDA_HOME

如果nvcc提示找不到命令,或$CUDA_HOME变量提示不存在,那么使用

nano ~/.bashrc

打开用户环境变量,添加这三行。注意,将这里的cuda版本号改成你自己安装的版本号

export CUDA_HOME=/usr/local/cuda
export CUDNN_HOME=/usr/local/cuda
export LD_LIBRARY_PATH=/usr/local/cuda-12.6/lib64
export PATH=$PATH:/usr/local/cuda-12.6/bin

然后执行

source ~/.bashrc

来刷新用户环境。

其实这里的$CUDA_HOME是必须添加的,不添加这个环境变量,SimpleTunner可以正常训练,但是导出训练好的模型权重会出错。我当时遇到这个错误直接红温了,浪费了我好几个小时。

IV. 环境配置

1、确认python版本

输入

python3 --version

来确认你的版本。SimpleTunner只支持Python 3.10和3.11,如果你的版本不是这两个,那么你需要使用counda来做版本隔离。这里是官方关于conda安装的文档,这里是国内的一篇参考文章。

2、创建虚拟环境

创建虚拟环境,而不是直接使用系统python环境的目的是隔离可能产生冲突的包。

建议挑选一个空目录,用于存放SimpleTunner的相关文件。

这里分为两种情况:

如果不使用conda,那么直接运行以下命令

python3 -m venv env

就可以在当前目录创建一个名为env的虚拟环境,然后使用

source env/bin/activate

就可以进入虚拟环境了。

如果使用的是conda,那么使用

conda create -n stenv python=3.10.12

就会创建一个名为stenv,python版本为3.10.12的虚拟环境。

然后使用

conda activate stenv

就可以进入这个虚拟环境了。

3、解决网络问题

如果你的GPU服务器在境外,不需要关注这一部分。

a. 换源

首先在虚拟环境里使用以下两条命令

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple/
pip config set install.trusted-host pypi.tuna.tsinghua.edu.cn

来更换pip源为清华大学pypi。

接着执行

pip install -U poetry pip

来安装SimpleTunner需要的包管理工具。

然后运行

poetry source add --priority=default mirrors https://pypi.tuna.tsinghua.edu.cn/simple/

为poetry配置清华大学软件源。

如果还需要更换系统包管理器的软件源,可以参考各大镜像站的说明,例如这个

b. 使用代理

同样是编辑用户环境配置文件:

nano ~/.bashrc

加入这一行:

export all_proxy=http://ip:port

上面的各项可以按照需要配置,参见这张表。

然后执行

source ~/.bashrc

来刷新用户环境。

4、安装系统依赖

这一部分安装的是非python软件包。需要先执行:

sudo apt install git

来安装git用于后续下载源码。

文档中提到,对于容器主机,如果 CUDA 版本为12.2-12.4,需要执行

sudo apt install libgl1-mesa-glx

它们可能还缺少一些其它的软件。我的建议是,缺啥补啥。

V. 下载与安装

1、下载

在目录里执行

git clone --branch=release https://github.com/bghira/SimpleTuner.git

来下载SimpleTunner源码。这里下载的是release分支。有关GitHub的网络问题,建议考虑代理。

2、安装

首先,确保处于虚拟环境之中,然后进入刚刚下载好的SimpleTunner目录里:

cd SimpleTuner

再执行

poetry install --no-root

视频里说这会花“a cup of coffee”的时间,个人感觉会花1-2小时,并有可能遭遇网络问题。如果遭遇到了网络问题,只能自求多福了。

接着,删除默认的diffuser并安装github上的最新版以缓解bug

pip uninstall diffusers
pip install git+https://github.com/huggingface/diffusers

对于容器主机,可能需要删除以下依赖:

pip uninstall -y deepspeed bitsandbytes

这样,一般来说,就把SimpleTunner安装好了。

VI. 准备数据集

1、图像处理

FLUX支持多种分辨率的图片,按照官方文档的说法:

⚠️
 Image quality for training is more important for Flux than for most other models, as it will absorb the artifacts in your images first, and then learn the concept/subject.

⚠️
 512-pixel training is recommended for Flux; it is more reliable than high-resolution training, which tends to diverge.
ℹ️ Running 512px and 1024px datasets concurrently is supported, and could result in better convergence for Flux.

所以,我个人推荐使用512x512分辨率的高质量图像组成的数据集。

对于我个人而言,我使用的是一系列该游戏角色的3D模型在Blender里的纯黑背景的多角度、多动作渲染图,经过比例缩放与裁剪后统一为512X512的图像。

(9月1日补充:我发现训练特征稍微复杂一些的角色模型时,还是使用高分辨率(1024x1024)的图片更好一些,不然会导致模糊和边缘画质降低。)

2、标注

我使用的是最为传统的WD14 Tagger标注,然后去除角色特征相关的prompt。视频里使用的是GPT-4o等带有视觉能力的LLM进行标注,但是似乎效果不佳。按照我的推断,使用自然语言标注应当更加合适,但似乎很难对标注后的内容做清洗,所以我最终还是选择了最传统的标注方法。

标注后的内容需要保存为与原图同名的txt文本文件。

a. 使用自然语言标注(9月1日新增)

可以使用自然语言标注,使用触发词替换描述角色特征的语句。

可以使用llava、minicpm等视觉大语言模型做基础标注后再修改。

假设我要训练纳西妲的角色lora,使用自然描述的图片有可能是“A young girl with long silver hair adorned with white flowers. She is seated on a verdant, flower-strewn lawn, her body slightly turned towards us, the viewers. Her attire is as vibrant and colorful as her surroundings, featuring a sleeveless top in shades of green and gold. A dragon-like creature graces her head, adding an element of fantasy to the scene. The background is lush with trees and more flowers, creating a sense of tranquility and harmony with nature. There are no actions depicted; it is a still life capturing a moment of quiet contemplation.

将涉及到角色的部分使用触发词替代。修改之后的描述语句是“Nahida is seated on a verdant, flower-strewn lawn, her body slightly turned towards us, the viewers. The background is lush with trees and more flowers, creating a sense of tranquility and harmony with nature. It is a still life capturing a moment of quiet contemplation. This pictures is drawed in anime style.

个人觉得这里其实处理的不是很好,咱觉得如果需要训练角色lora,就应该详细描述背景、角色的行为、动作、姿态。以及画风、传递出的情绪等。训练画风lora时可能就需要描述画面里的所有元素,但是使用触发词替代所有与画风、画面氛围相关的内容。

3、配置数据集

将图片与同名文本存入一个目录下,这里假设为/mnt/d/fluxtrain/datasets/Verina,在SimpleTunner目录下的config文件夹里新建multidatabackend.json文件,

nano config/multidatabackend.json

填入以下内容:

[
    {
      "id": "verina-capture",
      "type": "local",
      "crop": false,
      "crop_aspect": "square",
      "crop_style": "center",
      "resolution": 512,
      "minimum_image_size": 512,
      "maximum_image_size": 512,
      "target_downsample_size": 512,
      "resolution_type": "pixel",
      "cache_dir_vae": "cache/vae/flux/Verina",
      "instance_data_dir": "/mnt/d/fluxtrain/datasets/Verina",
      "disabled": false,
      "skip_file_discovery": "",
      "caption_strategy": "textfile",
      "metadata_backend": "json"
    },
    {
      "id": "text-embeds",
      "type": "local",
      "dataset_type": "text_embeds",
      "default": true,
      "cache_dir": "cache/text/flux/Verina",
      "disabled": false,
      "write_batch_size": 128
    }
  ]

这里的instance_data_dir即为数据集所在的位置。cache_dir、cache_dir_vae可酌情设置位置。由于我已经将图片裁剪为了512X512,因此将crop设置为了false。caption_strategy制定了数据集的存放方式,这里为txt文本,所以是textfile。

修改好之后,记得保存退出

更多有关SimpleTunner数据集的配置,请参照官方文档

VII. 下载模型

在终端使用下面的命令可以直接从huggingface下载黑森林实验室官方的FLUX.1 dev模型:

git clone https://huggingface.co/black-forest-labs/FLUX.1-dev

这个过程可能会很漫长,或者报错。如果无法直接访问抱抱脸,也可以使用镜像站,例如:

git clone https://hf-mirror.com/black-forest-labs/FLUX.1-dev

甚至手动下载模型。但是,必须保证目录结构和文件的完好。

需要注意的是,SimpleTunner支持训练FLUX.1 Schnell的Lora,但是我发现基于dev训练的lora也可以在schnell上使用,所以不如一来就训练基于dev的模型。除非你担心许可证问题。相关配置需要在环境里设置。

VIII. 配置环境变量

在SimpleTunner里,train.sh会从config/config.env里读取相关的参数,并以环境变量的方式传递给脚本。所以先把这个文件复制一份,然后打开编辑:

cp config/config.env.example config/config.env
nano config/config.env

这里面的参数非常多,但是对我来说,有用的不是很多。参照官方文档和自己的理解,我大致整理如下:

变量说明我的设置
MODEL_TYPE需要训练的模型类型。‘lora’
FLUX是否启用FLUX支持。true
USE_DORA是否训练DORA模型。false
CHECKPOINTING_STEPS每训练多少步保存一次训练好的权重。250
CHECKPOINTING_LIMIT保存权重数量的上限。1000
LEARNING_RATE学习率。文档中Flux 的训练类似于 SD 1.5 LoRA,1e-3可能会造成过拟合,而1e-5会造成欠拟合。一般来说,优化器会动态调整学习率,而12B的大模型还是推荐一个比较低的学习率。如果增大了batch size,那么建议提高学习率。9e-5
MODEL_NAME填入你下载的FLUX.1 模型的路径。"/mnt/d/fluxtrain/FLUX.1-dev"
DEBUG_EXTRA_ARGS默认为"--report_to=wandb",即开启向wandb上报的功能,清空可关闭。
MAX_NUM_STEPS最大训练步数.10000
DATALOADER_CONFIG数据集配置文件路径。"config/multidatabackend.json"
OUTPUT_DIR模型输出lujing。"/mnt/d/fluxtrain/output/models"
PUSH_TO_HUB向抱抱脸推送模型。false
PUSH_CHECKPOINTS向抱抱脸推送中间模型。false
RESOLUTION数据集分辨率。可以使用逗号来分割其他分辨率:1024x1024,1280x768,2048x2048。512
VALIDATION_PROMPT生成用于验证模型训练效果的图片的提示词。"Anime girl Verina in a miniskirt and white sleeveless shirt sitting on the swing and showing her belly button. The miniskirt is drawing in lily and green leaves. In the background is the deserted garden at sunset.There is a little rabbit on the ground."
VALIDATION_GUIDANCE生成用于验证模型训练效果的图片的提示词引导(CFG),这里我参考了官方文档里的这一部分,所以没有设置的很高。1.5
VALIDATION_GUIDANCE_REAL可以将其设置为大于1.0来实现这一点。如果你不启用CFG,结果可能不可靠或看起来很糟糕。1.0
VALIDATION_NO_CFG_UNTIL_TIMESTEP在验证采样期间跳过CFG(仅限flux,默认=2)。1
VALIDATION_STEPS每隔多少步生成一次验证图像。250
VALIDATION_NUM_INFERENCE_STEPS每张验证图像所需要的步数。50
VALIDATION_NEGATIVE_PROMPT验证图像的负面提示词,flux需要为空。""
VALIDATION_SEED验证图像的随机种子,可以随意修改。42
VALIDATION_RESOLUTION验证图像的分辨率。1024
TRAIN_BATCH_SIZEBatch Size设置,取决于你的数据集和显存。当你的数据集很小的时候,可以增大它。1
LR_SCHEDULE学习率调度器,可以选择余弦式、多项式等。"polynomial"
LR_WARMUP_STEPS学习率预热。1000
CAPTION_DROPOUT_PROBABILITY数据集丢失概率,如果你希望严格限制对模型的更改仅限于你展示的提示,你可能希望禁用丢弃。如果你希望更广泛地在模型中应用更改,你可能希望增加丢弃率。0.1
MAX_WORKERSVAE缓存时使用多少WORKER。32
TORCH_NUM_THREADSpyTorch使用的CPU线程数。8
USE_XFORMERS启用nVidia的xformers优化。true
OPTIMIZER优化器,根据需要选择。支持adamw, adamw8bit, adafactor, dadaptation, adamw_bf16。配置文件中的说明如下:AdamW 8Bit 是一个稳健且轻量级的选择。Adafactor 可能会减少内存消耗,而 Dadaptation 则缓慢且实验性。
AdamW 是默认的优化器,但它占用大量内存,并且比 AdamW8Bit 或 Adafactor 慢。
注意:在训练量化基础模型时,不能使用 adamw_bf16。相反,可以尝试 adafactor 或 adamw。
"adamw_bf16"
TRAINER_EXTRA_ARGS这里涉及到很多关键的额外参数:

--base_model_precision=int8-quanto:以int8加载基础模型,可以节约显存且比fp8快。

--text_encoder_1_precision=no_change --text_encoder_2_precision=no_change:不量化文本编码器,保持语义完整。

--lora_rank=8:设置要训练的lora维度,可以减小以节约显存,同时,更高的维度也更难训练。

--flux_fast_schedule:使用FLUX.1 Schnell作为基础模型。

--max_grad_norm=1.0 --gradient_precision=fp32:限制梯度范数可能会更长时间地保留模型,而fp32梯度允许使用累积步骤。但fp32梯度与Prodigy不兼容,可能与其他有严格数据类型处理的优化器也不兼容。

--base_model_default_dtype=bf16:模型基本数据类型为bf16

--flux_lora_target=all+ffs:当训练'mmdit'时,我们发现训练非常稳定,这使得模型需要更长时间来学习。当训练'all'时,我们可以很容易地改变模型分布,但它更容易遗忘,并且从高质量数据中受益。当训练'all+ffs'时,除了前馈和规范层之外,所有注意力层都被训练,这可以帮助适应LoRA的模型目标。

--lora_init_type=default:如果你想要使用LoftQ初始化,你不能使用Quanto来量化基础模型。这可能提供更好/更快的收敛,但仅适用于NVIDIA设备,并且需要Bits n Bytes。其他选项是'default'、'gaussian'(困难),以及未测试的选项:'olora'和'pissa'。

--user_prompt_library=config/user_prompt_library.json":在生成验证图像时使用多段自定义的提示词,文件位置是config/user_prompt_library.json,格式参照文档

--base_model_precision=int8-quanto
--text_encoder_1_precision=no_change --text_encoder_2_precision=no_change
--lora_rank=8
--max_grad_norm=1.0
--gradient_precision=fp32
--base_model_default_dtype=bf16
--flux_lora_target=all+ffs
--lora_init_type=default
TRAINING_SEED训练时使用的随机种子。42
MIXED_PRECISION启用混合精度。"bf16"
TRAINING_DYNAMO_BACKENDpytorch2.2支持动态分辨率,开启后可以避免每次分辨率变化导致的重新编译,但会导致一定的性能损失。'no'
TRAINING_NUM_PROCESSES训练进程数量,取决于GPU的数量。1
TRAINING_NUM_MACHINES训练机器数量,取决于GPU的数量。1

当然,我的配置中一定也有着不少错误和误解的地方,欢迎大家指正。

编辑完成后,保存文件退出,就可以开始训练了。

IX, 开始训练

在虚拟环境中,进入SimpleTunner目录i,执行以下命令开始训练:

bash train.sh

开始的处理过程会长达10分钟左右,不知道为什么,它总是会在第一次训练的时候提示我登录wandb,我一般都是选择3关闭这个功能。

另外,如果你对于基础模型开启了量化加载,然后进行训练,中途因为某些原因中断了,那么你将无法继续训练。这是一个由diffuser造成的bug,目前尚未解决。

X. 总结

所以,目我所知道的FLUX的Lora就是这样的,期待更加完善的工具/文档出现。

(PS,Schnell模型似乎不能使用uni_pc系列采样器,会导致VAE解码出错)

最后更新于 2024-09-01