Stable Diffusion XL之使用Stable Diffusion XL训练自己的AI绘画模型

文章目录

  • 一 SDXL训练基本步骤
  • 二 从0到1上手使用Stable Diffusion XL训练自己的AI绘画模型
    • 2.1 配置训练环境与训练文件
    • 2.2 SDXL训练数据集制作
      • (1) 数据筛选与清洗
      • (2) 使用BLIP自动标注caption
      • (3) 使用Waifu Diffusion 1.4自动标注tag
      • (4) 补充标注特殊tag
      • (5) 训练数据预处理(标注文件整合)
    • 2.3 SDXL微调(finetune)训练
      • (1 )SDXL 微调数据集要求
      • (2) SDXL 微调训练参数配置
        • 2.1 训练参数配置(XL_config文件夹)
          • 2.1.1 config_file.toml
          • 2.1.2 sample_prompt.toml
      • (3) SDXL关键参数详解
      • (4) SDXL模型开始训练
    • 2.4 基于SDXL训练LoRA模型
      • (1) SDXL LoRA数据集制作
      • (2) SDXL LoRA训练参数配置
        • 2.1 训练参数讲解(XL_LoRA_config文件夹)
          • 2.1.1 config_file.toml
      • (3) SDXL LoRA关键参数详解
      • (4) SDXL LoRA模型训练

一 SDXL训练基本步骤

Stable Diffusion XL系列模型的训练过程主要分成以下几个步骤,

  1. 训练集制作:数据质量评估,标签梳理,数据清洗,数据标注,标签清洗,数据增强等。
  2. 训练文件配置:预训练模型选择,训练环境配置,训练步数设置,其他超参数设置等。
  3. 模型训练:运行SDXL模型/LoRA模型训练脚本,使用TensorBoard监控模型训练等。
  4. 模型测试:将训练好的自训练SDXL模型/LoRA模型用于效果评估与消融实验

二 从0到1上手使用Stable Diffusion XL训练自己的AI绘画模型

下面是SDXL的训练资源
链接:https://pan.quark.cn/s/5664c0de758d
提取码:LRZV

2.1 配置训练环境与训练文件

1. 首先进入SDXL-Train项目中,安装SDXL训练所需的依赖库

cd SDXL-Train
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple some-package

# accelerate库的版本需要重新检查一遍,需要安装accelerate==0.16.0版本才能兼容SDXL的训练
pip install accelerate==0.16.0 -i https://pypi.tuna.tsinghua.edu.cn/simple some-package

# 这里推荐大家安装2.0.1版本的Pytorch,能够兼容SDXL训练的全部流程
pip install torch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2 --index-url https://download.pytorch.org/whl/cu118
或者conda
conda install pytorch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2 pytorch-cuda=11.8 -c pytorch -c nvidia

在完成上述的依赖库安装后,我们需要确认一下目前的Python、PyTroch、CUDA以及cuDNN的版本是否兼容,在命令行输入以下命令:

# Python版本推荐3.8或者3.9,两个版本皆可
>>>python
Python 3.9
# 加载PyTroch
>>>import torch
# 查看PyTorch版本
>>>print(torch.version)
2.0.1
# 查看CUDA版本
>>> print(torch.version.cuda)
11.8
# 查看cuDNN版本
>>> print(torch.backends.cudnn.version())
8500
# 查看PyTroch、CUDA以及cuDNN的版本是否兼容,True代表兼容
>>> print(torch.cuda.is_available())
True

  1. 安装和验证好所有SDXL训练所需的依赖库后,我们还需要设置一下SDXL的训练环境,我们主要是用accelerate库的能力,accelerate库能让PyTorch的训练和推理变得更加高效简洁。我们只需在命令行输入以下命令,并对每个设置逐一进行填写即可:
# 输入以下命令,开始对每个设置进行填写
accelerate config

# 开始进行训练环境参数的配置
In which compute environment are you running? # 选择This machine,即本机
This machine

# 选择单卡或是多卡训练,如果是多卡,则选择multi-GPU,若是单卡,则选择No distributed training                                                                                                               
Which type of machine are you using?                                                                                        
multi-GPU

# 几台机器用于训练,一般选择1台。注意这里是指几台机器,不是几张GPU卡                                                                                                                  
How many different machines will you use (use more than 1 for multi-node training)? [1]: 1

# torch dynamo,DeepSpeed,FullyShardedDataParallel,Megatron-LM等环境参数,不需要配置                          
Do you wish to optimize your script with torch dynamo?[yes/NO]: # 输入回车即可                                                           
Do you want to use DeepSpeed? [yes/NO]:  # 输入回车即可                                                                                  
Do you want to use FullyShardedDataParallel? [yes/NO]:    # 输入回车即可                                                                 
Do you want to use Megatron-LM ? [yes/NO]:       # 输入回车即可

# 选择多少张卡投入训练                                                                          
How many GPU(s) should be used for distributed training? [1]:2

# 设置投入训练的GPU卡id,如果是全部的GPU都投入训练,则输入all即可。
What GPU(s) (by id) should be used for training on this machine as a comma-seperated list? [all]:all 

# 训练精度,可以选择fp16
Do you wish to use FP16 or BF16 (mixed precision)? 
fp16                             

# 完成配置后,配置文件default_config.yaml会保存在/root/.cache/huggingface/accelerate下                                                                                   
accelerate configuration saved at /root/.cache/huggingface/accelerate/default_config.yaml完成上述的流程后,接下来我们就可以进行SDXL训练数据的制作和训练脚本的配置流程了!

后续进行SDXL与SDXL LoRA模型训练的时候,只需要加载对应的default_config.yaml配置文件即可,具体的调用方法,本文后续的章节会进行详细讲解。

还有一点需要注意的是,我们进行SDXL模型的训练时,SDXL的CLIP Text Encoder会调用CLIP-ViT-bigG-14-laion2B-39B-b160k和clip-vit-large-patch14两个配置文件。一般情况下SDXL模型会从huggingface上将配置文件下载到~/.cache/huggingface/目录中,但是由于网络原因很可能会下载失败,从而导致训练的失败。

所以为了让大家能更方便的训练SDXL模型,已经将CLIP-ViT-bigG-14-laion2B-39B-b160k和clip-vit-large-patch14这两个配置文件放入SDXL-Train项目的utils_json文件夹中,并且已经为大家配置好依赖路径,大家只要使用SDXL-Train项目便无需做任何修改。如果大家想要修改CLIP-ViT-bigG-14-laion2B-39B-b160k和clip-vit-large-patch14这两个依赖文件夹的调用路径,大家可以找到SDXL-Train/library/sdxl_train_util.py脚本中的第122行,将"utils_json/"部分修改成自己的本地自定义路径比如“/本地路径/utils_json/”即可。

完成上述的流程后,接下来我们就可以进行SDXL训练数据的制作和训练脚本的配置流程了!

2.2 SDXL训练数据集制作

(1) 数据筛选与清洗

首先,我们需要对数据集进行清洗,和传统深度学习时代一样,数据清洗工作依然占据了AIGC时代模型训练70%-80%左右的时间。

并且这个过程必不可少,因为数据质量决定了机器学习性能的上限,而算法和模型只是在不断逼近这个上限而已。

  • 我们需要筛除分辨率较低、质量较差(比如说768*768分辨率的图片< 100kb)、存在破损以及和任务目标无关的数据,接着再去除数据里面可能包含的水印,干扰文字等污染特征。

  • 同时,我们需要优先保证数据集的质量,在有质量的基础上再去增加数据集的数量与丰富度。

  • 为了满足AI绘画生成图片时的尺寸适应度,我们可以对数据进行多尺度的增强,比如进行1:1,1:2,2:1,1:3,3:4,4:3,9:16,16:9等等尺寸的裁剪与缩放操作。但是切记不能在多尺度增强的时候将图片的主体特征裁剪掉(比如人脸,建筑等)。

完成上述的数据筛选与清洗工作后,我们就可以开始进行数据标注了。

数据标注可以分为自动标注和手动标注。自动标注主要依赖像BLIP(img2caption)和Waifu Diffusion 1.4(img2tag)等能够进行图片生成标签的模型,手动标注则依赖标注人员。

(2) 使用BLIP自动标注caption

我们先用BLIP对数据进行自动标注,BLIP输出的是自然语言标签,我们进入到SDXL-Train/finetune/路径下,运行以下代码即可获得自然语言标签(caption标签):

cd SDXL-Train/finetune/
python make_captions.py "/数据路径" --caption_weights “../BLIP/model_large_caption.pth” --batch_size=8 --beam_search --min_length=5 --max_length=75 --debug --caption_extension=".caption" --max_data_loader_n_workers=2

注意:在使用BLIP进行数据标注时需要依赖bert-base-uncased模型,已经帮大家配置好了,大家只要使用SDXL-Train项目便无需做任何修改。同时,如果大家想要修改bert-base-uncased模型的调用路径,可以找到SDXL-Train/finetune/blip/blip.py脚本的第189行,将“…/bert-base-uncased”部分修改成自己的本地自定义路径比如“/本地路径/bert-base-uncased”即可。

从上面的代码可以看到,我们第一个传入的参数是训练集的路径。下面一一向大家介绍一下其余参数的意义:

--caption_weights:表示加载的本地BLIP模型,如果不传入本地模型路径,则默认从云端下载BLIP模型。
--batch_size:表示每次传入BLIP模型进行前向处理的数据数量。
--beam_search:设置为波束搜索,默认Nucleus采样。
--min_length:设置caption标签的最短长度。
--max_length:设置caption标签的最长长度。
--debug:如果设置,将会在BLIP前向处理过程中,打印所有的图片路径与caption标签内容,以供检查。
--caption_extension:设置caption标签的扩展名,一般为".caption"。
--max_data_loader_n_workers:设置大于等于2,加速数据处理。

(3) 使用Waifu Diffusion 1.4自动标注tag

接下来我们可以使用Waifu Diffusion 1.4进行自动标注,Waifu Diffusion 1.4输出的是tag关键词,这里需要注意的是,调用Waifu Diffusion 1.4模型需要安装Tensorflow库,并且需要下载特定的版本(2.10.1)或者(2.10.0),不然运行时会报“DNN library is not found“错误。我们只需要在命令行输入以下命令即可:
如果是2.10.1建议不适用国内源,可能更新不完全,会报错,2.10.0可以使用国内源。

pip install tensorflow==2.10.1

或者

pip install tensorflow==2.10.0 -i https://pypi.tuna.tsinghua.edu.cn/simple some-package

完成上述的环境配置后,我们依然进入到SDXL-Trian/finetune/路径下,运行以下代码即可获得tag自动标注:

cd SDXL-Train/finetune/
python tag_images_by_wd14_tagger.py "/数据路径" --batch_size=8 --model_dir="../tag_models/wd-v1-4-moat-tagger-v2" --remove_underscore --general_threshold=0.35 --character_threshold=0.35 --caption_extension=".txt" --max_data_loader_n_workers=2 --debug --undesired_tags=""

从上面的代码可以看到,

我们第一个传入的参数是训练集的路径。
--batch_size:表示每次传入Waifu Diffusion 1.4模型进行前向处理的数据数量。
--model_dir:表示加载的本地Waifu Diffusion 1.4模型路径。
--remove_underscore:如果开启,会将输出tag关键词中的下划线替换为空格。
--general_threshold:设置常规tag关键词的筛选置信度。
--character_threshold:设置人物特征tag关键词的筛选置信度。
--caption_extension:设置tag关键词标签的扩展名,一般为".txt"。
-max_data_loader_n_workers:设置大于等于2,加速数据处理。
--debug:如果设置,将会在Waifu Diffusion 1.4模型前向处理过程中,打印所有的图片路径与tag关键词标签内容,以供检查。
--undesired_tags:设置不需要输出的tag关键词。

(4) 补充标注特殊tag

完成了caption和tag的自动标注之后,如果我们需要训练一些特殊标注的话,还可以进行手动的补充标注。

SDXL-Trian项目中也提供了对数据进行补充标注的代码,下面代码将其进行提炼总结,方便大家直接使用。

大家可以直接拷贝以下的代码,并按照代码中提供的注释进行参数修改,然后运行代码即可对数据集进行补充标注:

import os
# 设置为本地的数据集路径
train_data_dir = "/本地数据集路径"

# 设置要补充的标注类型,包括[".txt", ".caption"]
extension   = ".txt" 

# 设置要补充的特殊标注
custom_tag  = "qclineart"

# 若设置sub_folder = "--all"时,将遍历所有子文件夹中的数据;默认为""。
sub_folder  = "" 

# 若append设为True,则特殊标注添加到标注文件的末尾
append      = False

# 若设置remove_tag为True,则会删除数据集中所有的已存在的特殊标注
remove_tag  = False
recursive   = False

if sub_folder == "":
    image_dir = train_data_dir
elif sub_folder == "--all":
    image_dir = train_data_dir
    recursive = True
elif sub_folder.startswith("/content"):
    image_dir = sub_folder
else:
    image_dir = os.path.join(train_data_dir, sub_folder)
    os.makedirs(image_dir, exist_ok=True)

# 读取标注文件的函数,不需要改动
def read_file(filename):
    with open(filename, "r") as f:
        contents = f.read()
    return contents

# 将特殊标注写入标注文件的函数,不需要改动
def write_file(filename, contents):
    with open(filename, "w") as f:
        f.write(contents)

# 将特殊标注批量添加到标注文件的主函数,不需要改动
def process_tags(filename, custom_tag, append, remove_tag):
    contents = read_file(filename)
    tags = [tag.strip() for tag in contents.split(',')]
    custom_tags = [tag.strip() for tag in custom_tag.split(',')]

    for custom_tag in custom_tags:
        custom_tag = custom_tag.replace("_", " ")
        if remove_tag:
            while custom_tag in tags:
                tags.remove(custom_tag)
        else:
            if custom_tag not in tags:
                if append:
                    tags.append(custom_tag)
                else:
                    tags.insert(0, custom_tag)

    contents = ', '.join(tags)
    write_file(filename, contents)


def process_directory(image_dir, tag, append, remove_tag, recursive):
    for filename in os.listdir(image_dir):
        file_path = os.path.join(image_dir, filename)

        if os.path.isdir(file_path) and recursive:
            process_directory(file_path, tag, append, remove_tag, recursive)
        elif filename.endswith(extension):
            process_tags(file_path, tag, append, remove_tag)

tag = custom_tag

if not any(
    [filename.endswith(extension) for filename in os.listdir(image_dir)]
):
    for filename in os.listdir(image_dir):
        if filename.endswith((".png", ".jpg", ".jpeg", ".webp", ".bmp")):
            open(
                os.path.join(image_dir, filename.split(".")[0] + extension),
                "w",
            ).close()

# 但我们设置好要添加的custom_tag后,开始整个代码流程
if custom_tag:
    process_directory(image_dir, tag, append, remove_tag, recursive)

看完了上面的完整代码流程,如果大家觉得代码太复杂,don‘t worry,大家只需要复制上面的全部代码,并将train_data_dir ="/本地数据集路径"和custom_tag ="qclineart"设置成自己数据集的本地路径和想要添加的特殊标注,然后运行代码即可,非常简单实用。

大家注意,一般我们会将手动补充的特殊tag放在第一位,因为和caption标签不同,tags标签是有顺序的,最开始的tag权重最大,越靠后的tag权重越小。

(5) 训练数据预处理(标注文件整合)

  • 首先,我们需要对刚才生成的后缀为.caption和.txt的标注文件进行整合,存储成一个json格式的文件,方便后续SDXL模型训练时调取训练数据与标注。

  • 我们需要进入SDXL-Train项目的finetune文件夹中,运行merge_all_to_metadata.py脚本即可:

cd SDXL-Train
python ./finetune/merge_all_to_metadata.py "/本地数据路径" "/本地数据路径/meta_clean.json"

运行完merge_all_to_metadata.py脚本后,我们在数据集路径中得到一个meta_clean.json文件,打开可以看到图片名称对应的tag和caption标注都封装在了文件中。

在整理好标注文件的基础上,我们接下来我们需要对数据进行分桶与保存Latent特征,并在meta_clean.json的基础上,将图片的分辨率信息也存储成json格式,并保存一个新的meta_lat.json文件。

我们需要进入SDXL-Train项目的finetune文件夹中,运行prepare_buckets_latents.py脚本即可:

cd SDXL-Train
python ./finetune/prepare_buckets_latents.py "/本地数据路径" "/本地数据路径/meta_clean.json" "/本地数据路径/meta_lat.json" "调用的SDXL模型路径" --batch_size 4 --max_resolution "1024,1024"

运行完脚本,我们即可在数据集路径中获得meta_lat.json文件,其在meta_clean.json基础上封装了图片的分辨率信息,用于SDXL训练时快速进行数据分桶。

图片的Latent特征保存为了.npz文件,用于SDXL模型训练时,快速读取数据的Latent特征,加速训练过程。

到目前为止,我们已经完整的进行了SDXL训练所需的数据集制作与预处理流程。总结一下,我们在一张训练图片的基础上,一共获得了以下5个不同的训练配置文件:
meta_clean.json
meta_lat.json
自然语言标注(.caption)
关键词tag标注(.txt)
数据的Latent特征信息(.npz)
在这里插入图片描述
在完成以上所有数据处理过程后,接下来我们就可以进入SDXL训练的阶段了,我们可以对SDXL进行全参微调(finetune),也可以基于SDXL训练对应的LoRA模型。

2.3 SDXL微调(finetune)训练

(1 )SDXL 微调数据集要求

制作过程就是上个章节的内容

用于SDXL全参微调的数据集筛选要求和SDXL训练Lora不一样:

  • 数据尺寸需要在512x512像素以上。
  • 数据的大小最好大于300K。
  • 数据种类尽量丰富,不同主题,不同画风,不同概念都要充分采集。
  • 一个特殊tag对应的图像特征在数据集中需要一致,不然在推理过程触发这个tag时可能会生成多个特征的平均。
  • 每个数据都要符合我们的审美和评判标准!每个数据都要符合我们的审美和评判标准!每个数据都要符合我们的审美和评判标准!

(2) SDXL 微调训练参数配置

本节中,主要介绍Stable Diffusion XL全参微调(finetune)训练的参数配置和训练脚本。

大家可以在SDXL-Trian项目的train_config文件夹中找到相应的训练参数配置(XL_config文件夹),并且可以在SDXL-Trian项目中运行SDXL_finetune.sh脚本,进行SDXL的全参微调训练。

2.1 训练参数配置(XL_config文件夹)

XL_config文件夹中有两个配置文件config_file.toml和sample_prompt.toml,他们分别存储着SDXL的训练超参数与训练中的验证prompt

2.1.1 config_file.toml

config_file.toml的配置信息包含了sdxl_arguments,model_arguments,dataset_arguments,training_arguments,logging_arguments,sample_prompt_arguments,saving_arguments,optimizer_arguments八个维度的参数信息。
1. [sdxl_arguments]

#Stable Diffusion XL训练时需要打开,用于两个Text Encoder输出结果的缓存与融合。注:当cache_text_encoder_outputs设为true时,shuffle_caption将不起作用。
cache_text_encoder_outputs = true
#当此参数为true时,VAE在训练中使用float32精度;当此为false时,VAE在训练中使用fp16精度。
no_half_vae = true
#Stable Diffusion XL Base U-Net在训练时的最小时间步长(默认为0)。
min_timestep = 0
#Stable Diffusion XL Base U-Net在训练时的最大时间步长(默认为1000)。
max_timestep = 1000
#当设置为true时,对训练标签进行打乱,能一定程度提高模型的泛化性。
shuffle_caption = false

2. [model_arguments]

#读取本地Stable Diffusion XL预训练模型用于微调。
pretrained_model_name_or_path = "/本地路径/SDXL模型文件"
#读取本地VAE模型,如果不传入本参数,在训练中则会读取Stable Diffusion XL自带的VAE模型。
vae  = "/本地路径/VAE模型文件"

3. [dataset_arguments]

#训练时对数据进行debug处理,不让破损数据中断训练进程。
debug_dataset = false
#读取数据集json文件,json文件中包含了数据名称,数据标签,数据分桶等信息。
in_json = "/本地路径/data_meta_lat.json"
#读取本地数据集存放路径。
train_data_dir = "/本地路径/训练集"
#整个数据集重复训练的次数。(经验分享:如果数据量级小于一千,可以设置为10;如果数据量级在一千与一万之前,可以设置为5;如果数据量级大于一万,可以设置为2)
dataset_repeats = 10
#在训练过程中,会将txt中的tag进行随机打乱。如果将keep tokens设置为n,那前n个token的顺序在训练过程中将不会被打乱。
keep_tokens = 0
#设置训练时的数据输入分辨率,分别是width和height。
resolution = "1024,1024"
#针对一个数据丢弃全部标签的概率,默认为0。
caption_dropout_rate = 0
#针对一个数据丢弃部分标签的概率,默认为0。(类似于传统深度学习的Dropout逻辑)
caption_tag_dropout_rate = 0
#每训练n个epoch,将数据标签全部丢弃。
caption_dropout_every_n_epochs = 0
#数据颜色增强,建议不启用,其与caching latents不兼容,若启用会导致训练时间大大增加。
color_aug = false
#在训练一开始学习每个数据的前n个tag(标签用逗号分隔后的前n个tag,比如girl,boy,good)
token_warmup_min = 1
#训练中学习标签数达到最大值所需的步数,默认为0,即一开始就能学习全部的标签。
token_warmup_step = 0

4.[training_arguments]

#模型保存的路径。
output_dir = "/本地路径/模型权重保存地址"
#模型名称。
output_name = "sdxl_finetune_qclineart"
#模型保存的精度,一共有[“None”, "float", "fp16", "bf16"]四种选择,默认为“None”,即FP32精度。
save_precision = "fp16"
#每n个steps保存一次模型权重。
save_every_n_steps = 1000
#训练Batch-Size,与传统深度学习一致。
train_batch_size = 4
#设置Text Encoder最大的Token数,有[None, 150, 225]三种选择,默认为“None”,即75。
max_token_length = 225
#对CrossAttention模块进行轻量化,能够一定程度上加速模型训练并降低显存占用,开启mem_eff_attn后xformers失效。
mem_eff_attn = false
#xformers插件可以使SDXL模型在训练时显存减少一半左右。
xformers = true
#训练的总步数。
max_train_steps = 100000
#数据加载的DataLoader worker数量,默认为8。
max_data_loader_n_workers = 8
#能够让DataLoader worker持续挂载,减少训练中每个epoch之间的数据读取时间,但是会增加内存消耗。
persistent_data_loader_workers = true
#设为true时开启梯度检查,通过以更长的计算时间为代价,换取更少的显存占用。相比于原本需要存储所有中间变量以供反向传播使用,使用了checkpoint的部分不存储中间变量而是在反向传播过程中重新计算这些中间变量。模型中的任何部分都可以使用gradient checkpoint。
gradient_checkpointing = true
#如果显存不足,我们可以使用梯度累积步数,默认为1。
gradient_accumulation_steps = 1
#训练中是否使用混合精度,一共有["no", "fp16", "bf16"]三种选择,默认为“no”。
mixed_precision = "fp16"

5. [logging_arguments]

#选择训练log保存的格式,可以从["tensorboard", "wandb", "all"]三者中选择,也可以不设置。
log_with = "tensorboard"
#设置训练log保存的路径。
logging_dir = "/本地路径/logs"
#增加log文件的文件名前缀,比如sdxl_finetune_qclineart1234567890。
log_prefix = "sdxl_finetune_qclineart"

6. [sample_prompt_arguments]

#在训练中每n步测试一次模型效果。
sample_every_n_steps = 100
#设置训练中测试模型效果时使用的sampler,可以选择["ddim","pndm","lms","euler","euler_a","heun","dpm_2","dpm_2_a","dpmsolver","dpmsolver++","dpmsingle", "k_lms","k_euler","k_euler_a","k_dpm_2","k_dpm_2_a"],默认是“ddim”。
sample_sampler = "euler_a"

7. [saving_arguments]

#每次模型权重保存时的格式,可以选择["ckpt", "safetensors", "diffusers", "diffusers_safetensors"],目前SD WebUI兼容"ckpt"和"safetensors"格式模型。
save_model_as = "safetensors"

8. [optimizer_arguments]

#AdamW (default),Lion, SGDNesterov,AdaFactor等。
optimizer_type = "AdaFactor"
#训练学习率,单卡推荐设置2e-6,多卡推荐设置1e-7。
learning_rate = 1e-7
#是否训练时微调Text Encoder。
train_text_encoder = false
#最大梯度范数,0表示没有clip。
max_grad_norm = 0
#设置优化器额外的参数,比如"weight_decay=0.01 betas=0.9,0.999 ..."。
optimizer_args = [ "scale_parameter=False", "relative_step=False", "warmup_init=False",]
#设置学习率调度策略,可以设置成linear, cosine, cosine_with_restarts, polynomial, constant (default), constant_with_warmup, adafactor等。
lr_scheduler = "constant_with_warmup"
#在启动学习率调度策略前,先固定学习率训练的步数。
lr_warmup_steps = 100
2.1.2 sample_prompt.toml

主要作用是在训练中阶段性验证模型的性能,里面包含了模型生成验证图片的相关参数:

[prompt]
width = 1024
height = 1024
scale = 7
sample_steps = 28
[[prompt.subset]]
prompt = "1girl, aqua eyes, baseball cap, blonde hair, closed mouth, earrings, green background, hat, hoop earrings, jewelry, looking at viewer, shirt, short hair, simple background, solo, upper body, yellow shirt"

(3) SDXL关键参数详解

  • 1. pretrained_model_name_or_path对SDXL模型微调训练的影响

pretrained_model_name_or_path:我们需要加载本地的SDXL模型作为训练底模型。

在SDXL全参数微调训练中,底模型的选择可以说是最为重要的一环。我们需要挑选一个生成能力分布与训练数据分布近似的SDXL模型作为训练底模型(比如说我们训练二次元人物数据集,可以选择生成二次元图片能力强的SDXL模型)。SDXL在微调训练的过程中,在原有底模型的很多能力与概念上持续扩展优化学习,从而得到底模型与数据集分布的一个综合能力。

  • 2. xformers加速库对SDXL模型微调训练的影响

当我们将xformers设置为true时,使用xformers加速库能对SDXL训练起到2倍左右的加速,因为其能使得训练显存占用降低2倍,这样我们就能增大我们的Batch Size数

想要启动xformers加速库,需要先安装xformers库源,这也非常简单,我们只需要在命令行输入如下命令即可:

pip install xformers -i https://pypi.tuna.tsinghua.edu.cn/simple some-package
  • 3. learning_rate对SDXL模型微调训练的影响

SDXL训练过程对学习率的设置非常敏感,如果我们将学习率设置的过大,很有可能导致SDXL模型训练跑飞,在前向推理时生成非常差的图片;如果我们将学习率设置的过小,可能会导致模型无法跳出极小值点。

这里总结了相关的SDXL学习率设置经验,分享给大家。如果我们总的Batch Size(单卡Batch Size x GPU数)小于10,可以设置学习率2e-6;如果我们总的Batch Size大于10小于100,可以设置学习率1e-7。

  • 4. 使用save_state和resume对SDXL模型训练的中断重启

在AI绘画领域,很多时候我们需要进行大规模数据的训练优化,数据量级在10万甚至100万以上,这时候整个训练周期需要一周甚至一个月,训练中可能会出现一些通讯/NCCL超时等问题,导致训练中断。

经典NCCL超时问题如下所示:

[E ProcessGroupNCCL.cpp:828] [Rank 0] Watchdog caught collective operation timeout: WorkNCCL(SeqNum=213, OpType=ALLREDUCE, Timeout(ms)=1800000) ran for 1809831 milliseconds before timing out.

这些训练中断问题会导致我们的训练成本大大增加,为了解决这个问题,我们可以在config_file.toml中设置save_state = true,这样我们在训练模型时不单单保存模型权重,还会保存相关的optimizer states等训练状态

接着,我们在config_file.toml中设置resume = “/本地路径/模型权重保存地址”,重新运行SDXL训练脚本,这时会直接调取训练中断前的模型权重与训练状态,接着继续训练。

(4) SDXL模型开始训练

完成训练参数配置后,我们就可以运行训练脚本进行SDXL模型的全参微调训练了。

2.4 基于SDXL训练LoRA模型

目前Stable Diffusion XL全参微调的训练成本是Stable Diffusion之前系列的2-3倍左右,而基于Stable Diffusion XL训练LoRA的成本与之前的系列相比并没有太多增加,故训练LoRA依旧是持续繁荣SDXL生态的高效选择。

(1) SDXL LoRA数据集制作

SDXL LoRA训练数据集筛选要求和SDXL微调不一样:

  • 当我们训练人物主题时,一般需要10-20张高质量数据;- 当我们训练画风主题时,需要100-200张高质量数据;当我们训练抽象概念时,则至少需要200张以上的数据。
  • 不管是人物主题,画风主题还是抽象概念,一定要保证数据集中数据的多样性(比如说猫女姿态,角度,全身半身的多样性)。
  • 每个数据都要符合我们的审美和评判标准!每个数据都要符合我们的审美和评判标准!每个数据都要符合我们的审美和评判标准。

按照本文4.3 Stable Diffusion XL数据集制作章节里的步骤,进行数据的清洗,自动标注,以及添加特殊tag——即触发词。

除了对数据进行标注,我们还需要对数据的标注进行清洗,删除一些概念与触发词重合的标签. 为什么我们要进行数据标注的清洗呢?因为如果不对标注进行清洗,会导致训练时的tag污染。

我们拿猫女数据集为例,我们想要让SDXL LoRA模型学习猫女的主要特征,包括脸部特征,服装特征(最具猫女特点的黑色皮衣和黑色眼罩)等,我们想让“catwomen”学习到这些特征。但是自动标注会给数据打上一些描述脸部特征和服装特征的tag,导致猫女的主要特征被这些tag分走,从而导致tag污染。这样就会导致很多精细化的特征丢失在自动标注的tag中,使得SDXL LoRA在生成猫女图片时缺失黑色皮衣或者黑色眼罩等。

所以我们需要删除自动标注的脸部,服装等tag,从而使得保留下来的触发词等标签是SDXL LoRA模型着重需要学习的。

一张一张手动删除标签费时费力,这里推荐大家使用Stable Diffusion WebUI的一个数据标注处理插件:stable-diffusion-webui-dataset-tag-editor,可以对标签进行批量处理,非常方便。

(2) SDXL LoRA训练参数配置

大家可以在SDXL-Trian项目中train_config/XL_LoRA_config路径下找到SDXL LoRA的训练参数配置文件config_file.toml和sample_prompt.toml,他们分别存储着SDXL_LoRA的训练超参数与训练中的验证prompt信息。

其中config_file.toml文件中的配置文件包含了sdxl_arguments,model_arguments,dataset_arguments,training_arguments,logging_arguments,sample_prompt_arguments,saving_arguments,optimizer_arguments以及additional_network_arguments九个个维度的参数信息。

训练SDXL_LoRA的参数配置与SDXL全参微调的训练配置有相同的部分(上述的前八个维度),也有LoRA的特定参数需要配置(additional_network_arguments)。

下面我们首先看看这些共同的维度中,有哪些需要注意的事项吧:

2.1 训练参数讲解(XL_LoRA_config文件夹)
2.1.1 config_file.toml

1. [sdxl_arguments] # 与SDXL全参微调训练一致

cache_text_encoder_outputs = true
no_half_vae = true
min_timestep = 0
max_timestep = 1000
shuffle_caption = false

2. [model_arguments] # 与SDXL全参微调训练一致

pretrained_model_name_or_path = "/本地路径/SDXL模型文件"
# 如果只使用模型自带的VAE,不读取额外的VAE模型,则需要将本行直接删除
vae  = "/本地路径/VAE模型文件" 

3. [dataset_arguments] # 与SDXL全参微调训练不一致

#LoRA训练过程中取消了caption_dropout_rate = 0,caption_tag_dropout_rate = 0,
#caption_dropout_every_n_epochs = 0这三个参数,因为本身LoRA的模型容量较小,不需要再进行类标签Dropout的操作了。
debug_dataset = false
in_json = "/本地路径/data_meta_lat.json"
train_data_dir = "/本地路径/训练集"
dataset_repeats = 1
keep_tokens = 0
resolution = "1024,1024"
color_aug = false
token_warmup_min = 1
token_warmup_step = 0

4. [training_arguments] # 与SDXL全参微调训练不一致

#SDXL_LoRA增加了sdpa参数,当其设置为true时,训练中启动scaled dot-product attention优化,
#这时候就不需要再开启xformers了
output_dir = "/本地路径/模型权重保存地址"
output_name = "sdxl_lora_qclineart"
save_precision = "fp16"
save_every_n_epochs = 1
train_batch_size = 4
max_token_length = 225
mem_eff_attn = false
sdpa = true
xformers = false
max_train_epochs = 100 #max_train_epochs设置后,会覆盖掉max_train_steps,即两者同时存在时,以max_train_epochs为准
max_data_loader_n_workers = 8
persistent_data_loader_workers = true
gradient_checkpointing = true
gradient_accumulation_steps = 1
mixed_precision = "fp16"

5. [logging_arguments] # 与SDXL全参微调训练一致

log_with = "tensorboard"
logging_dir = "/本地路径/logs"
log_prefix = "sdxl_lora_qclineart"

6. [sample_prompt_arguments] # 与SDXL全参微调训练一致

sample_every_n_epochs = 1
sample_sampler = "euler_a"

7. [saving_arguments] # 与SDXL全参微调训练一致

save_model_as = "safetensors"

8. [optimizer_arguments] # 与SDXL全参微调训练不一致

optimizer_type = "AdaFactor"
learning_rate = 1e-5 # 训练SDXL_LoRA时,学习率可以调的大一些,一般比SDXL全参微调的学习率大10倍左右,比如learning_rate = 1e-5
max_grad_norm = 0
optimizer_args = [ "scale_parameter=False", "relative_step=False", "warmup_init=False",]
lr_scheduler = "constant_with_warmup"
lr_warmup_steps = 100

除了上面的参数,训练SDXL_LoRA时还需要设置一些专属参数,这些参数非常关键:
9. [additional_network_arguments]

#保存模型权重时不附带Metadata数据,建议关闭,能够减少保存下来的LoRA大小。
no_metadata = false
#选择训练的LoRA模型结构,可以从["networks.lora", "networks.dylora", "lycoris.kohya"]中选择,最常用的LoRA结构默认选择"networks.lora"。
network_module = "networks.lora"
#设置LoRA的RANK,设置的数值越大表示表现力越强,但同时需要更多的显存和时间来训练。
network_dim = 32
#设置缩放权重,用于防止下溢并稳定训练的alpha值。
network_alpha = 16
#置卷积的Rank与缩放权重。
network_args = [ "conv_dim=32", "conv_alpha=16",]
#如果设置为true,那么只训练U-Net部分。
network_train_unet_only = true

下面表格中给出一些默认配置,大家可以作为参考:

network_categorynetwork_dimnetwork_alphaconv_dimconv_alpha
LoRA321--
LoCon16881
LoHa8441

如果我们想要训练LoRA,我们需要设置network_module = “networks.lora”,同时设置network_dim和network_alpha,和上面的配置一致。

如果我们想要训练LoCon,我们需要设置network_module = "lycoris.kohya"和algo=“locon”,同时设置network_dim和network_alpha:

network_module = "lycoris.kohya"
algo = "locon"
network_dim = 32
network_alpha = 16
network_args = [ "conv_dim=32", "conv_alpha=16",]

如果我们想要训练LoHa,我们需要设置network_module = "lycoris.kohya"和algo=“loha”,同时设置network_dim和network_alpha:

network_module = "lycoris.kohya"
algo = "loha"
network_dim = 32
network_alpha = 16
network_args = [ "conv_dim=32", "conv_alpha=16",]

(3) SDXL LoRA关键参数详解

  • 1. train_batch_size对SDXL LoRA模型训练的影响

和传统深度学习一样,train_batch_size即为训练时的batch size,表示一次性送入SDXL LoRA模型进行训练的图片数量。一个Epoch表示模型完整地遍历一次整个训练数据集

所以一般来说,较大的batch size往往每个epoch训练时间更短,但是显存占用会更大,并且收敛得慢(需要更多epoch数)。较小的batch size每个epoch训练时间长,但是显存占用会更小,并且收敛得快(需要更少epoch数)。

但是有研究表明这个结论会在batch size大于8000的时候才会体现,所以在实际的训练时,如果GPU数不大于8卡的话,还是需要尽可能占满GPU显存为宜,比如64-96之间(理论上batch size = 2 n 2^n 2n 时计算效率较高),训练一般都能取得不错效果。

上面的结论在训练SDXL大模型时是非常适用的,不过我们在训练SDXL LoRA模型时,一般来说数据量级是比较小的(10-300为主),所以在这种情况下,我们可以设置batch size为2-6即可。

  • 2. pretrained_model_name_or_path对SDXL LoRA模型训练的影响

pretrained_model_name_or_path参数中我们需要加载本地的SDXL模型作为训练底模型。

底模型的选择至关重要,SDXL LoRA的很多底层能力与基础概念的学习都来自于底模型的能力。并且底模型的优秀能力需要与我们训练的主题,比如说人物,画风或者某个抽象概念相适配。如果我们要训练二次元LoRA,则需要选择二次元底模型,如果我们要训练三次元LoRA,则需要选择三次元底模型,以此类推。

  • 3. network_dim对SDXL LoRA模型训练的影响

network_dim即特征维度,越高表示模型的参数量越大,设置高维度有助于LoRA学习到更多细节特征,但模型收敛速度变慢,同时也更容易过拟合,需要的训练时间更长。所以network_dim的设置需要根据任务主题去调整。

一般来说,在SDXL的1024*1024分辨率训练基础上,可以设置network_dimension = 128,此时SDXL LoRA大小约为686MB。

  • 4. network_alpha对SDXL LoRA模型训练的影响

network_alpha是一个缩放因子,用于缩放模型的训练权重 W W W, W = W i n × a l p h a / d i m W = W_{in} \times alpha / dim W=Win×alpha/dim
。network_alpha设置的越高,LoRA模型能够学习更多的细节信息,同时学习速率也越快,推荐将其设置为network_dim的一半。

(4) SDXL LoRA模型训练

完成训练参数配置后,我们就可以运行训练脚本进行SDXL_LoRA模型的训练了。
我们打开SDXL_fintune_LoRA.sh脚本,可以看到以下的代码:

accelerate launch \
  --config_file accelerate_config.yaml \
  --num_cpu_threads_per_process=8 \
  /本地路径/SDXL-Train/sdxl_train_network.py \
  --sample_prompts="/本地路径/SDXL-Train/train_config/XL_LoRA_config/sample_prompt.toml" \
  --config_file="/本地路径/SDXL-Train/train_config/XL_LoRA_config/config_file.toml"

我们把训练脚本封装在accelerate库里,这样就能启动我们一开始配置的训练环境了,同时我们将刚才配置好的config_file.toml和sample_prompt.toml参数传入训练脚本中。

接下里,就到了激动人心的时刻,我们只需在命令行输入以下命令,就能开始SDXL_LoRA训练啦:

# 进入SDXL-Trian项目中
cd SDXL-Trian

# 运行训练脚本!
sh SDXL_fintune_LoRA.sh

当我们基于SDXL训练SDXL LoRA模型时,我们设置分辨率为1024+FP16精度+xformers加速时,进行Batch Size = 1的微调训练需要约13.3G的显存,进行Batch Size=8的微调训练需要约18.4G的显存,所以想要微调训练SDXL LoRA模型,最好配置一个16G以上的显卡,能让我们更佳从容地进行训练。

感谢
https://zhuanlan.zhihu.com/p/643420260

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/494919.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Sublime for Mac 使用插件Terminus

1. 快捷键打开命令面板 commandshiftp2. 选择 Package Control: Install Package&#xff0c;然后会出现安装包的列表 3. 在安装终端插件前&#xff0c;我们先装个汉化包&#xff0c;ChineseLocallization&#xff0c;安装完重启 4. 输入 terminus&#xff0c;选择第一个&am…

面试题:Java虚拟机JVM的组成

1. 基础概念 JVM是什么 Java Virtual Machine Java程序的运行环境&#xff08;java二进制字节码的运行环境&#xff09; 好处&#xff1a; 一次编写&#xff0c;到处运行 自动内存管理&#xff0c;垃圾回收机制 JVM由哪些部分组成&#xff0c;运行流程是什么&#xff1f; …

DoCAN配置

DoCAN涉及模块 CanTrcv -> Can -> CanIf -> CanTp -> PduR -> Dcm DCM DcmDslProtocolRow DcmDslProtocolID: DCM_UDS_ON_CAN DslProtocolSIDTable DcmDslMainConnection Rx 物理寻址/功能寻址 PDUR PduRBswModules-Dcm

spring安全框架之Shiro

Shiro 一、现存问题 1.1 现存问题 认证&#xff08;登录&#xff09;&#xff1a;认证操作流程都差不多&#xff0c;但是每次都需要手动的基于业务代码去实现&#xff0c;很麻烦&#xff01; 授权&#xff1a;如果权限控制粒度比较粗&#xff0c;可以自身去实现&#xff0c…

【论文阅读】Faster Neural Networks Straight from JPEG

Faster Neural Networks Straight from JPEG 论文链接&#xff1a;Faster Neural Networks Straight from JPEG (neurips.cc) 作者&#xff1a;Lionel Gueguen&#xff0c;Alex Sergeev&#xff0c;Ben Kadlec&#xff0c;Rosanne Liu&#xff0c;Jason Yosinski 机构&#…

数据结构与算法 单链表的基本运算

一、实验内容 编写一个程序实现&#xff0c;实现单链表的各种基本运算&#xff08;假设单链表的元素类型为char&#xff09;&#xff0c;并以此为基础设计一个程序完成下列功能&#xff1a; 初始化单链表&#xff1b;采用尾插法依次插入元素a&#xff0c;b&#xff0c;c&…

GitHub Copilot如何订阅使用

1.Copilot是什么 Copilot是由Github和OpenAI联合开发的一个基于人工智能大模型的代码写作工具。 我们都知道Github是世界上拥有开源项目及代码最多的一个平台&#xff0c;有了这么一个得天独厚的资源&#xff0c;Github联合OpenAI喂出了Copilot。经过不断地更新迭代&#xff…

GNU Radio之OFDM Carrier Allocator底层C++实现

文章目录 前言一、OFDM Carrier Allocator 简介二、底层 C 实现1、make 函数2、ofdm_carrier_allocator_cvc_impl 函数3、calculate_output_stream_length 函数4、work 函数5、~ofdm_carrier_allocator_cvc_impl 函数 三、OFDM 数据格式 前言 OFDM Carrier Allocator 是 OFDM …

Spring Boot项目启动过程中为什么日志打印没有显示完整包名呢?

一、前言 不知道大家注意过没有&#xff0c;在Spring Boot项目启动过程中日志打印并没有显示完整的报名&#xff0c;而是显示一些o.a.c&#xff0c;o.s.web形式的包名&#xff0c;如下图&#xff1a; 这是为什么呢&#xff1f; 二、原理 首先&#xff0c;我们先看一下Spring…

ArrayList和LinkedList有什么区别?

ArrayList和LinkedList的区别 ArrayList 和 LinkedList 是 Java 中常用的两种集合类&#xff0c;它们都实现了 List 接口&#xff0c;但在内部实现和性能上有一些区别。 内部实现&#xff1a; ArrayList 使用数组实现&#xff0c;它的元素在内存中是连续存储的&#xff0c;每…

软件部署资源计算工具:精确评估资源需求

软件部署资源计算工具&#xff1a;精确评估资源需求 在当今快速发展的信息技术时代&#xff0c;软件部署已成为企业运营不可或缺的一部分。然而&#xff0c;一个常见的挑战是如何精确评估软件部署所需的资源。资源评估不仅关系到软件的性能和稳定性&#xff0c;还直接影响到成…

Spring Boot:Web开发之三大组件的整合

Spring Boot 前言Spring Boot 整合 ServletSpring Boot 整合 FilterSpring Boot 整合 Listener 前言 在 Web 开发中&#xff0c;Servlet 、Filter 和 Listener 是 Java Web 应用中的三大组件。Servlet 是 Java 代码&#xff0c;通过 Java 的 API 动态的向客户端输出内容。Filt…

SpringMvc之映射器HandlerMapping

简介 在springmvc的处理流程中&#xff0c;第一步就是查询请求对应的映射器&#xff0c;然后组装成处理器链处理请求&#xff0c;本文意在梳理该过程 重要实现 HandlerMapping是一个接口&#xff0c;该接口用于通过HttpServletRequest寻找对应的处理器&#xff0c;接口介绍如下…

python学习15:python中的input语句

python中的input语句 我们前面学习过print语句&#xff0c;可以将内容输出到屏幕上&#xff1b;在python中&#xff0c;与之对应的还有一个input语句&#xff0c;用来获取键盘输入。 数据输出&#xff1a;print 数据输入&#xff1a;input 使用上也很简单&#xff1a; 使用inp…

31-3 文件包含漏洞 - 文件包含漏洞利用(CVE-2021-3019:Lanproxy 任意文件读取漏洞复现)

一、Lanproxy简介: lanproxy是一个将局域网个人电脑、服务器代理到公网的内网穿透工具,支持TCP流量转发,可支持任何TCP上层协议(访问内网网站、本地支付接口调试、SSH访问、远程桌面等)。 二、漏洞概述: Lanproxy1.0 版本存在目录遍历漏洞,可通过绕过路径限制(../)来…

量化交易入门(二十四)MTM指标买卖逻辑和回测

MTM指标可以用来指导买卖决策,其基本逻辑如下: 买入信号: 当MTM从负值上穿0线,并向上突破某个阈值(如20)时,表明上升动力充足,可以考虑买入。当MTM在0线上方并持续上升,创出新高时,表明上升趋势强劲,可以考虑加仓或持有。 卖出信号: 当MTM从正值下穿0线,并向下突破某个阈值(如-…

C++中stack的用法及其解析

一、stack的介绍 1.stack是一个容器适配器&#xff0c;它的名字叫做栈 专门用在后进先出的上下文环境中的&#xff0c;它的删除与插入操作只能从容器的一端进行。形象一点&#xff0c;就好像一个容器里放东西&#xff0c;先放进去的就在底部&#xff0c;要想拿出来&#xff0c;…

华为昇腾asend

昇腾Ascend C编程语言 Ascend C原生支持C/C编程规范&#xff0c;通过多层接口抽象、并行编程范式、孪生调试等技术&#xff0c;极大提高了算子的开发效率&#xff0c;帮助AI 参考文章 手把手教你在昇腾平台上搭建PyTorch训练环境 - 哔哩哔哩 (bilibili.com)https://www.bilibi…

PCL点云处理之重复随机采样一致性(RRANSAC法)平面拟合(二百三十七)

PCL点云处理之重复随机采样一致性(RRANSAC法)平面拟合(二百三十七) 一、算法介绍二、算法实现1.代码2.结果一、算法介绍 pcl::SAC_RRANSAC"是 PCL库中的一个方法,是 RANSAC 方法的改进版本,通过多次重复采样和模型拟合来提高鲁棒性。RRANSAC 的思想是在 RANSAC 的基…

双网卡环境概率出现DNS解析错误

测试环境 VMware Rocky Linux 9 虚拟机, 双网卡(eth0和eth1)配置如下&#xff1a; eth0 10.206.216.27/24 DNS 10.204.16.18 eth1 192.168.1.27/24 DNS 192.168.1.1问题描述 手动配置eth1的DNS后&#xff0c;网络不通&#xff0c;通过抓包发现是eth1的DNS server配置有误…