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 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_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/data-juicer/output/images", exist_ok=True) with open("./data/data-juicer/output/result.jsonl", "r") as f: for line in tqdm(f): metadata = json.loads(line) texts.append(metadata["text"]) file_names.append(metadata["image"][0]) df = pd.DataFrame({"text": texts, "file_name": file_names}) df.to_csv("./data/data-juicer/output/result.csv", index=False) df from transformers import CLIPProcessor, CLIPModel import torch model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32") processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32") images = [Image.open(img_path) for img_path in df["file_name"]] inputs = processor(text=df["text"].tolist(), images=images, return_tensors="pt", padding=True) outputs = model(**inputs) logits_per_image = outputs.logits_per_image # this is the image-text similarity score probs = logits_per_image.softmax(dim=1) # we can take the softmax to get the probabilities probs from torch.utils.data import Dataset, DataLoader class CustomDataset(Dataset): def __init__(self, df, processor): self.texts = df["text"].tolist() self.images = [Image.open(img_path) for img_path in df["file_name"]] self.processor = processor def __len__(self): return len(self.texts) def __getitem__(self, idx): inputs = self.processor(text=self.texts[idx], images=self.images[idx], return_tensors="pt", padding=True) return inputs dataset = CustomDataset(df, processor) dataloader = DataLoader(dataset, batch_size=8) for batch in dataloader: outputs = model(**batch) logits_per_image = outputs.logits_per_image probs = logits_per_image.softmax(dim=1) print(probs) import torch from diffusers import StableDiffusionPipeline torch.manual_seed(1) pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v-1-4", torch_dtype=torch.float16) pipe = pipe.to("cuda") prompt = "二次元,一个紫色长发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌,手持话筒" negative_prompt = "丑陋、变形、嘈杂、模糊、低对比度" guidance_scale = 4 num_inference_steps = 50 image = pipe( prompt=prompt, negative_prompt=negative_prompt, guidance_scale=guidance_scale, num_inference_steps=num_inference_steps, height=1024, width=1024, ).images[0] image.save("example_image.png") image from PIL import Image torch.manual_seed(1) 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
主体框架工作流
环境准备和依赖安装: 使用pip命令安装所需的Python库,包括simple-aesthetics-predictor
、data-juicer
、pytorch-lightning
、peft
、lightning
、pandas
、torchvision
和DiffSynth-Studio
。 数据集加载: 从modelscope.msdatasets
加载名为AI-ModelScope/lowres_anime
的数据集,并指定子集和分割类型。 数据预处理: 创建保存图片和元数据的目录。 遍历数据集,将图片保存为JPEG格式,并生成包含文本和图片路径的元数据文件。 配置数据处理: 定义data_juicer的配置文件,包括项目名称、数据集路径、进程数、文本和图片键、特殊标记以及导出路径。 写入配置文件并使用dj-process
命令行工具处理数据。 数据处理结果分析: 读取处理后的数据,提取文本和文件名,并将它们保存到CSV文件中。 模型加载和推理: 加载CLIP模型和处理器,对图片和文本进行编码,获取图像-文本相似度得分。 自定义数据集和数据加载器: 定义自定义数据集类CustomDataset
,用于封装处理后的图片和文本数据。 创建数据加载器DataLoader
,用于批量加载数据。 模型训练/推理循环: 遍历数据加载器中的批次,进行模型推理,获取每个批次的图像-文本相似度得分。 生成图像: 使用Stable Diffusion模型根据给定的提示生成图像,并保存到文件。 图像拼接: 将生成的多张图像拼接成一张长图,并调整大小。 逐行代码解释
安装所需的Python包!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
simple-aesthetics-predictor
:安装一个简单的美学预测器。 data-juicer
:安装数据处理工具包,使用可编辑模式安装(-e
)。 卸载已有的pytorch-lightning
版本。 安装peft
(参数高效微调)、lightning
(新的PyTorch Lightning库)、pandas
(数据处理)和torchvision
(计算机视觉工具包)。 安装DiffSynth-Studio
,DiffSynth-Studio是一个开源的扩散引擎,专为实现图片和视频的风格转换而设计。 加载数据集 from modelscope.msdatasets import MsDataset ds = MsDataset.load( 'AI-ModelScope/lowres_anime', subset_name='default', split='train', cache_dir="/mnt/workspace/kolors/data" )
从modelscope.msdatasets
导入MsDataset
类。 使用MsDataset.load
方法加载名为'AI-ModelScope/lowres_anime'
的数据集,指定使用默认子集('default'
),数据划分为训练集('train'
),并将数据缓存到指定目录。 准备数据处理 import json, os from data_juicer.utils.mm_utils import SpecialTokens from tqdm import tqdm
导入必要的库:json
(处理JSON数据)、os
(文件系统操作)、tqdm
(进度条显示)。 从data_juicer
的工具模块中导入SpecialTokens
(用于处理特殊标记)。 创建必要的目录 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")
打开一个名为metadata.jsonl
的文件,用于写入每个图像的元数据。 遍历数据集中的每一条数据: 将图像转换为RGB格式。 将图像保存到指定目录,文件名为数据的索引。 创建元数据字典,包含文本描述"二次元"
和图像路径。 将元数据以JSON格式写入文件,每条记录占一行。 配置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())
定义data_juicer
的配置,内容包括: 全局参数,如项目名称、数据集路径、并行处理的子进程数量等。 指定文本和图像的键,以及特殊的图像标记。 输出路径。 处理流程,包括图像尺寸过滤(最小宽度和高度为1024)和图像长宽比过滤(比例在0.5到2.0之间)。 将配置写入data_juicer_config.yaml
文件。 运行data_juicer
处理数据 !dj-process --config data/data-juicer/data_juicer_config.yaml
使用data_juicer
的命令行工具,根据配置文件处理数据集。 读取处理后的数据并创建DataFrame import pandas as pd import os, json from PIL import Image from tqdm import tqdm texts, file_names = [], [] os.makedirs("./data/data-juicer/output/images", exist_ok=True) with open("./data/data-juicer/output/result.jsonl", "r") as f: for line in tqdm(f): metadata = json.loads(line) texts.append(metadata["text"]) file_names.append(metadata["image"][0]) df = pd.DataFrame({"text": texts, "file_name": file_names}) df.to_csv("./data/data-juicer/output/result.csv", index=False) df
导入必要的库:pandas
(数据处理)、os
、json
、PIL.Image
(图像处理)和tqdm
。 创建用于存储图像的输出目录。 打开处理后的结果文件result.jsonl
,逐行读取: 解析每行的JSON数据,提取文本和图像路径,分别存储到列表中。 使用pandas
创建一个包含文本和图像文件名的DataFrame。 将DataFrame保存为CSV文件。 显示DataFrame的内容。 使用CLIP模型计算图像和文本的相似度 from transformers import CLIPProcessor, CLIPModel import torch model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32") processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32") images = [Image.open(img_path) for img_path in df["file_name"]] inputs = processor(text=df["text"].tolist(), images=images, return_tensors="pt", padding=True) outputs = model(**inputs) logits_per_image = outputs.logits_per_image # this is the image-text similarity score probs = logits_per_image.softmax(dim=1) # we can take the softmax to get the probabilities probs
从transformers
库中导入CLIPProcessor
和CLIPModel
,以及torch
。 加载预训练的CLIP模型和处理器。 打开DataFrame中所有的图像文件。 使用处理器将文本和图像进行预处理,返回PyTorch张量,并进行适当的填充。 将预处理后的数据输入模型,获得输出。 提取每个图像与文本的相似度分数(logits_per_image
)。 对相似度分数应用softmax,得到概率分布。 显示计算得到的概率。 定义自定义数据集和数据加载器 from torch.utils.data import Dataset, DataLoader class CustomDataset(Dataset): def __init__(self, df, processor): self.texts = df["text"].tolist() self.images = [Image.open(img_path) for img_path in df["file_name"]] self.processor = processor def __len__(self): return len(self.texts) def __getitem__(self, idx): inputs = self.processor(text=self.texts[idx], images=self.images[idx], return_tensors="pt", padding=True) return inputs dataset = CustomDataset(df, processor) dataloader = DataLoader(dataset, batch_size=8) for batch in dataloader: outputs = model(**batch) logits_per_image = outputs.logits_per_image probs = logits_per_image.softmax(dim=1) print(probs)
从torch.utils.data
中导入Dataset
和DataLoader
。 定义CustomDataset
类: 在初始化时,存储文本列表、打开的图像列表和处理器。 实现__len__
方法,返回数据集的大小。 实现__getitem__
方法,对指定索引的数据进行处理,并返回处理后的输入。 创建数据集和数据加载器,设置批次大小为8。 遍历数据加载器中的每个批次: 将批次数据输入模型,计算相似度分数和概率,并打印结果。 使用Stable Diffusion生成图像 import torch from diffusers import StableDiffusionPipeline torch.manual_seed(1) pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v-1-4", torch_dtype=torch.float16) pipe = pipe.to("cuda") prompt = "二次元,一个紫色长发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌,手持话筒" negative_prompt = "丑陋、变形、嘈杂、模糊、低对比度" guidance_scale = 4 num_inference_steps = 50 image = pipe( prompt=prompt, negative_prompt=negative_prompt, guidance_scale=guidance_scale, num_inference_steps=num_inference_steps, height=1024, width=1024, ).images[0] image.save("example_image.png") image
导入torch
和StableDiffusionPipeline
。 设置随机种子为1,确保生成的图像可重复。 加载预训练的Stable Diffusion模型,并将其移动到GPU上,设置为半精度浮点数以节省显存。 定义正向和负向提示词,以及指导尺度和推理步数。 使用提示词生成图像,指定图像的高度和宽度为1024像素。 保存生成的图像为example_image.png
,并显示图像。 生成更多图像并保存 from PIL import Image torch.manual_seed(1) 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")
使用不同的随机种子和提示词,生成多张图像,并分别保存为1.jpg
至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
导入numpy
和PIL.Image
。 打开之前生成的8张图像,将其转换为numpy数组。 将图像按照行和列拼接,形成一个大的图像网格: 每行拼接两张图像,共四行。 将拼接后的图像调整大小为1024x2048像素。 显示最终的拼接图像。 利用AI生成剧本(以kimi为例)
提示词1:你是一个古风漫画家,我们现在要做一个古风仙侠漫,现在要写一个故事简介
提示词2:根据故事简介,写一个故事大纲
提示词3:展开第四章:修仙大会,并把漫画具体的场景描绘出来
提示词4:
你是一个文生图专家,我们现在要做一个实战项目,就是要根据刚才展开的修仙大会内容编排一个文生图, 由8张场景图片生成,你需要输出每张图片的生图提示词 生图提示词要求 1、风格为古风 2、根据场景确定是使用全身还是上半身 3、人物描述 4、场景描述 5、做啥事情 例子: 古风,水墨画,一个黑色长发少女,坐在教室里,盯着黑板,深思,上半身,红色长裙 修仙大会的提示词(AI生成)
AI生成的提示词微调后整理如下:
编号 场景 正向提示词 负向提示词 结果 1 大会前夕 古风,水墨画,市集繁华,一个笑容甜美的少女(笑笑),背影转头,穿梭在人群中,好奇地打量着各种摊位,全身,身着简单朴素的布衣。 丑陋,变形,嘈杂,模糊,低对比度 2 报名处的混乱 古风,水墨画,报名处人潮汹涌,一个表情轻松的少女(笑笑)站在人群中,用幽默化解紧张气氛,上半身,身着带有些许修仙特色的服饰。 丑陋,变形,嘈杂,模糊,低对比度 3 大会开幕式 古风,水墨画,宏伟的主会场,一个少女(笑笑)和其他修仙者一起,仰头观看开幕式,全身,身着节日盛装。 丑陋,变形,嘈杂,模糊,低对比度 4 比武大会 古风,水墨画,比武台上,一个少女(笑笑)正在进行灵力控制比赛,全身,身着便于活动的修仙服饰,脸上带着自信的微笑。 丑陋,变形,嘈杂,模糊,低对比度 5 夜晚的庆祝 古风,水墨画,夜市灯火通明,一个少女(笑笑)和她的队友们围坐一桌,品尝美食,享受烟火表演,上半身,身着轻便的夜行衣。 丑陋,变形,嘈杂,模糊,低对比度 6 意外的挑战 古风,水墨画,夜市角落,一个少女(笑笑)面对神秘人物,准备接受挑战,全身,身着带有一些神秘符号的服饰,表情认真。 丑陋,变形,嘈杂,模糊,低对比度 7 智慧的较量 古风,水墨画,僻静角落,一个少女(笑笑)和神秘人物进行灵力与智慧的较量,上半身,身着代表智慧的服饰,手中拿着棋子或类似道具。 丑陋,变形,嘈杂,模糊,低对比度 8 大会的落幕 古风,水墨画,主会场,一个少女(笑笑)和她的队友们站在领奖台上,接受“最具潜力新人奖”,全身,身着带有荣誉象征的服饰,脸上洋溢着喜悦和自豪。 丑陋,变形,嘈杂,模糊,低对比度总结
promptjson二次元clipclitpu数据集提示词gitdiffusion演唱会pandas元数据kolguicsvcto数据处理pytorchstablediffusion