Datawhale训练营AIGC方向 第二期
AI生图模型
概念AI生图模型属于多模态机器学习模型,通过海量的图库和文本描述的深度神经网络学习,最终的目标是可以根据输入的指示(不管是文本还是图片还是任何)生成符合语义的图片。
通俗来说,AI生图模型获得图片生成能力主要是通过 学习 图片描述 以及 图片特征,尝试将这两者进行一一对应,存储在自己的记忆里。
现有模型Kolors(可图)模型(点击即可跳转魔搭模型介绍页) 是快手开源的文本到图像生成模型,该模型具有对英语和汉语的深刻理解,并能够生成高质量、逼真的图像。
代码开源链接:https://github.com/Kwai-Kolors/Kolors
模型开源链接:https://modelscope.cn/models/Kwai-Kolors/Kolors
技术报告链接:https://github.com/Kwai-Kolors/Kolors/blob/master/imgs/Kolors_paper.pdf
魔搭研习社最佳实践说明:https://www.modelscope.cn/learn/575?pid=543
魔搭社区还开源了专门的各种风格的可图优质咒语书(点击即可跳转)
Baseline代码精读
代码框架结构图
让我们交给AI,让AI分析baseline的代码框架
代码任务:
安装和卸载依赖包 使用!pip
命令来安装或卸载 Python 包。包括:
simple-aesthetics-predictor
, data-juicer
, peft
, lightning
, pandas
, torchvision
, 和 DiffSynth-Studio
的安装。
卸载 pytorch-lightning
(使用 -y
自动确认卸载)。
数据集加载与预处理
使用 ModelScope 加载了一个名为 lowres_anime
的数据集。
将数据集中每条记录中的图像转换为 RGB 格式并保存至磁盘。
构建了一个 用于数据清理的JSONL 文件,该文件包含了每张图像的路径及其对应的文本描述。
数据过滤与处理
使用 Data-Juicer 库对数据集进行过滤,包括图像尺寸和长宽比的过滤。
过滤后的数据被保存在一个新的 JSONL 文件中。
数据整理与特征提取
读取 result.jsonl
文件中的数据,并将其转换为 Pandas DataFrame,然后保存为 CSV 文件,并且将图片保存到./data/lora_dataset_processed/train文件夹下。
读取过滤后的 JSONL 文件,并从中提取图像路径和对应的文本描述。
使用 CLIP 模型对图像和文本进行特征提取,并计算图像-文本相似度分数。
将整理后的数据保存为 CSV 文件。
PyTorch 数据集与数据加载器
创建了一个 PyTorch 的自定义数据集类 CustomDataset
,用于加载图像和文本数据。
使用 DataLoader 对数据集进行批处理。
文本到图像生成
使用 StableDiffusionPipeline
生成基于提示(prompt)的图像。
通过调整不同的提示和参数,生成多幅图像。
接下来,我会根据这些主要任务将代码分为几个部分,并解释每个部分的作用。
代码主体框架分析
1. 数据集加载与预处理
这部分代码负责从 ModelScope 加载数据集,并将图像转换为 RGB 格式后保存到指定目录。同时,构建了一个 JSONL 文件,其中包含了每张图像的路径及其对应的文本描述。
# 导入所需的库
from modelscope.msdatasets import MsDataset # 从ModelScope导入MsDataset类,用于加载数据集
import json, os # 导入json模块用于处理JSON数据,os模块用于操作系统相关的功能
from data_juicer.utils.mm_utils import SpecialTokens # 从data-juicer库导入SpecialTokens类,这里未直接使用
from tqdm import tqdm # 导入tqdm库用于显示进度条
# 加载数据集
ds = MsDataset.load( # 使用MsDataset类加载数据集
'AI-ModelScope/lowres_anime', # 数据集的名字
subset_name='default', # 数据集的子集名称
split='train', # 数据集的分割,这里是训练集
cache_dir="/mnt/workspace/kolors/data" # 缓存数据集的位置
)
# 保存图像并构建 JSONL 文件
os.makedirs("./data/lora_dataset/train", exist_ok=True) # 创建存放图像的目录,如果已经存在则不创建
os.makedirs("./data/data-juicer/input", exist_ok=True) # 创建存放JSONL文件的目录,如果已经存在则不创建
with open("./data/data-juicer/input/metadata.jsonl", "w") as f: # 打开或创建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") # 写入换行符以便下一个数据条目
2. 数据过滤与处理
这部分代码使用 Data-Juicer 库对数据集进行了过滤,包括图像尺寸和长宽比的过滤,并将过滤后的数据保存到一个新的 JSONL 文件中。
# 定义数据处理配置
data_juicer_config = """
# 全局参数
project_name: 'data-process' # 项目名
dataset_path: './data/data-juicer/input/metadata.jsonl' # 数据集目录或文件路径
np: 4 # 处理数据集的子进程数量
text_keys: 'text' # 文本键
image_key: 'image' # 图像键
image_special_token: '<__dj__image>' # 图像特殊标记
export_path: './data/data-juicer/output/result.jsonl' # 输出结果路径
# 处理流程
# 包含多个处理操作符及其参数列表
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 # # 符合前面条件的图片才会被保留
"""
# 保存data-juicer配置到data/data-juicer/data_juicer_config.yaml
with open("data/data-juicer/data_juicer_config.yaml", "w") as file:
file.write(data_juicer_config.strip())
# data-juicer开始执行数据筛选
!dj-process --config data/data-juicer/data_juicer_config.yaml
3. 数据整理与特征提取
这部分代码读取过滤后的 JSONL 文件,并从中提取图像路径和对应的文本描述。使用 CLIP 模型对图像和文本进行特征提取,并计算图像-文本相似度分数。最后,将整理后的数据保存为 CSV 文件。
import pandas as pd # 导入pandas库,用于数据处理
import os, json # 导入os和json库,用于文件操作和JSON处理
from PIL import Image # 导入PIL库中的Image模块,用于图像处理
from tqdm import tqdm # 导入tqdm库,用于显示进度条
# 读取过滤后的 JSONL 文件并整理数据
texts, file_names = [], [] # 初始化空列表用于存储文本和文件名
os.makedirs("./data/data-juicer/output/images", exist_ok=True) # 创建存放图像的目录,如果已经存在则不创建
with open("./data/data-juicer/output/result.jsonl", "r") as f: # 打开JSONL文件用于读取
for line in tqdm(f): # 遍历文件中的每一行,并显示进度条
metadata = json.loads(line) # 解析每一行的JSON数据
texts.append(metadata["text"]) # 将文本添加到texts列表
file_names.append(metadata["image"][0]) # 将图像路径添加到file_names列表
# 创建 DataFrame 并保存为 CSV 文件
df = pd.DataFrame({"text": texts, "file_name": file_names}) # 创建DataFrame
df.to_csv("./data/data-juicer/output/result.csv", index=False) # 将DataFrame保存为CSV文件
# 特征提取
from transformers import CLIPProcessor, CLIPModel # 导入CLIPProcessor和CLIPModel类
import torch # 导入torch库
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32") # 加载预训练的CLIP模型
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32") # 加载预训练的CLIP处理器
images = [Image.open(img_path) for img_path in df["file_name"]] # 从DataFrame中读取图像路径,并打开图像
inputs = processor(text=df["text"].tolist(), images=images, return_tensors="pt", padding=True) # 使用CLIP处理器处理文本和图像数据
outputs = model(**inputs) # 使用CLIP模型进行特征提取
logits_per_image = outputs.logits_per_image # 获取图像-文本相似度分数
probs = logits_per_image.softmax(dim=1) # 计算概率分布
4. PyTorch 数据集与数据加载器 lora模型微调
这部分代码创建了一个 PyTorch 的自定义数据集类 CustomDataset
,用于加载图像和文本数据,并使用 DataLoader 对数据集进行批处理。
# 执行可图Lora训练
import os
cmd = """
python DiffSynth-Studio/examples/train/kolors/train_kolors_lora.py \ # 选择使用可图的Lora训练脚本DiffSynth-Studio/examples/train/kolors/train_kolors_lora.py
--pretrained_unet_path models/kolors/Kolors/unet/diffusion_pytorch_model.safetensors \ # 选择unet模型
--pretrained_text_encoder_path models/kolors/Kolors/text_encoder \ # 选择text_encoder
--pretrained_fp16_vae_path models/sdxl-vae-fp16-fix/diffusion_pytorch_model.safetensors \ # 选择vae模型
--lora_rank 16 \ # lora_rank 16 表示在权衡模型表达能力和训练效率时,选择了使用 16 作为秩,适合在不显著降低模型性能的前提下,通过 LoRA 减少计算和内存的需求
--lora_alpha 4.0 \ # 设置 LoRA 的 alpha 值,影响调整的强度
--dataset_path data/lora_dataset_processed \ # 指定数据集路径,用于训练模型
--output_path ./models \ # 指定输出路径,用于保存模型
--max_epochs 1 \ # 设置最大训练轮数为 1
--center_crop \ # 启用中心裁剪,这通常用于图像预处理
--use_gradient_checkpointing \ # 启用梯度检查点技术,以节省内存
--precision "16-mixed" # 指定训练时的精度为混合 16 位精度(half precision),这可以加速训练并减少显存使用
""".strip()
os.system(cmd) # 执行可图Lora训练
# 加载lora微调后的模型
from diffsynth import ModelManager, SDXLImagePipeline # 导入ModelManager和SDXLImagePipeline
from peft import LoraConfig, inject_adapter_in_model # 导入LoraConfig和inject_adapter_in_model
import torch # 导入torch
# 加载LoRA配置并注入模型
def load_lora(model, lora_rank, lora_alpha, lora_path):
lora_config = LoraConfig(
r=lora_rank, # 设置LoRA的秩(rank)
lora_alpha=lora_alpha, # 设置LoRA的alpha值,控制LoRA的影响权重
init_lora_weights="gaussian", # 初始化LoRA权重为高斯分布
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") # 加载LoRA微调后的权重
model.load_state_dict(state_dict, strict=False) # 将权重加载到模型中,允许部分权重不匹配
return model # 返回注入LoRA后的模型
# 加载预训练模型
model_manager = ModelManager(
torch_dtype=torch.float16, # 设置模型的数据类型为float16,减少显存占用
device="cuda", # 指定使用GPU进行计算
file_path_list=[
"models/kolors/Kolors/text_encoder", # 文本编码器的路径
"models/kolors/Kolors/unet/diffusion_pytorch_model.safetensors", # UNet模型的路径
"models/kolors/Kolors/vae/diffusion_pytorch_model.safetensors" # VAE模型的路径
]
)
# 初始化图像生成管道
pipe = SDXLImagePipeline.from_model_manager(model_manager) # 从模型管理器中加载模型并初始化管道
# 加载并应用LoRA权重到UNet模型
pipe.unet = load_lora(
pipe.unet,
lora_rank=16, # 设置LoRA的秩(rank),与训练脚本中的参数保持一致
lora_alpha=2.0, # 设置LoRA的alpha值,控制LoRA对模型的影响权重
lora_path="models/lightning_logs/version_0/checkpoints/epoch=0-step=500.ckpt" # 指定LoRA权重的文件路径
)
5. 文本到图像生成
这部分代码使用 StableDiffusionPipeline
生成基于提示(prompt)的图像。通过调整不同的提示和参数,生成多幅图像。
from diffusers import StableDiffusionPipeline
import torch
# 加载模型
torch.manual_seed(1)
pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v-1-4", torch_dtype=torch.float16)
pipe = pipe.to("cuda")
# 生成图像
torch.manual_seed(0) # 设置随机种子,确保生成的图像具有可重复性。如果想要每次生成不同的图像,可以将种子值改为随机值。
image = pipe(
prompt="二次元,一个紫色短发小女孩,在家中沙发上坐着,双手托着腮,很无聊,全身,粉色连衣裙", # 设置正向提示词,用于指导模型生成图像的内容
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度", # 设置负向提示词,模型会避免生成包含这些特征的图像
cfg_scale=4, # 设置分类自由度 (Classifier-Free Guidance) 的比例,数值越高,模型越严格地遵循提示词
num_inference_steps=50, # 设置推理步数,步数越多,生成的图像细节越丰富,但生成时间也更长
height=1024, width=1024, # 设置生成图像的高度和宽度,这里生成 1024x1024 像素的图像
)
image.save("1.jpg") # 将生成的图像保存为 "1.jpg" 文件
# 保存图像
image.save("example_image.png")
# 更多图像生成
# ...
以上就是整个代码的主体框架分析。
三、基于话剧的连环画制作
先确定适合的prompt
场景1: 女主正在上课
风格: 西幻风,3D立体 人物描述: 一位穿着学院制服的黑发少女 场景描述: 中世纪风格的教室,木制长桌和椅子 动作: 坐在桌前,专注地看着书本 提示词:西幻风, 3D立体, 黑发少女, 学院制服, 中世纪风格教室, 木制长桌和椅子, 坐在桌前, 专注看书, 上半身
场景2: 开始睡着了
风格: 西幻风,3D立体 人物描述: 同上 场景描述: 同上 动作: 头伏在书本上,轻柔地打着盹 提示词:西幻风, 3D立体, 黑发少女, 学院制服, 中世纪风格教室, 木制长桌和椅子, 头伏在书本上, 打着盹, 上半身
场景3: 进入梦乡,梦到自己站在路旁
风格: 西幻风,3D立体 人物描述: 同上 场景描述: 幻境中的森林小径旁,周围是古老的树木 动作: 站立在路旁,望着前方的迷雾 提示词:西幻风, 3D立体, 黑发少女, 学院制服, 幻境中的森林小径, 古老树木环绕, 站立在路旁, 望着前方迷雾, 全身
场景4: 王子骑马而来
风格: 西幻风,3D立体 人物描述: 一位身穿铠甲的英俊王子 场景描述: 同上 动作: 骑着一匹白马,缓缓驶过森林小径 提示词:西幻风, 3D立体, 英俊王子, 穿着铠甲, 幻境中的森林小径, 古老树木环绕, 骑着白马缓缓驶过, 全身
场景5: 两人相谈甚欢
风格: 西幻风,3D立体 人物描述: 黑发少女和王子 场景描述: 幻境中的森林小径旁,有一块平坦的草地 动作: 坐在草地上,面对面交谈 提示词:西幻风, 3D立体, 黑发少女, 学院制服, 英俊王子, 穿着铠甲, 幻境中的森林小径旁, 平坦草地, 坐在草地上, 面对面交谈, 上半身
场景6: 一起坐在马背上
风格: 西幻风,3D立体 人物描述: 同上 场景描述: 幻境中的森林小径 动作: 两人并肩坐在马背上,王子握着缰绳 提示词:西幻风, 3D立体, 黑发少女, 学院制服, 英俊王子, 穿着铠甲, 幻境中的森林小径, 两人并肩坐在马背上, 王子握着缰绳, 全身
场景7: 下课了,梦醒了
风格: 西幻风,3D立体 人物描述: 同场景1 场景描述: 中世纪风格的教室 动作: 惊醒,看着空荡荡的教室 提示词:西幻风, 3D立体, 黑发少女, 学院制服, 中世纪风格教室, 惊醒, 看着空荡荡的教室, 上半身
场景8: 又回到了学习生活中
风格: 西幻风,3D立体 人物描述: 同上 场景描述: 中世纪风格的教室,书桌上堆满了书籍 动作: 坐在桌前,手执羽毛笔,埋头写作 提示词:西幻风, 3D立体, 黑发少女, 学院制服, 中世纪风格教室, 书桌上堆满书籍, 坐在桌前, 手执羽毛笔, 埋头写作, 上半身
然后我们再跑通一遍baseline
最后生成的图如下:
总效果图概览
``还是很有意思的~
总结
### Datawhale训练营AIGC方向 第二期:AI生图模型总结#### AI生图模型概念
AI生图模型作为多模态机器学习模型,通过深度学习技术,利用图库和文本描述生成符合语义的图片。其核心在于通过大量图片及其描述进行学习,将图片特征和描述一一对应,从而实现根据指令(文本、图片等)生成图片的能力。
#### 现有模型:Kolors
- **来源**:快手开源的文本到图像生成模型
- **特点**:支持中英双语,能生成高质量、逼真的图像
- **资源链接**:
- 代码开源:https://github.com/Kwai-Kolors/Kolors
- 模型开源:https://modelscope.cn/models/Kwai-Kolors/Kolors
- 技术报告:https://github.com/Kwai-Kolors/Kolors/blob/master/imgs/Kolors_paper.pdf
- 最佳实践:https://www.modelscope.cn/learn/575?pid=543
#### Baseline代码精读
##### 主体任务
1. **安装和卸载依赖包**:使用`!pip`命令安装或卸载必要的Python包(如`simple-aesthetics-predictor`, `data-juicer`, `lightning`等)。
2. **数据集加载与预处理**:
- 使用ModelScope加载`lowres_anime`数据集,并将其转换为RGB格式保存。
- 创建一个JSONL文件,包含每张图像的路径及其文本描述。
3. **数据过滤与处理**:
- 使用Data-Juicer库对图像尺寸和长宽比进行过滤,并将过滤后的数据保存在新的JSONL文件中。
4. **数据整理与特征提取**:
- 从过滤后的数据中提取文本描述和图像文件路径。
- 使用CLIP模型对图像和文本进行特征提取,并计算相似度分数。
- 将处理后的数据存储为CSV格式文件。
5. **PyTorch 数据集与数据加载器(lora模型微调)**:
- 创建自定义PyTorch数据集类`CustomDataset`,使用DataLoader进行批处理。
- 解释如何利用可图(Kolors)的Lora模块进行微调训练。
6. **文本到图像生成**:
- 使用`StableDiffusionPipeline`基于输入的提示生成图像。
- 调整提示词和参数生成不同的图像。
#### 基于话剧的连环画制作
通过详细设计不同场景的提示词,每个场景围绕一位黑发少女在中世纪风格教室和幻境森林中的学习、梦境及与王子的互动展开。各场景通过详细的提示词来引导AI生成符合场景描述的图片,如“西幻风, 3D立体, 黑发少女...”。
#### 实践结果
经过上述步骤的实现,最终生成了一系列有趣且具备一定连贯性的场景图片,这些图片在各个细节上较好地满足了给定的提示词要求,展示了AI生图模型的强大能力。