最近在研究AIGC🤖️技术,看了很多微调方法、论文层。但搞技术这么能纸上谈兵呢?今天本柯南迷就想来实践生成美少女小兰👸
在这篇文章里,我选用了 textual inversion和dreambooth📷来做比较,这两种方法都是通过扩大词字典的嵌入,来插入新的概念。
训练图片处理
在网上找到了11张高清的小兰🌸特写图,尽量找人物主体比较鲜明的图片,这样才能让模型更好地学习到人物特征~ 为了图片不因为resize而变形,这里使用letterbox方法将图片先处理为512×512大小的尺寸:
js
def letterbox_image(image, size=(512, 512), color=(0, 0, 0), scale=False):
iw, ih = image.size
w, h = size
scale = min(w / iw, h / ih)
nw = int(iw * scale)
nh = int(ih * scale)
image = image.resize((nw, nh), Image.BICUBIC)
new_image = Image.new('RGB', size, color)
new_image.paste(image, ((w - nw) // 2, (h - nh) // 2))
return new_image
到这一步,我们需要训练的人物主体数据就处理好啦~
dreambooth微调
dreambooth的效果类似于照相摄影棚------一旦拍摄了几张某个对象的照片,摄影棚就会生成包含该对象在不同条件和场景下的照片。 dreambooth的目标是扩展模型的语言视觉词典,一旦新词典嵌入模型,模型就可以在不同的背景场景下生成新词主题,同时保留其关键识别特征。
这个新词可以用标识符(identifier)来表示,为了防止语言漂移,需要在标识符的后面加入这个新词的大类,比如:"A [V] dog",[V]为标识符,dog为大类。

为了防止语言漂移,研究者提出了 Class-specific Prior Preservation Loss

dreambooth微调代码
转换ckpt检查点文件为diffusers官方权重
这里我选用了huggingface.co/runwayml/st... 上的模型 ,如果只有.ckpt文件,就需要按照readme的指示转换权重
js
!python tools/ckpt2diffusers.py \
--checkpoint_path=./ckpt_models/v1-5-pruned_emaonly.ckpt \
--dump_path=./model \
--original_config_file=./ckpt_models/model.yaml \
--scheduler_type="ddim"
若出现加载的checkpoint和模型的不一致,需要修改statedict中的key和value。
训练object脚本的输入
下一步进入到train_object.sh脚本,我们看到在训练之前需要准备的输入:

INSTANCE_DIR: 一开始处理完的小兰的数据集的路径 CLASS_DIR: 我们还需要准备一个class的数据集,这里我把这个class设为girl,并在网上找了11张动漫少女的图片:

同样使用上面letterbox的方法对图片进行处理,最后放在CLASS_DIR下
TEST_PROMPTS_FILE:用于测试的prompt,可以使用deepdanbooru对预期的图片生成对应的标签。
最后生成的效果
prompt🌹 A photo of a doctor as Mouriran girl, in the hospital, black_hair, looking_at_viewer, smiling, open mouth, white clothes.



prompt🌹 A photo of a professor as Mouriran girl, black_hair, looking_at_viewer, smiling, blue blouse.

可以看出来dreambooth模型学习得比较好,仅仅1000个steps就能捕捉到小兰的特征(特别是头发那个角角),15-20分钟即可训练好。
textual inversion微调
虽然dreambooth能够较好地拟合要学习的主体的特征,但是微调了整个模型,参数量较大,而且每次学习一个新的概念都要重新训练,所以这里我们再探究一下使用textual inversion,这种更轻量级方法的效果。
比起dreambooth需要微调整个模型,textual inversion仅仅只需要微调要插入的词对应的embeddings

loss跟stable diffusion的类似:

代码仓库
这里直接使用diffusers库里examples的训练代码: github.com/huggingface...
根据readme跑代码
修改相关参数设置
js
--pretrained_model_name_or_path: 跟微调dreambooth用到的基础模型一样sdv1-5
--train_data_dir: 一开始处理好的小兰数据路径
--placeholder_token: <mouriran>
--initializer_token: girl
--learnable_property: object
--train_batch_size: 4
--learning_rate: 5e-3
5000个steps大概要花50分钟。。。
最后生成的效果 (5000个steps)



这个生成效果还是比较诡异的。。。。🤢感觉模型应该没有学好对应的embedding,仅仅是生成了漫画风的图片。
根据平时的经验来看,感觉textual inversion还是比较难训的,一是所需要的图片不止3-5张,二是很难学习到主体的细节。如果看到这篇文章的小伙伴有关于使用textual inversion的经验,欢迎评论一起讨论鸭~😃