赞
踩
(赛题链接:可图Kolors-LoRA风格故事挑战赛_创新应用大赛_天池大赛)
(学习链接:从零入门AI生图原理&实践)
(阿里云链接:阿里云免费试用)
最后使用成功,关闭即可
(ps:据说在阿里云网站也可以找到运行的地方,可以不用去魔搭社区,魔搭社区可能会在使用高峰期流量过大而加载很慢,想要探索一下的小伙伴可以去找找阿里云的,启动速度会比魔搭要快的,但是整体的运行还是和魔搭社区同步的,以下附上简易版阿里云进入途径)
(魔搭链接:我的Notebook · 魔搭社区)
(ps:如果5000小时试用已经过期了可使用魔搭的免费Notebook实例,如下)
如果Notebook的试用也用完了,那就只能付费使用阿里云了,暂时没有别的解决方法
然后依次点击每一个模块的运行按钮(第一次的时候要这样,后面就可以直接点击>>按钮一键运行了)
提交的时候,这个基础模型三个都可选噢~
(作品发布链接:比赛品牌馆讨论区)
- !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
!
符号用于在Jupyter Notebook或IPython环境中执行系统命令。-v
标志表示安装时显示详细信息(verbose mode),-e
标志表示通过编辑模式(editable mode)安装。在编辑模式下安装的包将链接到当前的开发环境,使得对包的修改能够即时生效。pytorch-lightning
的Python包,并通过-y
标志自动确认卸载过程中的所有提示。peft
: 一个用于性能评估的工具。- #下载数据集
- 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:
- for data_id, data in enumerate(tqdm(ds)):
- image = data["image"].convert("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))
- f.write("\n")
MsDataset
类从指定的数据集加载数据。具体来说:
'AI-ModelScope/lowres_anime'
是数据集的名称或标识符。split='train'
表示加载训练集部分的数据。cache_dir="/mnt/workspace/kolors/data"
是数据集的缓存目录,数据集可能会在此处进行下载或存储。os.makedirs
函数创建目录:
./data/lora_dataset/train
:存储训练集图像的目录。./data/data-juicer/input
:存储数据预处理输入文件的目录。open("./data/data-juicer/input/metadata.jsonl", "w") as f
打开文件 metadata.jsonl
用于写入数据预处理后的元数据,jsonl
文件格式是每行一个 JSON 对象,适合存储和处理大型数据集的元数据。for data_id, data in enumerate(tqdm(ds)):
迭代数据集中的每个数据项:
data["image"].convert("RGB")
将图像数据转换为RGB格式。image.save(f"/mnt/workspace/kolors/data/lora_dataset/train/{data_id}.jpg")
将处理后的图像保存到 ./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 格式写入 metadata.jsonl
文件。- 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
-
-
- 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())):
- 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()
- 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")
- data_frame
data_juicer_config
是一个YAML格式的字符串,定义了数据处理的各种参数和操作流程。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
:过滤图像尺寸,保留宽度和高度均大于等于 1024
像素的图像。image_aspect_ratio_filter
:过滤图像宽高比,保留宽高比在 0.5
到 2.0
之间的图像。!dj-process
是一个命令行工具,用于执行数据处理任务。--config data/data-juicer/data_juicer_config.yaml
指定了配置文件的路径,告诉命令行工具按照配置文件中定义的流程处理数据。os.makedirs("./data/lora_dataset_processed/train", exist_ok=True)
创建存储处理后数据的目录 ./data/lora_dataset_processed/train
。
./data/data-juicer/output/result.jsonl
,逐行读取每条数据data_frame
。file_names
列和 texts
列添加到数据框中。to_csv
方法将数据框保存为 CSV 文件 ./data/lora_dataset_processed/train/metadata.csv
,编码为 utf-8-sig
,并且不包含行索引。- # 下载模型
- from diffsynth import download_models
- download_models(["Kolors", "SDXL-vae-fp16-fix"])
-
- #模型训练
- 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()
-
- os.system(cmd)
download_models(["Kolors", "SDXL-vae-fp16-fix"])
:这行代码调用了 diffsynth
库中的 download_models
函数,用于下载指定的模型。
"Kolors"
是要下载的第一个模型的标识符。"SDXL-vae-fp16-fix"
是要下载的第二个模型的标识符。模型训练说明
cmd
是一个包含要执行的命令的字符串变量,这个命令将在操作系统的 shell 中运行。--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 模型的秩为 16。--lora_alpha 4.0
:设置 Lora 模型的 alpha 参数为 4.0。--dataset_path data/lora_dataset_processed
:指定训练数据集的路径。--output_path ./models
:指定模型训练结果输出的路径。--max_epochs 1
:设置最大训练轮数为 1。--center_crop
:使用中心裁剪图像。--use_gradient_checkpointing
:使用梯度检查点技术。--precision "16-mixed"
:设置训练精度为混合精度 16 位。os.system(cmd)
:通过操作系统的 shell 执行存储在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_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
- 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"
- )
diffsynth
:包含了模型管理和图像处理流水线的相关功能。model
:要加载 LoRA 的模型。
lora_rank
:LoRA 的秩(rank)参数,影响适配器层的维度。
lora_alpha
:LoRA 的 alpha 参数,用于控制 LoRA 适配器的权重。
lora_path
:LoRA 模型的路径,即预训练模型的权重文件路径。
LoraConfig
:使用 peft
库中的 LoraConfig
类来配置 LoRA 的参数,包括秩、alpha 值、初始化权重方式和目标模块。
inject_adapter_in_model
:通过 peft
库中的 inject_adapter_in_model
函数将 LoRA 适配器注入到模型中。
torch.load(lora_path, map_location="cpu")
:加载预训练的 LoRA 模型的权重。
model.load_state_dict(state_dict, strict=False)
:将加载的权重应用到模型中,strict=False
表示允许部分加载。
ModelManager
:使用 diffsynth
中的 ModelManager
类来管理模型,指定了模型的数据类型为 torch.float16
,设备为 "cuda"
(GPU)。
file_path_list
:指定了需要加载的模型文件的路径列表,包括文本编码器、U-Net 和 VAE 模型。
SDXLImagePipeline.from_model_manager(model_manager)
:使用 ModelManager
创建 SDXLImagePipeline
,这是一个图像处理流水线,用于处理图像数据。
pipe.unet = load_lora(...)
:调用之前定义的 load_lora
函数,将加载的 LoRA 模型应用到 SDXLImagePipeline
的 U-Net 模型 (pipe.unet
) 上。
- 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)]
- 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))
- image
每个 torch.manual_seed(x)
设置了一个特定的随机种子,确保每次生成的图像是确定性的。这在生成对比图时很有用。
使用 pipe
对象生成图像:
pipe
是一个 SDXLImagePipeline
对象,用于处理图像生成任务。prompt
参数包含了描述图像内容的文本。negative_prompt
是描述不希望出现在图像中的内容。cfg_scale=4
是指定了图像生成的缩放因子。num_inference_steps=50
指定了生成图像的推断步数。height=1024, width=1024
指定了生成图像的高度和宽度。每次生成的图像都使用 image.save("X.jpg")
进行保存,其中 X
是保存的文件名,依次为 1.jpg
到 8.jpg
。
images
列表加载了之前保存的所有图像。np.concatenate
函数将图像按照 2x2 的网格连接起来,形成一个大图像。Image.fromarray(image)
将连接后的 numpy 数组转换为 PIL 图像对象。resize((1024, 2048))
将大图像调整为指定的大小。①AE/VAE模型
AE/VAE模型本质上展示了一种"捕捉高维数据的数据特征,并将其映射与压缩成低维表示"的形式,是当前主流生成式模型的基础。它提供了两个重要能力:将高维信息捕捉分解为多个特征,以及将这些特征压缩映射为低维向量。
在autoencoder模型中,我们加入一个编码器,它能帮我们把图片编码成向量。然后解码器能够把这些向量恢复成图片。
但我们想建一个产生式模型,而不是一个只是储存图片的网络。我们可以对编码器添加约束,就是强迫它产生服从单位高斯分布的潜在变量。正是这种约束,把VAE和标准自编码器给区分开来了。
现在,产生新的图片也变得容易:我们只要从单位高斯分布中进行采样,然后把它传给解码器就可以了,然后我们还需要在重构图片的精确度和单位高斯分布的拟合度上进行权衡。
我们可以让网络自己去决定这种权衡。对于我们的损失函数,我们可以把这两方面进行加和。一方面,是图片的重构误差,我们可以用平均平方误差来度量,另一方面。我们可以用KL散度来度量我们潜在变量的分布和单位高斯分布的差异。
为了优化KL散度,我们需要应用一个简单的参数重构技巧:不像标准自编码器那样产生实数值向量,VAE的编码器会产生两个向量:一个是均值向量,一个是标准差向量。
区分AE模型和VAE模型:
②GAN - 生成式对抗模型
GAN体现一种互相对抗、共同进化的思想,通过生成模型与判别模型的互相对抗,迫使双方的神经网络不断调整参数,最终使生成产物质量与训练集更加相似。
区分AE/VAE模型和GAN模型:
③Diffsion - 扩散模型
从单个图像样来看这个过程,扩散过程q就是不断往图像上加噪声直到图像变成一个纯噪声,下图为扩散过程,从 到最后的 就是一个马尔可夫链,表示状态空间中经过从一个状态到另一个状态的转换的随机过程。
逆扩散过程p就是从纯噪声生成一张图像的过程。
扩散模型包含两个步骤:
基础模型辨析
①CLIP跨模态模型
CLIP模型由一个图像编码器和一个文本编码器组成,它们共享参数。图像编码器负责将图像嵌入到语义空间中,而文本编码器则负责将文本嵌入到同样的语义空间中。CLIP模型使用了Transformer架构来实现这两个编码器,这种架构能够处理长距离的依赖关系,并且在大规模数据上进行预训练。
CLIP模型在多个任务上都表现出色,包括但不限于:
- 图像分类:给定一张图像,预测图像所属的类别。
- 图像检索:给定一段文本描述,检索出与描述相匹配的图像。
- 文本分类:给定一段文本,预测文本所属的类别。
- 文本生成:根据给定的文本描述,生成与描述相匹配的图像。
②U-NET卷积神经网络
U-NET是一种以“提取特征-还原特征”为核心的卷积神经网络。
U-NET将整个分割过程分为收缩路径和扩展路径,原理有点类似扩散模型,只不过训练的并非噪声,而是特征。
在收缩路径过程中,模型会不断的提取图片特征,并逐渐降低图像分辨率,使模型获得从低分辨率图片中提取特征的能力;在扩展路径的过程中,模型会不断在低分辨率的图像上采样提取特征,逐步还原为高分辨率的图片。
③ADD对抗性扩散蒸馏算法
ADD 通过三步过程结合了 GAN 和扩散模型的元素:
①Stable Diffusion - 潜在扩散模型
Stable Diffusion是一种用于生成模型的框架,主要应用于文本到图像合成等任务。这一框架结合了扩散过程(Diffusion)和稳定化技术(Stabilization),旨在提高生成模型在长期生成过程中的稳定性和生成质量。
首先,SD模型被分为三个空间,即像素空间、潜在空间、条件模块。像素空间的所有运算都是高维的,潜在空间的运算都是低维的。
右侧为条件模块。高维数据进入后会经过两道工序处理:1.由CLIP映射为嵌入向量,建立与图像的关联;2.由VA模型将其压缩为低维向量。接着,映射入潜在空间中。
中间为潜在空间。低维数据映射入潜在空间后,由U-NET对低维数据的特征进行提取运算,获得低维的特征向量。同时,它会产生一张随机噪声图,将特征加入噪声图后,在潜在空间中进行扩散运算过程。
最后,模型于潜在空间完成了扩散运算,并将运算结果高维还原为一张符合文本要求的图片输出。
②SDXL Turbo - 实时的文图模型
SDXL Turbo 在传统的稳定扩散模型(SD)的基础上,加入了对抗性蒸馏技术。这项技术通过引入和修改对抗训练,让模型向着更少的除噪步骤进化。
ADD技术主要改动的部位在于潜在空间中的扩散生成过程(Diffusion Process),加入GAN对抗训练加速这一过程。
③LCM - 潜在一致性模型
①LORA - 低秩自适应模型
LORA想要使模型输出全新的需求产物,它采用的方法是:低秩矩阵。
②ControlNet:外置的控制型神经网络
ControlNet则是看向了另一个目标:让模型的输出内容变得有序。
引用自:
参考链接:stable diffusion原理解读通俗易懂,史诗级万字爆肝长文!https://mp.weixin.qq.com/s?__biz=MzI1MjQ2OTQ3Ng==&mid=2247617834&idx=1&sn=2b8f0f56b8b5b25e5ba1240e5705a6a8&chksm=e9e004a1de978db79be4b5d01829959efb839852f818fabc14e5020c0f26b132e5f044c3bf8f&scene=27Stable Diffusion 万字长文详解稳定扩散模型https://zhuanlan.zhihu.com/p/669570827
LoRA引入了两个矩阵A和B,如果参数W的原始矩阵的大小为d × d,则矩阵A和B的大小分别为d × r和r × d,其中r要小得多(通常小于100)。参数r称为秩。如果使用秩为r=16的LoRA,则这些矩阵的形状为16 x d,这样就大大减少了需要训练的参数数量。LoRA的最大的优点是,与微调相比,训练的参数更少,但是却能获得与微调基本相当的性能。
LoRA的一个技术细节是:在开始时,矩阵A被初始化为均值为零的随机值,但在均值周围有一些方差。矩阵B初始化为完全零矩阵。这确保了LoRA矩阵从一开始就不会以随机的方式改变原始W的输出。一旦A和B的参数被调整到期望的方向,那么W的输出中A和B的更新应该是对原始输出的补充。
LoRA还有相关变体LoRA+、VeRA、LoRA- fa、LoRA-drop、AdaLoRA、DoRA、Delta-LoRA等
引用自:LoRA及其变体概述
hahaha都看到这里了,要是觉得有用的话就辛苦动动小手点个赞吧!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。