Datawhale AI夏令营第四期魔搭-AIGC文生图方向Task1笔记

简介: 这段内容介绍了一个使用LoRA技术定制Stable Diffusion模型的工作流程。首先定义了提示词的结构,接着概述了LoRA作为轻量级微调方法的角色。ComfyUI作为一个图形化工具,简化了AI模型的配置与操作。示例脚本展示了如何通过Data-Juicer和DiffSynth-Studio进行数据准备、模型训练,并最终生成特定风格的二次元图像。通过不同的种子和提示词,生成了一系列具有一致风格但内容各异的高质量二次元角色图像。

output.png
提示词
提示词很重要,一般写法:主体描述,细节描述,修饰词,艺术风格,艺术家

举个例子

【promts】Beautiful and cute girl, smiling, 16 years old, denim jacket, gradient background, soft colors, soft lighting, cinematic edge lighting, light and dark contrast, anime, super detail, 8k

【负向prompts】(lowres, low quality, worst quality:1.2), (text:1.2), deformed, black and white,disfigured, low contrast, cropped, missing fingers

Lora
Stable Diffusion中的Lora(LoRA)模型是一种轻量级的微调方法,它代表了“Low-Rank Adaptation”,即低秩适应。Lora不是指单一的具体模型,而是指一类通过特定微调技术应用于基础模型的扩展应用。在Stable Diffusion这一文本到图像合成模型的框架下,Lora被用来对预训练好的大模型进行针对性优化,以实现对特定主题、风格或任务的精细化控制。

ComfyUI
ComfyUI 是一个工作流工具,主要用于简化和优化 AI 模型的配置和训练过程。通过直观的界面和集成的功能,用户可以轻松地进行模型微调、数据预处理、图像生成等任务,从而提高工作效率和生成效果。

a4c3848b-68a8-4b38-b040-c79c91b90c95.png
在ComfyUI平台的前端页面上,用户可以基于节点/流程图的界面设计并执行AIGC文生图或者文生视频的pipeline。

参考图控制
ControlNet是一种用于精确控制图像生成过程的技术组件。它是一个附加到预训练的扩散模型(如Stable Diffusion模型)上的可训练神经网络模块。扩散模型通常用于从随机噪声逐渐生成图像的过程,而ControlNet的作用在于引入额外的控制信号,使得用户能够更具体地指导图像生成的各个方面(如姿势关键点、分割图、深度图、颜色等)。

LoRA 样例脚本
第一步:安装
安装 Data-Juicer 和 DiffSynth-Studio

!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

请在这里手动重启 Notebook kernel
第二步:下载数据集

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")

第三步:数据处理
使用 data-juicer 处理数据

[4]
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

保存处理好的数据

[5]
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

第四步:训练模型
下载模型

[6]
from diffsynth import download_models

download_models(["Kolors", "SDXL-vae-fp16-fix"])

查看训练脚本的输入参数

[7]
!python DiffSynth-Studio/examples/train/kolors/train_kolors_lora.py -h

开始训练

提示:

在训练命令中填入 --modelscope_model_id xxxxx 以及 --modelscope_access_token xxxxx 后,训练程序会在结束时自动上传模型到 ModelScope
部分参数可根据实际需求调整,例如 lora_rank 可以控制 LoRA 模型的参数量

[8]
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)

加载模型

[9]
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"
)

生成图像

[19]
torch.manual_seed(0)
image = pipe(
prompt="二次元,一个紫色短发小女孩,在床上甜美的睡着了,全身,粉色连衣裙,梦到了美丽的风景",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("1.jpg")
100%|██████████| 50/50 [00:17<00:00, 2.79it/s]

[20]
torch.manual_seed(1)
image = pipe(
prompt="二次元,日系动漫,博物馆的门口,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙在去博物馆的门口",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("2.jpg")
100%|██████████| 50/50 [00:18<00:00, 2.75it/s]

[21]
torch.manual_seed(2)
image = pipe(
prompt="二次元,日系动漫,博物馆的室内,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙站着,看墙上的画,露出憧憬的神情",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度,色情擦边",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("3.jpg")
100%|██████████| 50/50 [00:18<00:00, 2.75it/s]

[22]
torch.manual_seed(5)
image = pipe(
prompt="二次元,一个紫色短发小女孩穿着粉色吊带漏肩连衣裙,对着流星许愿,闭着眼睛,十指交叉,侧面",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度,扭曲的手指,多余的手指",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("4.jpg")
100%|██████████| 50/50 [00:18<00:00, 2.73it/s]

[23]
torch.manual_seed(0)
image = pipe(
prompt="二次元,一个紫色中等长度头发小女孩穿着粉色吊带漏肩连衣裙,在画室练习画画",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("5.jpg")
100%|██████████| 50/50 [00:18<00:00, 2.72it/s]

[29]
torch.manual_seed(1)
image = pipe(
prompt="二次元,紫色长发少女,穿着粉色吊带漏肩连衣裙看着墙上,墙上有幅风景画",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("6.jpg")
100%|██████████| 50/50 [00:17<00:00, 2.78it/s]

[30]
torch.manual_seed(7)
image = pipe(
prompt="二次元,紫色长发少女很高兴,在人山人海的人群看画",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("7.jpg")
100%|██████████| 50/50 [00:18<00:00, 2.75it/s]

[25]
torch.manual_seed(0)
image = pipe(
prompt="二次元,紫色长发少女,穿着黑色礼服,手里拿着一个奖杯,背后是她画好的画",
negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
cfg_scale=4,
num_inference_steps=50, height=1024, width=1024,
)
image.save("8.jpg")
100%|██████████| 50/50 [00:18<00:00, 2.75it/s]

[31]
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

相关文章
|
2月前
|
人工智能 API 开发者
用Qwen3+MCPs实现AI自动发布小红书笔记!支持图文和视频
魔搭自动发布小红书MCP,是魔搭开发者小伙伴实现的小红书笔记自动发布器,可以通过这个MCP自动完成小红书标题、内容和图片的发布。
994 41
|
2月前
|
Web App开发 人工智能 JSON
Windows版来啦!Qwen3+MCPs,用AI自动发布小红书图文/视频笔记!
上一篇用 Qwen3+MCPs实现AI自动发小红书的最佳实践 有超多小伙伴关注,同时也排队在蹲Windows版本的教程。
441 1
|
4月前
|
人工智能 自然语言处理 搜索推荐
创作者会被AI取代吗?AIGC为电影行业带来新变革
在AI技术飞速发展的今天,AIGC(AI生成内容)正深刻改变电影行业的内容生成、制作流程与商业模式。创作者角色从执行者向策划者转变,需与AI协作挖掘创意与情感价值。生成式人工智能认证(GAI认证)成为新时代创作者必备资质,助力其在人机共生的新生态中保持竞争力,共同推动创作领域迈向更高层次。拥抱变革,共创未来,是每个创作者在AI时代的必由之路。
创作者会被AI取代吗?AIGC为电影行业带来新变革
|
3月前
|
人工智能 自然语言处理 搜索推荐
JeecgBoot AI 应用开发平台,AIGC 功能介绍
JeecgBoot推出AIGC功能模块,包含AI应用开发平台与知识库问答系统,支持AI流程编排、模型管理、知识库训练及向量库对接。基于LLM大语言模型,提供智能对话、RAG检索增强生成等功能,兼容多种大模型(如DeepSeek、Qwen等)。平台结合低代码与AIGC,适用于复杂业务场景,支持快速原型到生产部署,助力用户打造个性化智能体,如“诗词达人”或“翻译助手”,并可嵌入第三方系统提升交互能力。项目开源,欢迎体验与交流。
134 0
JeecgBoot AI 应用开发平台,AIGC 功能介绍
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
技术创新领域,AI(AIGC)是否会让TRIZ“下岗”?
法思诺创新直播间探讨了AI(AIGC)是否将取代TRIZ的问题。专家赵敏认为,AI与TRIZ在技术创新领域具有互补性,结合两者更务实。TRIZ提供结构化分析框架,AI加速数据处理和方案生成。DeepSeek、Gemini等AI也指出,二者各有优劣,应在复杂创新中协同使用。企业应建立双轨知识库,重构人机混合创新流程,实现全面升级。结论显示,AI与TRIZ互补远超竞争,结合二者是未来技术创新的关键。
119 0
|
6月前
|
人工智能 物联网
AI电影从这个LoRA开始:魔搭AIGC1月赛题公布&12月赛题获奖作品新鲜出炉
魔搭社区LoRA创意挑战赛月度赛第三期来啦! 1月赛题揭晓:电影风格模型训练大赛
154 15
|
7月前
|
人工智能 自然语言处理 搜索推荐
Open Notebook:开源 AI 笔记工具,支持多种文件格式,自动转播客和生成总结,集成搜索引擎等功能
Open Notebook 是一款开源的 AI 笔记工具,支持多格式笔记管理,并能自动将笔记转换为博客或播客,适用于学术研究、教育、企业知识管理等多个场景。
454 0
Open Notebook:开源 AI 笔记工具,支持多种文件格式,自动转播客和生成总结,集成搜索引擎等功能
|
6月前
|
人工智能 编解码 安全
全球AI新浪潮:智能媒体服务的技术创新与AIGC加速出海
本文介绍了智能媒体服务的国际化产品技术创新及AIGC驱动的内容出海技术实践。首先,探讨了媒体服务在视频应用中的升级引擎作用,分析了国际市场的差异与挑战,并提出模块化产品方案以满足不同需求。其次,重点介绍了AIGC技术如何推动媒体服务2.0智能化进化,涵盖多模态内容理解、智能生产制作、音视频处理等方面。最后,发布了阿里云智能媒体服务的国际产品矩阵,包括媒体打包、转码、实时处理和传输服务,支持多种广告规格和效果追踪分析,助力全球企业进行视频化创新。
193 0
|
机器学习/深度学习 自然语言处理
文生图模型-Stable Diffusion | AIGC
所谓的生成式模型就是通过文本或者随机采样的方式来得到一张图或者一段话的模型,比如文生图,顾名思义通过文本描述来生成图像的过程。当前流行的文生图模型,如DALE-2, midjourney以及今天要介绍的Stable Diffusion,这3种都是基于Diffusion扩散模型【1月更文挑战第6天】
1267 0

热门文章

最新文章