前言
Task 01 通过预训练模型的调用,在baseline上跑通模型,实现内容→图片。即,根据prompt中输入的文本描述,模型生成对应的图片。Task 02 深入学习。
目录
一、AI生图技术 1.1 基础点 1.2 技术难点 1.3 题外话(补充知识点:生成对抗网络) 二、代码精读 代码分块分析 三、实战演练一一基于话剧的连环画制作 话剧正文 四、浅尝scepter webui一、AI生图技术
1.1 基础点
AIGC(AI-Generated Content)是通过AI技术自动生成内容的生产方式。AI生图是最早被大众所知且广泛认可的AIGC领域。
简单的理解,AI生图,就是训练模型实现 图片描述 与 图片特征 的匹配。比如说,输入文本“狗狗”,然后给模型狗狗的照片。通过大量的样本训练,让模型知道文本“狗狗”对应的照片是什么样的,当下次输入“狗狗”后,能够生成对应的图片。
1.2 技术难点
相信大家也在网上见过一些AI生成令人涕笑的图片,图中存在不符常识的细节。如下图
这不由得令人深思,模型是否真正理解内容与特征之间的含义?以上图为例,模型是否真的理解“正常人类的手”到底具有什么特征(几根手指、指甲的样子…)。生成图内容的“逻辑性”是一较难克服的难点。
1.3 题外话(补充知识点:生成对抗网络)
不用于PS的P图,这里涉及到Deepfake技术,一种使用AI技术生成的伪造媒体,包括图片、视频、音频等。随着近几年AI生成技术的精近,生成的图片等也是愈发真实,令人迷惑,难以辨别。这不由得想起生成对抗网络(GANs),只不过现在屏幕前的人似乎就像模型中的“判别器”,面对生成的能够以假乱真的样本,难以给出准确的判断结果。论及GAN,再整理点小笔记。
GAN模型
GAN大概是2014年左右Goodfellow提出的模型,其核心思想为实现二人零和博弈。模型基础架构如下:
构成:
生成器(G)和 判别器(D) 。Z 为noise,随机噪声,一般可从正态分布或其他分布随机生成。X 为真实的样本数据,G(Z) 为 G 生成的样本。
思想:
生成器 G 学习 Z → G(Z) 的映射过程,学习并生成能够以假乱真的生成样本 G(Z) ;判别器 D 判断其输入是来自真实样本的 X 还是 G(Z)。
训练(如何实现):
先训练D。利用 G 生成样本数据 G(Z),将其标为0(告诉 D 这是假数据),并将真实数据X标为1(告诉 D 这是真数据),将上述数据输入 D 进行训练,通过损失函数、反向传播等对D进行权重更新。(一个简单的分类器) 再通过D训练G。D 训练完成后,固定参数,不进行权重更新。此时,同样 G生成样本数据 G(Z),但将其标为1!,输入 D 中,根据损失更新 G 的参数。(告诉 D 这是真数据,但是 D 已训练完成知道真数据和假数据的特征, D 能信吗?相应的 D 会给出自己的判断,也就是 G 权重优化的依据)如此,循环训练。两者能力不断增强,当 G 完成 Z → G(Z) ,生成的样本非常真实,真实到 D 难以分辨(问D,这是真的还是假的,D说可能是真的,可能是假的,真假概率都是0.5)。此时,达到理想的状态,纳什均衡点(理论上),生成的数据完美符合最初的要求。
二、代码精读
Task 01中的baseline代码精读与学习。随着大语言模型的广泛应用,对广大学习者来说是个福音。利用诸如chatgpt、文心一言进行代码解读已并非难事,Task 02中推荐的是通义千问。无论用什么工具,能对代码深入理解学习就行。
一个模型的代码,说白了就是利用某种编程语言,构建逻辑结构模块,利用计算机算力,实现某种目的。这个过程,需要什么?
数据集。对DL来说,主要作训练和测试用。将数据集划分为训练集和测试集,训练集数据用于训练模型,调整模型参数。训练完后,用未参与训练的测试集数据对模型进行测试,客观评估模型泛化能力。 模型算法。核心环节。对Python来说,目前构建模型算法可以直接调用一些成熟的DL框架,pytorch、tensorflow,国内百度的paddle。框架内有许多封装好的函数,一些常用的模块都可以直接调用,如LSTM、CNN,调用完组网就可以直接构建一些简单模型了。一些基础的ML模型甚至可以直接用,如SVR、XGBoost。如有需要可以直接在网上搜索,很多模型算法甚至直接有python包。 计算机算力。计算机强大的算力是其产生的原因。单纯靠人类计算,费时费力。CPU、GPU,个人电脑算力不足可以用云服务器。对于这个Task,厘清
目的是什么?实现图片生成,在prompt中输入关键词,模型生成对应的图片。 怎么实现?
数据?算法模型?算力?
提供数据。利用预训练模型和微调手段,Kolors和Lora。阿里云服务器。
代码分块分析
pip装一些必要的资源包。
!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
导包全写一起
import json, os
from data_juicer.utils.mm_utils import SpecialTokens
from tqdm import tqdm
import pandas as pd
from PIL import Image
import torch
from diffusers import StableDiffusionPipeline
(1)导入数据集,从modelscope的MsDataset里载入数据集lowres_anime,用于后面训练。
from modelscope.msdatasets import MsDataset
ds = MsDataset.load(
'AI-ModelScope/lowres_anime', # 载入指定数据集
subset_name='default',
split='train', # 数据集的模式,应该是分了train和test之类
cache_dir="/mnt/workspace/kolors/data" # 数据集的保存位置
)
数据预处理。下载完训练数据之后,需要对数据进行预处理,一般来说,包括数据清洗、筛选、处理异常值等。数据包中的数据一般都已经经过这些初步处理,要做的就是按照模型的需要处理数据。这里主要是对载入的数据包内容进行拆分,图片,描述性文本对应保存,设定data_juicer规则对数据进行筛选过滤。
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)): # ds即导入数据,对ds进行遍历处理,进行后面的操作
image = data["image"].convert("RGB") # 转换成RGB,即彩色图
image.save(f"/mnt/workspace/kolors/data/lora_dataset/train/{data_id}.jpg") # 以jpg形式保存图片,名为图片的索引
metadata = {"text": "二次元", "image": [f"/mnt/workspace/kolors/data/lora_dataset/train/{data_id}.jpg"]} # 生成图片对应的索引数据
f.write(json.dumps(metadata)) # 索引数据写入json文件
f.write("\n")
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
通过之前的json文件metadata,把数据集中的描述内容text(二次元)和文件名image(.jpg)对应起来,并创建了一个DataFrame形式保存,导出csv。
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
(2)下载模型Kolors
from diffsynth import download_models
download_models(["Kolors", "SDXL-vae-fp16-fix"])
执行Loras训练。
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)
# 定义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 模型
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函数,导入lora微调参数
pipe.unet = load_lora(
pipe.unet,
lora_rank=16,
lora_alpha=2.0,
lora_path="models/lightning_logs/version_0/checkpoints/epoch=0-step=500.ckpt"
)
(3)生成图像。prompt即 输入的文本特征,negative_prompt 是不希望图片有的特征。
torch.manual_seed(0)
image = pipe(
prompt="二次元,一个黑色长发少女,在家中沙发上斜躺着,看书,全身,白色连衣裙",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("1.jpg")
图片拼接。baseline里生成并保存了8张照片。拼接成2×4的形式。
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
三、实战演练一一基于话剧的连环画制作
做了一个小test
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的输入中,需要多加注意,尽量输入成模型能够理解的短词。
话剧正文
老套剧情
效果图如下
配上文字,如下
四、浅尝scepter webui
魔搭体验网址:Scepter万能图片编辑生成
进入网站后,可直接点击“推理”
模型管理中可选择模型。在输入框内输入“描述”,点击生成,即可生成图像。尝试输入“a cute rabbit”,得到了一只可爱的兔子:
当描述为中文,“一只可爱的兔子”,生成:
在生成下方,还有许多选项可供选择,使用咒语、微调、控制等,均可进行尝试,网页中也提供了视频进行学习。
稍微研究了一下这些内容。咒语书其实就是教大家如何进行prompt工程,对自己想要生成的图片进行恰当的描述,让模型能够理解你的input,使得生成的图片能够满足要求。
那么试试看,选择“可爱的3D角色”,利用提示的模版,加上"rabbit",会生成怎样的图片?
再试试微调模型,选择铅笔素描,获取示例提示词。
按照提示词,对原先的“a cute rabbit”进行修改,生图
有兴趣的可以试试。
总结
### 总结文章#### 一、AI生图技术基础
本文首先介绍了AIGC(AI-Generated Content)特别是AI生成图像技术的基础知识。AI生图通过大量样本训练模型,将文本描述与图片特征匹配,使模型能够根据输入文本生成对应的图片。然而,该技术仍面临挑战,如模型对内容的理解深度不足,可能导致生成的图片存在逻辑不合理的问题。
#### 二、技术难点与补充知识点:生成对抗网络(GANs)
文中进一步探讨了AI生图的技术难点,尤其强调了生成内容的“逻辑性”是一大难题。随后通过补充知识点“生成对抗网络(GANs)”给出了一种可能的解决思路。GANs模型基于深度学习和二人零和博弈的思想,包含生成器和判别器两个组件。通过不断迭代训练,两者能力提升,最终能生成难以分辨真伪的图片。
#### 三、代码精读与实现
本文详细介绍了如何在Task 01中通过预训练模型的调用跑通模型,并根据给定的文本prompt生成图片。过程中涉及到的数据集准备、数据预处理、模型下载、模型微调(Loras训练)、最后的图片生成及拼接等环节均通过代码块逐一解析。通俗易懂的代码讲解使读者能够快速上手实践。
#### 四、实战演练:基于话剧的连环画制作
通过一个小实验展示了基于模型生图的连环画制作过程。通过调整prompt及关键词输入,对生成的图片进行了多次尝试和改进,最终得到了理想的连环画效果。实验结果表明,尽管模型有时会出现理解偏差,但在仔细调整输入后,能够生成较为满意的图片。
#### 五、浅尝scepter webui
文章最后简要介绍了scepter webui这个在线图片编辑生成平台,展示了其操作简便、功能丰富的特点。通过具体分析scepter的模型管理、生成选项、咒语书和微调功能,进一步拓宽了读者对AI图像生成技术的了解和应用能力。
### 总结
本文主要围绕AI生成图片的技术展开,从基础知识、技术难点、代码实战到在线工具体验等方面进行了全面介绍。通过详细的代码讲解和实战演练,帮助读者深入了解该技术并实现应用。同时,通过补充GAN模型和在线工具的介绍,拓宽了读者的视野,增强了其技能储备和实践应用能力。