小白学习笔记,如有错误请各位大佬指正
一、跑通baseline教程
Datawhale 教程链接Datawhale
二、baseline代码分析
1.安装库
!pip install simple-aesthetics-predictor
!pip install -v -e data-juicer #用于数据处理的工具包
!pip uninstall pytorch-lightning -y #移除之前安装的pytorch-lightning包
!pip install peft lightning pandas torchvision #用于机器学习和数据处理
!pip install -e DiffSynth-Studio
2.下载数据集
from modelscope.msdatasets import MsDataset #用于处理数据集
ds = MsDataset.load(
'AI-ModelScope/lowres_anime',
subset_name='default',
split='train',
cache_dir="/mnt/workspace/kolors/data"
) #用于后续的数据处理
#保存数据集中的图片及元数据
import json, os #用于处理文件和目录操作
from data_juicer.utils.mm_utils import SpecialTokens
from tqdm import tqdm #显示循环进度条
os.makedirs("./data/lora_dataset/train", exist_ok=True) #创建保存图像的目录
os.makedirs("./data/data-juicer/input", exist_ok=True) #创建保存元数据的目录
with open("./data/data-juicer/input/metadata.jsonl", "w") as f: #打开文件metadata.jsonl以写入模式,保存元数据
for data_id, data in enumerate(tqdm(ds)): #显示进度条
image = data["image"].convert("RGB") #将图像转换为RGB模式
image.save(f"/mnt/workspace/kolors/data/lora_dataset/train/{data_id}.jpg") #将图像保存到指定路径
metadata = {"text": "二次元", "image": [f"/mnt/workspace/kolors/data/lora_dataset/train/{data_id}.jpg"]} #创建一个包含文本描述和图像路径的字典
f.write(json.dumps(metadata)) #将元数据字典转换为JSON格式并写入文件
f.write("\n") #在文件中写入换行符
3.使用 data-juicer 处理数据
data_juicer_config =
"""
# global parameters
project_name: 'data-process' 项目名称
dataset_path: './data/data-juicer/input/metadata.jsonl' # path to your dataset directory or file 数据集路径
np: 4 # number of subprocess to process your dataset 使用的子进程数量
text_keys: 'text'
image_key: 'image'
image_special_token: '<__dj__image>' 关键字配置
export_path: './data/data-juicer/output/result.jsonl' 结果导出路径
# process schedule
# a list of several process operators with their arguments
process:
- image_shape_filter: 图像尺寸过滤
min_width: 1024
min_height: 1024
any_or_all: any
- image_aspect_ratio_filter: 图像长宽比过滤
min_ratio: 0.5
max_ratio: 2.0
any_or_all: any
"""
with open("data/data-juicer/data_juicer_config.yaml", "w") as file:
file.write(data_juicer_config.strip()) #写入data_juicer_config.yaml文件
!dj-process --config data/data-juicer/data_juicer_config.yaml #进行数据处理
#保存处理好的数据
import pandas as pd
import os, json
from PIL import Image
from tqdm import tqdm #导入需要用到的库
texts, file_names = [], []
os.makedirs("./data/lora_dataset_processed/train", exist_ok=True) #创建保存处理后图像的目录
with open("./data/data-juicer/output/result.jsonl", "r") as file: #读取处理后的结果文件
for data_id, data in enumerate(tqdm(file.readlines())): #提取每条记录中的text和image路径,保存图像到指定目录,并记录图像文件名
data = json.loads(data)
text = data["text"]
texts.append(text)
image = Image.open(data["image"][0])
image_path = f"./data/lora_dataset_processed/train/{data_id}.jpg"
image.save(image_path)
file_names.append(f"{data_id}.jpg")
data_frame = pd.DataFrame() #创建一个pandas数据框,包含图像文件名和文本描述
data_frame["file_name"] = file_names
data_frame["text"] = texts
data_frame.to_csv("./data/lora_dataset_processed/train/metadata.csv", index=False, encoding="utf-8-sig") #将数据框保存为CSV文件
data_frame
4.训练模型
#下载模型
from diffsynth import download_models
download_models(["Kolors", "SDXL-vae-fp16-fix"]) #导入函数,调用模型
#查看训练脚本的输入参数
!python DiffSynth-Studio/examples/train/kolors/train_kolors_lora.py -h
#开始训练
import os
cmd =
"""
python DiffSynth-Studio/examples/train/kolors/train_kolors_lora.py \
--pretrained_unet_path models/kolors/Kolors/unet/diffusion_pytorch_model.safetensors \ 指定预训练的U-Net模型路径
--pretrained_text_encoder_path models/kolors/Kolors/text_encoder \指定预训练的文本编码器路径
--pretrained_fp16_vae_path models/sdxl-vae-fp16-fix/diffusion_pytorch_model.safetensors \ 指定预训练的VAE模型路径
--lora_rank 16 \
--lora_alpha 4.0 \ 配置lora模型的超参数
--dataset_path data/lora_dataset_processed \ 指定数据集路径
--output_path ./models \ 指定训练后的模型保存路径
--max_epochs 1 \ 指定训练的最大轮次
--center_crop \ 在图像预处理阶段应用中心裁剪
--use_gradient_checkpointing \ 启用梯度检查点以减少内存使用
--precision "16-mixed" 设置训练的精度为16-bit混合精度
""".strip() #定义了一个命令行字符串 cmd,用于启动训练脚本
os.system(cmd)
#加载模型
from diffsynth import ModelManager, SDXLImagePipeline
from peft import LoraConfig, inject_adapter_in_model
import torch #导入函数
def load_lora(model, lora_rank, lora_alpha, lora_path): #用于加载lora模型
lora_config = LoraConfig(
r=lora_rank,
lora_alpha=lora_alpha,
init_lora_weights="gaussian",
target_modules=["to_q", "to_k", "to_v", "to_out"],
) #配置lora参数
model = inject_adapter_in_model(lora_config, model) 将lora配置注入到原始模型中
state_dict = torch.load(lora_path, map_location="cpu")
model.load_state_dict(state_dict, strict=False)
return model
# Load models
model_manager = ModelManager(torch_dtype=torch.float16, device="cuda",
file_path_list=[
"models/kolors/Kolors/text_encoder",
"models/kolors/Kolors/unet/diffusion_pytorch_model.safetensors",
"models/kolors/Kolors/vae/diffusion_pytorch_model.safetensors"
]) #加载预训练模型
pipe = SDXLImagePipeline.from_model_manager(model_manager) #创建图像处理管道
# Load LoRA
pipe.unet = load_lora(
pipe.unet,
lora_rank=16, # This parameter should be consistent with that in your training script.
lora_alpha=2.0, # lora_alpha can control the weight of LoRA.
lora_path="models/lightning_logs/version_0/checkpoints/epoch=0-step=500.ckpt"
) #应用模型
5.生成图像
torch.manual_seed(0)
image = pipe(
prompt="二次元,一个紫色短发小女孩,在家中沙发上坐着,双手托着腮,很无聊,全身,粉色连衣裙",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("1.jpg")
torch.manual_seed(1)
image = pipe(
prompt="二次元,日系动漫,演唱会的观众席,人山人海,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙坐在演唱会的观众席,舞台上衣着华丽的歌星们在唱歌",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("2.jpg")
torch.manual_seed(2)
image = pipe(
prompt="二次元,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙坐在演唱会的观众席,露出憧憬的神情",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度,色情擦边",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("3.jpg")
torch.manual_seed(5)
image = pipe(
prompt="二次元,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙,对着流星许愿,闭着眼睛,十指交叉,侧面",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度,扭曲的手指,多余的手指",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("4.jpg")
torch.manual_seed(0)
image = pipe(
prompt="二次元,一个紫色中等长度头发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("5.jpg")
torch.manual_seed(1)
image = pipe(
prompt="二次元,一个紫色长发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌,手持话筒",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("6.jpg")
torch.manual_seed(7)
image = pipe(
prompt="二次元,紫色长发少女,穿着黑色连衣裙,试衣间,心情忐忑",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("7.jpg")
torch.manual_seed(0)
image = pipe(
prompt="二次元,紫色长发少女,穿着黑色礼服,连衣裙,在台上唱歌",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("8.jpg")
import numpy as np
from PIL import Image #导入处理图像和数组的库
images = [np.array(Image.open(f"{i}.jpg")) for i in range(1, 9)] #读取生成的图像文件,并将它们转换为 NumPy 数组
image = np.concatenate([
np.concatenate(images[0:2], axis=1),
np.concatenate(images[2:4], axis=1),
np.concatenate(images[4:6], axis=1),
np.concatenate(images[6:8], axis=1),
], axis=0) #拼接成一个大图像
image = Image.fromarray(image).resize((1024, 2048)) #将拼接后的图像数组转换回 PIL 图像对象,并调整图像大小
image
提示:
(1)在训练命令中填入 --modelscope_model_id xxxxx
以及 --modelscope_access_token xxxxx
后,训练程序会在结束时自动上传模型到 ModelScope
(2)部分参数可根据实际需求调整,例如 lora_rank
可以控制 LoRA 模型的参数量
(3)prompt为图像中包含的因素,negative_prompt为图像中不包含的内容。
6.图像展示
三、相关知识点补充
1.LoRA
Stable Diffusion中的Lora(LoRA)模型是一种轻量级的微调方法,它代表了“Low-Rank Adaptation”,即低秩适应。Lora不是指单一的具体模型,而是指一类通过特定微调技术应用于基础模型的扩展应用。在Stable Diffusion这一文本到图像合成模型的框架下,Lora被用来对预训练好的大模型进行针对性优化,以实现对特定主题、风格或任务的精细化控制。
LoRA(Low-Rank Adaptation)本质上是对特征矩阵进行低秩分解的一种近似数值分解技术,可以大幅降低特征矩阵的参数量,但是会伴随着一定的有损压缩。从传统深度学习时代走来的读者,可以发现其实LoRA本质上是基于Stable Diffusion的一种轻量化技术。
2.ComfyUI
ComfyUI 是一个工作流工具,主要用于简化和优化 AI 模型的配置和训练过程。通过直观的界面和集成的功能,用户可以轻松地进行模型微调、数据预处理、图像生成等任务,从而提高工作效率和生成效果。
3.参考图控制
ControlNet是一种用于精确控制图像生成过程的技术组件。它是一个附加到预训练的扩散模型(如Stable Diffusion模型)上的可训练神经网络模块。扩散模型通常用于从随机噪声逐渐生成图像的过程,而ControlNet的作用在于引入额外的控制信号,使得用户能够更具体地指导图像生成的各个方面(如姿势关键点、分割图、深度图、颜色等)。
参考图控制类型
简介
OpenPose姿势控制
输入是一张姿势图片(或者使用真人图片提取姿势)作为AI绘画的参考图,输入prompt后,之后AI就可以依据此生成一副相同姿势的图片;
Canny精准绘制
输入是一张线稿图作为AI绘画的参考图,输入prompt后,之后AI就可以根据此生成一幅根据线稿的精准绘制。
Hed绘制
Hed是一种可以获取渐变线条的线稿图控制方式,相比canny更加的灵活。
深度图Midas
输入是一张深度图,输入prompt后,之后AI就可以根据此生成一幅根据深度图的绘制。
颜色color控制
通过参考图控制和颜色控制,实现更加精准和个性化的图像生成效果。
4.提示词
写法:主体\(描述1, 描述2, 描述3\)
有些教程中提到大括号 { } 表示增加 1.01 权重,ComfyUI 文档中说明大括号的作用为动态提示,并非增加权重。
可以同时使用多个括号,用几个括号就代表几个基础权重值相乘:
(keyword): 1.1
((keyword)): 1.21
(((keyword))): 1.331
5.文本到图像Stable Diffusion
Stable Diffusion是一种潜在的扩散模型,可以从文本中生成AI图像。 它不是在高维图像空间中操作,而是首先将图像压缩到潜空间中。Stable Diffusion是一个文本到图像的生成模型。给它一个文本指令作为输入,它将返回给你一张与输入指令匹配的图像。
参考
1.Datawhale AI夏令营教程Datawhale
2.知乎文章https://zhuanlan.zhihu.com/p/639229126
3.知乎文章https://zhuanlan.zhihu.com/p/687923903
4.How does Stable Diffusion work?
总结
这篇文章主要介绍了通过Datawhale的教程使用一个基于Stable Diffusion的LoRA模型进行图像生成的过程,包括如何设置环境、处理数据、训练模型并生成图像的详细步骤。以下是总结的要点:### 一、跑通Baseline教程
参考了Datawhale的教程。
### 二、Baseline代码分析
#### 1. 安装库
- 安装了需要的库,包括`simple-aesthetics-predictor`, `data-juicer`, 以及其他与数据处理和机器学习相关的库。
- 特别注意移除不必要的包和安装特定版本的库,以确保环境稳定。
#### 2. 下载数据集
- 使用`modelscope`库下载并选择处理了“lowres_anime”数据集。
- 将图片和元数据保存到指定文件夹,其中图片转换为RGB模式,并创建了相应的JSONL格式的元数据文件。
#### 3. 使用`data-juicer`处理数据
- 通过自定义配置文件设置数据处理的参数,如图像的尺寸和长宽比过滤。
- 调用`data-juicer`的工具对数据进行预处理,并将处理后的数据保存到新目录和CSV文件中,以便于进一步使用。
#### 4. 训练模型
- 下载了预训练的Stable Diffusion相关模型。
- 通过命令行方式配置训练参数(如预训练权重、LoRA配置等)并启动训练过程。
- 介绍了如何加载训练好的模型,包括使用`LoraConfig`和`inject_adapter_in_model`将LoRA结构注入到基础模型中。
#### 5. 生成图像
- 使用训练好的模型通过一系列不同的`prompt`(用于描述图像内容的文本)和`negative_prompt`(不希望出现的元素)来生成图像。
- 展示了如何保存生成的图像并进行批处理,最后拼接成一个大的图像文件。
#### 6. 图像展示
- 虽然原文未提供具体的图像展示代码,但讨论了如何利用生成的图像构建最终的视觉输出。
### 三、相关知识点补充
#### 1. LoRA
- 介绍了LoRA是一种基于低秩适应的微调技术,用于减少预训练大模型的参数数量,同时保持其性能。
#### 2. ComfyUI
- 提到了ComfyUI作为一个工作流工具,能够简化AI模型的配置和训练过程。
#### 3. 参考图控制
- 介绍了ControlNet作为一种可以精确控制图像生成过程的附加模块,以及几种参考图控制方式(如OpenPose、Canny等)。
#### 4. 提示词
- 讲述了文本提示词的写法及其动态提示效果,即通过括号来增加权重。
#### 5. 文本到图像Stable Diffusion
- 概述了Stable Diffusion作为一种潜在的扩散模型,能够将文本描述转化为对应的图像。
### 参考链接
提供一些相关的教程和资料链接,便于读者进一步学习和验证。
这篇文章为想要使用Stable Diffusion或类似模型进行图像生成的研究者和开发者提供了一个清晰的入门路径和详细的实现步骤。