当前位置:AIGC资讯 > AIGC > 正文

Datawhale训练营AIGC方向 第二期

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生图模型的强大能力。

更新时间 2024-09-28