Datawhale X 魔搭夏令营第四期魔搭 AIGC文生图 baseline
安装并运行
前面就是启动虚拟机,绑定账号等,因此省略…
启动实例后,打开终端,输入命令下载文件:
git lfs install
git clone https://www.modelscope.cn/datasets/maochase/kolors.git
下载完成后进入kolors文件夹,打开baseline文件
开始运行Baseline
-
安装所需包:
!pip install simple-aesthetics-predictor !pip install -v -e data-juicer !pip uninstall pytorch-lightning -y !pip install peft lightning pandas torchvision !pip install -e DiffSynth-Studio
这些命令通常在Python开发环境中的命令行界面中执行,用于管理项目所需的依赖包。如果你正在编写Python脚本或使用Jupyter Notebook,并且需要安装或管理包,你可以使用这些命令。注意,
!
符号通常在Jupyter Notebook中使用,表示执行该命令。在标准的命令行界面中,你只需要写pip
而不是!pip
,后边如果出现XXX module
没有时候,就是下载了这些模型,但是没重启,所以加载不到 -
下载数据集
from modelscope.msdatasets import MsDataset ds = MsDataset.load( 'AI-ModelScope/lowres_anime', subset_name='default', split='train', cache_dir="/mnt/workspace/kolors/data" )
这段代码的目的是加载名为
AI-ModelScope/lowres_anime
的数据集的训练部分,并将其存储在指定的缓存目录中,其中调用modelscope
库中的MsDataset
类来加载特定的数据集。之后开始保存数据集import json, os # json用于处理JSON数据,os用于操作系统功能,如文件路径操作 from data_juicer.utils.mm_utils import SpecialTokens from tqdm import tqdm # tqdm,用于显示进度条 # 使用os.makedirs创建两个目录,如果目录已存在,则exist_ok=True参数确保不会抛出错误 os.makedirs("./data/lora_dataset/train", exist_ok=True) os.makedirs("./data/data-juicer/input", exist_ok=True) # 使用with open语句打开或创建metadata.jsonl文件,准备写入元数据 with open("./data/data-juicer/input/metadata.jsonl", "w") as f: # 使用for循环遍历数据集ds,其中data_id是数据项的索引,data是数据项本身 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.dumps将元数据字典转换为JSON格式的字符串,写入到metadata.jsonl文件中 f.write("\n") # 在每条记录后添加换行符
-
数据预处理
使用 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()) # 执行数据处理命令 !dj-process --config data/data-juicer/data_juicer_config.yaml
配置参数解释:
project_name
:项目名称,这里设置为'data-process'
dataset_path
:数据集的路径,这里是相对路径'./data/data-juicer/input/metadata.jsonl'
。np
:处理数据集时使用的子进程数量,这里设置为4text_keys
和image_key
:分别指定了元数据中文本和图像的键名image_special_token
:一个特殊标记,用于在处理过程中标记图像export_path
:处理后数据的导出路径
处理流程解释:
- process:定义了一个处理流程列表,包含两个处理操作:
image_shape_filter
:过滤图像尺寸,只保留宽度和高度至少为1024像素的图像。any_or_all: any
表示满足任一条件即可image_aspect_ratio_filter
:过滤图像的宽高比,只保留宽高比在0.5到2.0之间的图像
执行数据处理命令:
- 使用
!dj-process --config data/data-juicer/data_juicer_config.yaml
命令来执行data-juicer
的数据处理流程。这个命令假设你已经安装了data-juicer
,并且它可以通过命令行工具dj-process
来运行
保存处理好的数据
import pandas as pd # 用于数据处理和CSV文件操作 import os, json # 文件路径操作和JSON数据解析 from PIL import Image # 用于图像处理 from tqdm import tqdm # 进度条"tqdm()" texts, file_names = [], [] # 初始化两个列表:文本数据, 图像文件名 os.makedirs("./data/lora_dataset_processed/train", exist_ok=True) # 使用open函数以读取模式打开./data/data-juicer/output/result.jsonl文件 with open("./data/data-juicer/output/result.jsonl", "r") as file: # 遍历文件中的每一行,使用json.loads将JSON字符串解析为Python字典 for data_id, data in enumerate(tqdm(file.readlines())): 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") # 创建Pandas DataFrame data_frame = pd.DataFrame() # 初始化一个空的DataFrame data_frame["file_name"] = file_names data_frame["text"] = texts # 使用to_csv方法将data_frame导出,使用utf-8-sig编码以确保特殊字符的正确保存 data_frame.to_csv("./data/lora_dataset_processed/train/metadata.csv", index=False, encoding="utf-8-sig") data_frame
-
训练模型
下载模型,并且检查训练脚本的参数
from diffsynth import download_models download_models(["Kolors", "SDXL-vae-fp16-fix"]) # 主模型,VAE模型 !python DiffSynth-Studio/examples/train/kolors/train_kolors_lora.py -h
开始LoRA训练:
import os cmd = """ python DiffSynth-Studio/examples/train/kolors/train_kolors_lora.py \ --pretrained_unet_path models/kolors/Kolors/unet/diffusion_pytorch_model.safetensors \ --pretrained_text_encoder_path models/kolors/Kolors/text_encoder \ --pretrained_fp16_vae_path models/sdxl-vae-fp16-fix/diffusion_pytorch_model.safetensors \ --lora_rank 16 \ --lora_alpha 4.0 \ --dataset_path data/lora_dataset_processed \ --output_path ./models \ --max_epochs 1 \ --center_crop \ --use_gradient_checkpointing \ --precision "16-mixed" """.strip() # cmd.strip():移除字符串首尾的空白字符,确保命令格式正确 os.system(cmd) # os.system(),执行定义的命令
-
开始生成
加载已训练模型:
from diffsynth import ModelManager, SDXLImagePipeline from peft import LoraConfig, inject_adapter_in_model import torch # 定义load_lora函数 def load_lora(model, lora_rank, lora_alpha, lora_path): lora_config = LoraConfig( r=lora_rank, lora_alpha=lora_alpha, init_lora_weights="gaussian", target_modules=["to_q", "to_k", "to_v", "to_out"], ) model = inject_adapter_in_model(lora_config, model) state_dict = torch.load(lora_path, map_location="cpu") model.load_state_dict(state_dict, strict=False) return model # Load models # 创建ModelManager实例,指定数据类型为torch.float16,设备为"cuda",并提供模型文件的路径列表 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" ]) # 使用SDXLImagePipeline.from_model_manager方法创建一个图像处理管线,该管线使用ModelManager加载的模型 pipe = SDXLImagePipeline.from_model_manager(model_manager) # Load LoRA # 使用load_lora函数加载LoRA适配器到U-Net模型上,指定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" )
生成图像
torch.manual_seed(0) image = pipe( prompt="二次元,一个紫色短发小女孩,在家中沙发上坐着,双手托着腮,很无聊,全身,粉色连衣裙", negative_prompt="丑陋、变形、嘈杂、模糊、低对比度", cfg_scale=4, num_inference_steps=50, height=1024, width=1024, ) image.save("1.jpg") #保存为
prompt: 正向提示词,即为想要绘制出的内容 negative_prompt: 逆向提示词,你需要画面中不要出现的内容