对于sd的lora训练教程,我感觉其实都差不多,有许多的人对lora训练做出了较为详细和符合理论与代码的解释,在这里我只是对这些天我自己亲身训练lora的方法进行一部分总结。(因为我对神经网络和sd的架构还停留在比较原始甚至是说比较民科的阶段,所以有错误是非常正常的...如果有不认同的欢迎指正(´-ω-`))
之所以想写这个,是因为感觉单纯的机器式的无脑炼画风lora对于我来说太折磨了,与其这样不如把自己训练时的一些经验分享出来.....然后投身到其他类型的lora训练)
还有,因为我目前由于学业的关系(概率论挂了要补考和学一大堆课程....)所以更新会十分的缓慢混乱,假如你看到这里还接受的话那就看下去吧(悲)
1,lora是什么东东?
lora原本是微软的研究人员为了微调大语言模型的一种方法(https://github.com/microsoft/LoRA 中文为大型语言模型的低秩适应,论文https://arxiv.org/abs/2106.09685) 后来有人把lora的这个方法在代码上运用到了微调diffuser模型的过程中(https://github.com/cloneofsimo/lora 和 https://huggingface.co/blog/lora)....于是有了这么一个小消耗的(像是在sd1.5这样的以512x512分辨率训练的模型上训练的话,大约要8gb显存)的微调模型的新方法,简单的来说lora就是一个在大模型上训练的插件小模型,我们只训练插件模型的几个层,而不需要对大模型的所有层进行微调因此减少了训练时的显存消耗
(自然语言处理的一个重要范例包括对通用领域数据的大规模预训练以及对特定任务或领域的适应。当我们预训练更大的模型时,重新训练所有模型参数的完全微调变得不太可行。以 GPT-3 175B 为例——部署微调模型的独立实例(每个实例都有 175B 参数)的成本极其昂贵。我们提出了低秩适应(LoRA),它冻结了预训练的模型权重,并将可训练的秩分解矩阵注入到 Transformer 架构的每一层中,大大减少了下游任务的可训练参数的数量。与使用 Adam 微调的 GPT-3 175B 相比,LoRA 可以将可训练参数数量减少 10,000 倍,GPU 内存需求减少 3 倍。LoRA 在 RoBERTa、DeBERTa、GPT-2 和 GPT-3 上的模型质量表现与微调相当或更好,尽管可训练参数较少、训练吞吐量较高,并且与适配器不同,没有额外的推理延迟。)
2,lora微调了哪些部分?
lora大约微调了模型的clip层,unet层中的少数关键层的权重与偏置(我的民科理解(´-ω-`))
clip:text en/decoder(文本编码/解码器)
用于将tag或者prompt转化为数字token后输入到transformers形成77个嵌入向量这些向量可以被认为是embedding,这个embedding可以认为是“生成”图像的condition指导unet层对随机噪声图进行逐步去噪
unet:负责“生成”图像其实是在被压缩的潜空间latent space里面对随机噪声图经过一系列操作(比如先识别图片再缩小图片后对图片某些区域进行定义或者是概念再逐步去噪)得到一个符合tag对应的模型里的元素(向量)的图片
vae:image en/decoder(图像编码/解码器)
把人可以看的懂得“像素图”进行“压缩”,变为一张看不懂的“潜空间图片”(我不知道怎么形容你可以理解为你运行了没几步就停止生成的文生图图片?)减少运算量,达到优化运行速度的效果同时对环境友好(貌似是diffusers模型的创新点之一?)
3,lora怎么用
sd1.5.0版本后lycoris和locon插件记得卸载,因为locon插件已经过时,github仓库无人维护,会出现一些奇怪报错,lycoris插件则是在1.5.0版本后已经集成在webui里面了,不需要在webui再次安装插件,否则可能有报错(原因未知)不过貌似不管也行,不过1.5.0之前版本的webui就需要lycoris插件了(但还是推荐更新到新版本)
lycoris插件安装地址https://github.com/KohakuBlueleaf/a1111-sd-webui-lycoris
首先是找到lora模型也就是一些十几到100多mb大小的文件,塞入webui的model文件夹里面的lora文件夹
然后对lora分类,可以在文件夹里面分多个文件夹,这样调用lora的时候就比较方便
lycoris文件夹里面放的是lycoris模型,即训练时使用了lycoris训练脚本的模型(locon,loha,ia3等等)目前貌似lyco模型用lora前缀也可以,详细请看a1111的库https://github.com/AUTOMATIC1111/stable-diffusion-webui
不同种类的lora有不同的用法
画风lora可以文生图,图生图,可以和人物lora配合使用
人物lora可以文生图,也可以在图生图改变画风的时候保留有关人物的概念
动作,服装,人物细节等等“概念”lora也和画风的用法类似
4,lora训练?
(十分推荐3Blue1Brown对于神经网络的讲解,十分的通俗易懂https://www.bilibili.com/video/BV1bx411M7Zx/?spm_id_from=333.999.0.0&vd_source=811ef3ee5133f78287869bbbe3328cff)
首先说一下训练的本质是什么,其实根据网上的一些神经网络的一些图形化讲解视频
,我们可以大概看成是一些点对点的传输的网络,这个网络有许多层,每一层有许多神经元,每个神经元有一个activate(激发值)。在我们的训练集里面,我们的神经网络会识别图片的特定区域,将一张图片转化为对应于特定区域的一些特征值,也就是输入到第一层的神经元里面,之后第一层神经元与第二层神经元之间的一些关联(一个加权和公式:a1*x1+a2*x2+a3*x3.....+bias)即神经元之间的(联系)的权重和各个神经元自己的偏置bias得到下一层的activate(激发值)也就是输入的图片被识别得到第一层神经元的激发值,第一层决定了第二层的激发值,以此类推得到最后一层的结果。这个一个训练过程得到的loss值就是与原图像直接的差值的平方和,也就是对应的tag与训练集的图片的差别有多大.
其中,loss值即代价函数或者损失函数是对训练集整体所得到的,也就是loss值的高与低反应了对训练集图像在特定tag出的图(即得到的激发值)和原图上的差别(即原图的激发值)
训练过程则是一张梯度下降的过程,举个例子,二维平面里面的极小值就是斜率k=0且为周围最小的值,假如一个人想要沿着某点去往某个极小值,就需要沿着斜率k为负的方向“下降”,因为二维平面里面k为正时会导致y上生,k为负会导致y下降。
然后跳到三维空间,把斜率换成梯度,我们在高数书可以知道,梯度的方向是函数增加最快的方向,那梯度的反方向就是函数下降最快的方向,因此ai学习的目的就是逼近loss函数的值最低的那个点,也就是最拟合最像原图的那个平均综合值,那么如何逼近呢?这个时候就要用到反向传播算法了,他会和原图进行比较,得出一个差值,进而对这个差值如何达到来调整之前的每个神经元里的bias和各个神经元之间的权重,而算法也就是我们用的优化器都是找到我们刚刚开始训练的那个随机点的负梯度后进行改变内部参数的行为,并在整体上拟合训练集降低原图和训练集的loss值的行为称之为训练
当然,实际情况并不是三维的.....应该是几万甚至是几十万个参数,即每个神经元的bias偏置和权重多作为参数来组成loss函数,而我们说三维只是为了便于理解训练的本质而已)
5,实际操作步骤?
(注意,一下皆为sd1.5的内容,我还没有炼过sdxl的模型)
lora的一些参数
model_train_type = "sd-lora" pretrained_model_name_or_path = "D:/stablediffusion/lora_train/lora-scripts/sd-models/Animefull-latest.ckpt" v2 = false train_data_dir = "D:/stablediffusion/lora_train/lora-scripts/train/毛玉乳牛" prior_loss_weight = 1 resolution = "768,768" enable_bucket = true min_bucket_reso = 256 max_bucket_reso = 1_536 bucket_reso_steps = 64 output_name = "myrn_v1" output_dir = "./output" save_model_as = "safetensors" save_precision = "bf16" save_every_n_epochs = 1 max_train_epochs = 15 train_batch_size = 4 gradient_checkpointing = false network_train_unet_only = false network_train_text_encoder_only = false learning_rate = 0.00006 unet_lr = 0.00006 text_encoder_lr = 0.000006 lr_scheduler = "cosine_with_restarts" lr_warmup_steps = 0 lr_scheduler_num_cycles = 3 optimizer_type = "Lion" min_snr_gamma = 5 network_module = "networks.lora" network_dim = 128 network_alpha = 128 network_dropout = 0.1 log_with = "tensorboard" logging_dir = "./logs" caption_extension = ".txt" shuffle_caption = true weighted_captions = false keep_tokens = 1 max_token_length = 255 caption_tag_dropout_rate = 0.2 multires_noise_iterations = 6 multires_noise_discount = 0.3 seed = 1_337 clip_skip = 2 mixed_precision = "bf16" full_fp16 = false full_bf16 = false xformers = true lowram = false cache_latents = true cache_latents_to_disk = true cache_text_encoder_outputs = false cache_text_encoder_outputs_to_disk = false persistent_data_loader_workers = true
loha的一些参数
model_train_type = "sd-lora" pretrained_model_name_or_path = "D:/stablediffusion/lora_train/lora-scripts/sd-models/Animefull-latest.ckpt" v2 = false train_data_dir = "C:/Users/admin/Desktop/1" prior_loss_weight = 1 resolution = "768,1024" enable_bucket = true min_bucket_reso = 256 max_bucket_reso = 1_536 bucket_reso_steps = 64 output_name = "JIMA_artist2" output_dir = "./output" save_model_as = "safetensors" save_precision = "bf16" save_every_n_epochs = 1 max_train_epochs = 15 train_batch_size = 4 gradient_checkpointing = false network_train_unet_only = false network_train_text_encoder_only = false learning_rate = 0.00006 unet_lr = 0.00006 text_encoder_lr = 0.000005 lr_scheduler = "cosine_with_restarts" lr_warmup_steps = 0 lr_scheduler_num_cycles = 3 optimizer_type = "Lion" min_snr_gamma = 5 network_module = "lycoris.kohya" network_dim = 16 network_alpha = 8 network_dropout = 0 log_with = "tensorboard" logging_dir = "./logs" caption_extension = ".txt" shuffle_caption = true weighted_captions = false keep_tokens = 1 max_token_length = 255 multires_noise_iterations = 6 multires_noise_discount = 0.3 seed = 1_337 clip_skip = 2 mixed_precision = "bf16" full_fp16 = false full_bf16 = false xformers = true lowram = false cache_latents = true cache_latents_to_disk = true cache_text_encoder_outputs = false cache_text_encoder_outputs_to_disk = false persistent_data_loader_workers = true network_args = [ "conv_dim=4", "conv_alpha=2", "dropout=0.1", "algo=loha" ]
1一般步骤如下:先明确自己需要训练的lora种类是什么,再想这个lora要达到什么样的效果或者作用,并确定好触发词或者其他的东西
我目前只讲画风lora或者loha,以下是画风lora的一些参考
2之后去寻找训练集,你可以在网上寻找到你想要的图片也就是训练集
你可以使用脚本,爬虫,论坛,网盘,种子,啊等等方式找到你想要的图片)具体的内容就不展开了
我是用pixiv和twitter配合脚本下载,或者直接到悲伤熊猫(ehentai)的里站和表站去看看,还有一些论坛去找一下,一般这样就比较全了,当然我推荐支持作者,去patreon或者fanbox下(不过要钱还有可能不全等等因素)
3最后是裁剪训练集,分文件夹调整repeat次数,打标
对于画风,我推荐tagger1.4打标0.3置信度,机器打上的标签我们一般叫做全标
我们对于机器打的标签进行删除(即删标)和修改的行为(改正错误标签)是一种精选化打标(精准打标)的方法,画风打标相对于其他种类的lora十分的轻松,机打全标后不删,直接用就可以了,如果追求更好的效果需要手动更改标签,画风lora或者loha可以不使用触发词,当然你加触发词也可以
对于人物等其他类型lora使用我推荐0.35,不推荐Deepdabooru和BLIP模型,BLIP是自然语言描述特别容易描写错误,Deepdabooru和tagger1.4一样都是tag描述图片,但是错误率高很多。
假如你训练多概念lora,需要将不同文件夹里的图片数和repeat重复数的乘积尽可能的保持一致,我猜测是因为ai训练的过程中,由于训练数据比较少,会很大程度上根据你的训练集来学习(因此会遗忘原有的概念),假如你要同时学的两种概念在训练集上不能平衡,就会导致一种概念过拟合,一种概念欠拟合的情况,即反馈在模型内部神经元的权重上不能正确表现出训练集(或者说小的被大的盖过去了)原因是ai学习的时候是对训练集的整体进行拟合,而不是某一张图或者几张图,调整权重或者说矩阵来表现图片里的某些向量,多的拟合的会多一点,少的就会拟合的少一点甚至不形成概念(导致概念融合)在拟合,即逼近loss值最低点的时候被反向传播算法给减少了其权重,导致会有概念融合的情况产生。平衡的lora则会导致概念之间的平衡,这样ai在降低loss值的时候就会同时学习两种概念,避免了以上的情况
4然后是介绍一下我们的训练工具
来到我们的训练脚本并调整超参数,
我使用过
kohya_ss的gui脚本(可以训练db和lora和finetune)https://github.com/bmaltais/kohya_ss
秋叶aaaki的lora训练包,目前看还是秋叶的包对于我来说无脑且好用非常nice(嘿嘿嘿不知道算不算夹杂私货)(只能训练lora)https://github.com/Akegarasu/lora-scripts
还有青龙圣者在秋叶的基础上修改(缝缝补补)的包,但是有一点点难用,可以试一下(反正我是试试就逝世,~升天~)(可以训练db和lora与finetune)
以及貌似功能很强大的HCP diffusion,目前也出了gradio的脚本gui界面,可以尝试下载来用?我是部署过了但是感觉只是训练lora的话没必要?https://github.com/7eu7d7/HCP-Diffusion-webui
对于学习率
在以Lion优化器训练的前提下,对于画风loha/lora我一般使用6e-5为unet学习率,6e-6为te学习率
或者根据之前测试的结果学习率unet约为te的5到10倍比较好比如之前我曾经使用过的7e-5unet,8e-6te
或者你可以使用3e-5到7e-5这个区间的unet学习率来训练,3e-5我感觉可能有点欠拟合,7e-5和6e-5差不多,再高一点就过拟合比较严重了对于alpha与dim值,
画风lora我推荐128line dim128line alpha无脑炼谢谢(笑)确实很好用
画风loha由于相较于lora容易过拟合,所以我之前一般用16 line dim 8 line alpha 4conv dim 1conv alpha,但是貌似也有conv与line alpha都拉到1,然后拉高学习率的用法,和line与conv dim/alpha都使用同样的比率来训练的例子比如line8/2,conv4/1或者line16/4,conv8/2以及line 16/8和conv4/2的情况
对于学习步数
我推荐在20000步以下(也就是图片数x文件夹repeat数xepoch数)
实际步数还要除以batchsize,但我一般不管(0v0)我是估算在batchsize为1的情况下的学习步数
人物不要在正常的学习率下超过10000步,大约在5000步左右能达到较好的epoch
画风大概在10000步左右较好,之所以20000步是因为怕欠拟合(当测试的时候发现20000步epoch出的图不像,这个时候就需要调高学习率和高alpha值了)
对于分辨率
画风lora或者loha768到768就好了或者你可以试试看更高的分辨率
但是1024x1024及以上分辨率不推荐(训练太慢了而且相较于768x768分辨率来说收益低)如果你真的想要用大分辨率,我推荐768x1024或者896x896这样的分辨率,用一个个逐步增加的64像素点来压榨gpu显存(前提是不爆显存)
我的显卡是买的pdd上的3090,24gb显存,矿卡,目前来看768x768是比较好的选择,可以用比较大的batchsize(一次性同时训练的图片数)大batchsize训练速度快且对lion优化器有加成,一般在3batchsize以上会有效果,但是低batchsize可能与adam8bit差不多,且训练速度慢
那有人说512x512怎么样呢?我只能说不推荐,画面效果不如768x768,pass!
对于batchsize
越大越好,假如你用lion优化器的话
大batchsize可以提高训练的速度,同时对lion优化器有一定的加成
同时大batchsize会增加对显存的需求,视gpu或者训练的配置和你的时间量力而行
对于图片数量:
目前来看,在不做任何处理的情况下需要30张以上的原图片来训练画风比较好
但是目前也有用正则化来实现少图炼画风和人物的方法,我没试过,不做出评价(笑)
对于优化器
我一般使用lion或者adam8bit还有lion8bit,prodigy感觉容易过拟合,所以不太推荐(也可能是我打标有问题,主要是我太懒了直接机器打标就不管了....)
lion学习率大约为adam8bit的1/3(就是三分之一)
一般1e-4/1e-5为adam8bit学习率,由此可以推出lion则是用3e-5/3e-6(实际情况可以大一点)
对于学习率调度器
强烈推荐带重启的余弦退火,但是重启次数不要超过3次(也就是说无脑填3就行)
或者余弦退火但是预热不要超过总步数的5%
对于训练模型(训练底模)
NAI的4gb或者7gb模型,sd1.5这样的模型上训练比较通用,在某些融合模型上训练则只能在类似的画风的融合模型上表现良好,以外的都会爆炸(比如你用NAI训练人物lora和用AOM3或者anythingv5训练lora的表现都是不一样的)
我一般是用NAI训练模型,用融合模型比如anything出图
5之后开始训练
用训练出来的lora拉xyz图测试lora的各个方面是否符合预期,有无过拟合或者欠拟合等等,酌情分层,
若是不满意可以调整以上3项再训练,也可以在你感觉还行的lora上面继续训练(不推荐?容易过拟合,)
6,最后的一些注意事项
首先,训练集,打标,超参数这三个为lora训练的3要素
训练集与打标都非常重要,超参数的调整反而是没啥必要的....假如你对lora的训练效果不满意,可以先想想训练集里是不是有什么问题,其次是打标,最后才是超参数的调整
训练集要保证高清,与你要训练的内容符合,比如训练人物图片就要有这个人物,训练画风需要有画师的图且图最好为同一类画风(除非你想搞画风融合,否则一定要去掉不同的画风保持画风一致性),训练动作就是某一种动作的图片,训练某种背景就是要使用这种背景的图片,衣服,服装细节等等都是如此
其次,训练集里面的图片如果可以请不要裁剪(容易画风过拟)那假如我就是要画风过拟合或者训练集图片很少怎么办呢?就可以分文件夹调整repeat图片重复数,推荐拉低某个部位的权重即repeat重复数,否则ai很容易为了“学习”训练集里的内容导致你的“画面结构过拟合”只出来某种特写或者局部部位等等。
而画风lora训练虽然可以通过裁剪得到更多的训练集,但是也容易造成一些动作啊,结构啊等等过拟合,总之,如果你是刚刚开始训练lora,我不推荐裁剪(或者说碎尸法,笑)来炼lora,不过某些情况下裁剪确实有用,比如说强调某个主体,将多人图裁剪变成多张图片,还有为了让某个部位比如脸部拟合甚至过拟合等等。
之后是打标,目前来看,还是大多数情况下推荐人物/服装/某种概念/触发词+体位角度背景+1girl这样打标,其余的看情况删除或者保留,画风一般全标
根据我之前提到的训练的本质,我在这里简单的解释一下打标是什么东东(某民科开始忽悠咧)