Datawhale X 魔搭 AI夏令营魔搭- AIGC文生图方向 task02笔记

目录

Step1: 尝试理解baseline代码

1.代码结构

2. baseline解析

(1)安装python 包

(2)数据集加载

(3)数据集预处理

其一,tqdm库

基本使用:

进度条定制:

其二,data-juicer系统

其三,图像格式转换以及筛选

(4)使用CLIP模型编码数据集

(5)可图Lora训练

(6)加载lora微调之后的模型

Step2 :进行提示词创作并文生图

1.提示词以及生成图

2.一点思考

step3: Scepter 和 Web UI 工具箱的使用


Task2的主要任务为精读代码,实战进阶。

因为笔者已经对大模型的使用比较熟练,因此直接开干!

Step1: 尝试理解baseline代码

1.代码结构

这里附上完整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

2. baseline解析

(1)安装python 包

simple-aesthetics-predictor用于美学预测

data-juicer用于数据处理

peft用于参数高效微调

lightning(pytorch-lightning)用于简化PyTorch模型训练

pandas用于数据分析

torchvision用于图像处理

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

(2)数据集加载

from modelscope.msdatasets import MsDataset

#加载数据集 
ds = MsDataset.load(
    'AI-ModelScope/lowres_anime',  #这个字符串指定了要加载的数据集的名称,我们要加载的是名为lowres_anime的数据集,它位于ModelScope平台的AI-ModelScope组织下
    subset_name='default',    #子集的名称 ,一般来讲都是有train,test ,但是我们这里设置成了default,那么表示我们加载默认的子集,一般是指全部数据
    split='train',  #指定了数据集的特定分割部分
    cache_dir="/mnt/workspace/kolors/data"  #指定缓存目录
)

总之,大致的加载数据集的思路就是,找到相关目录下的数据集文件,选择加载哪个子集,加载子集中的什么部分(train or test ??),加载好的数据集文件下载在哪

(3)数据集预处理

import json, os
from data_juicer.utils.mm_utils import SpecialTokens
from tqdm import tqdm
  • json 用于处理JSON格式的数据。
  • os 用于操作系统相关功能,如文件和目录操作。
  • SpecialTokens 用于处理特殊标记。
  • tqdm 是一个进度条库,用于显示循环的进度。

这里扩展一些笔者不曾用到过的库,做些补充:

其一,tqdm库

tqdm是阿拉伯语"taqaddum"的缩写,意为“进步”,同时在西班牙语中,是“te quiero demasiado”的缩写,意为,“I love you so much"

tqdm是一个快速、可扩展的Python进度条,可以在Python长循环中添加一个进度提示信息,用户只需要封装任意的迭代器tqdm(iterator)。它可以帮助我们监测程序运行的进度,估计运行的时长,甚至可以协助debug。对于在长时间运行的任务中显示进度很有用,因为它可以让用户知道任务正在进行。

有点意思,因此笔者决定亲自使用,一探究竟,这是tqdm库的Github地址,有需要的小伙伴可以进行学习:https://github.com/tqdm/tqdm 

基本使用:

在本地使用了这个库,效果如下:

可变情况下:

手动情况下:

使用with进行手动控制

with tqdm(total=100) as pbar:
    for i in range(10):
        sleep(0.1)
        pbar.update(10)

如果提供了可选变量total(或具有len()的可迭代对象),则显示预测统计信息。

不使用with:

With也只是一个可选项,如果不想使用with,可以把tqdm()赋值给一个变量,但在这种情况下,不要忘记在末尾del或close()

pbar = tqdm(total=100)
for i in range(10):
    sleep(0.1)
    pbar.update(10)
pbar.close()
进度条定制:

1. 设置描述信息

可以通过desc参数为进度条添加描述信息。

2.自定义进度条长度

使用ncols参数可以自定义进度条的长度。

3. 改变进度条样式

bar_format 使用不同的字符来改变进度条的样式。

pbar = tqdm(total=100,desc="Processing")  
for i in range(10):
    sleep(0.1)
    pbar.update(10)
pbar.close()
其二,data-juicer系统

这是对应的github地址,有感兴趣的小伙伴可以进行学习

https://github.com/modelscope/data-juicericon-default.png?t=N7T8https://github.com/modelscope/data-juicerData-Juicer 是一个一站式多模态数据处理系统,旨在为大语言模型 (LLM) 提供更高质量、更丰富、更易“消化”的数据。

魔搭开源Data-Juicer流程示意图

2024年2月15日,OpenAI正式对外发布了Sora。

2024年3月23日的全球开发者先锋大会上,阿里云的魔搭社区宣布了一个新计划:“ModelScope-Sora开源计划”。

 在Data-Juicer的主页上逛了逛,心情激荡,尽管外国发展人工智能的速度很快,技术很领先,但是我们从来不会去放弃追赶,尤其是对于像阿里这样的国内顶尖企业,承担了很大的社会责任。

为了便于开发者学习,魔搭提供了可以在浏览器使用data-Juicer的notebook, 有感兴趣的小伙伴可以关注data-Juice进行学习。

在数据集的预准备阶段:

我们需要把图片信息转为Jsonl 文件,看来是需要使用Jsonl类型的图像数据,才方便进一步处理的。


其三,图像格式转换以及筛选

1. 创建两个目录

os.makedirs("./data/lora_dataset/train", exist_ok=True)#用于存储处理过的图像。
os.makedirs("./data/data-juicer/input", exist_ok=True)#用于存放输入给Data-Juicer的数据文件

 2. 遍历数据集ds中的每一项,并使用进度条展现进程情况,把图像转换成RGB格式数据,然后建立一个字典,里面格式为:

“text”:"二次元",“image”: RGB图像地址

3. 然后写入metadata.jsonl文件

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'  # 你前面生成的数据的索引文件
np: 4  # 线程数

text_keys: 'text' # 文件./data/data-juicer/input/metadata.jsonl的描述的字段名
image_key: 'image' # 文件./data/data-juicer/input/metadata.jsonl的图片字段名
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 # 最小宽度1024
        min_height: 1024 # 最小高度1024
        any_or_all: any # 符合前面条件的图片才会被保留
    - image_aspect_ratio_filter: # 图片长宽比过滤
        min_ratio: 0.5 # 最小长宽比0.5
        max_ratio: 2.0 # 最大长宽比2.0
        any_or_all: any # 符合前面条件的图片才会被保留
"""

# 保存data-juicer配置到data/data-juicer/data_juicer_config.yaml
with open("data/data-juicer/data_juicer_config.yaml", "w") as file:
    file.write(data_juicer_config.strip())

这部分代码定义了一个Data-Juicer的配置文件,并将其写入到data_juicer_config.yaml中:

  • project_name 指定了项目名称。
  • dataset_path 指定了输入数据集的路径,即前面创建的metadata.jsonl文件的路径。
  • np 设置了处理数据集时使用的子进程数量。
  • text_keysimage_key 分别指定了文本和图像数据在输入数据中的键名。
  • image_special_token 是一个特殊的标记,用于表示图像位置。
  • export_path 指定了处理后输出数据的路径。
  • process 列出了对数据集进行过滤的具体规则,包括:
    • image_shape_filter 用于过滤宽度和高度都不小于1024像素的图像。
    • image_aspect_ratio_filter 用于过滤宽高比在0.5到2.0之间的图像。

补充:

enumerate() : 对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值,因此我们在这 获取 data_id  和 data ,如果原始数据中没有设置索引,则会自己从0 ,1, 2 开始

(4)使用CLIP模型编码数据集

1.提取出图像数据和描述信息

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)
  • 打开result.jsonl文件进行读取。
  • 使用tqdm库显示读取文件的进度条。
  • 对于文件中的每一行,将其解析为JSON格式,并从中提取出文本描述和图像文件路径。
  • 将提取出来的文本描述和图像文件路径分别添加到textsfile_names列表中。
  • 将提取到的文本描述和图像文件路径转化为DataFrame,并将其保存为CSV文件

2. 使用CLIP模型来计算处理后的图像数据与对应文本描述之间的相似度,并将处理过程的结果保存为CSV文件。

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  # 从输出中提取logits_per_image,这是图像和文本之间的相似度分数
probs = logits_per_image.softmax(dim=1)  #得到每个图像对于其对应文本描述的概率

补充:

CLIP模型(由Open AI 提出)训练思路

CLIP预训练图像编码器和文本编码器,以预测数据集中哪些图像与哪些文本配对。然后,使用这种行为将CLIP转换为zero-shot分类器。将数据集的所有类转换为文本,例如“一张狗的照片”,并预测CLIP估计的标题类与给定图像的最佳配对。

(5)可图Lora训练

可图使用了基于U-Net架构的隐空间扩散模型,并创新性地引入了大语言模型进行文本表征

github地址:GitHub - Kwai-Kolors/Kolors: Kolors Team

在最近的智源FlagEval文生图模型评测榜单中,可图(Kolors)凭借其卓越表现,主观综合评分全球第二,仅次于闭源的DALL-E 3。尤其在主观图像质量上,可图(Kolors)表现突出,显著优于其他开源和闭源模型,评分排名第一。——引自快手技术CSDN博客

# 执行可图Lora训练
import os
cmd = """
python DiffSynth-Studio/examples/train/kolors/train_kolors_lora.py \ # 选择使用可图的Lora训练脚本DiffSynth-Studio/examples/train/kolors/train_kolors_lora.py
  --pretrained_unet_path models/kolors/Kolors/unet/diffusion_pytorch_model.safetensors \ # 选择unet模型
  --pretrained_text_encoder_path models/kolors/Kolors/text_encoder \ # 选择text_encoder
  --pretrained_fp16_vae_path models/sdxl-vae-fp16-fix/diffusion_pytorch_model.safetensors \ # 选择vae模型
  --lora_rank 16 \ # lora_rank 16 表示在权衡模型表达能力和训练效率时,选择了使用 16 作为秩,适合在不显著降低模型性能的前提下,通过 LoRA 减少计算和内存的需求
  --lora_alpha 4.0 \ # 设置 LoRA 的 alpha 值,影响调整的强度
  --dataset_path data/lora_dataset_processed \ # 指定数据集路径,用于训练模型
  --output_path ./models \ # 指定输出路径,用于保存模型
  --max_epochs 1 \ # 设置最大训练轮数为 1
  --center_crop \ # 启用中心裁剪,这通常用于图像预处理
  --use_gradient_checkpointing \ # 启用梯度检查点技术,以节省内存
  --precision "16-mixed" # 指定训练时的精度为混合 16 位精度(half precision),这可以加速训练并减少显存使用
""".strip()
os.system(cmd) # 执行可图Lora训练

梯度检查点技术是啥?

梯度检查点技术(Gradient Checkpointing)是一种在深度学习模型训练过程中节省内存的方法。在训练深度神经网络时,特别是在使用反向传播算法进行梯度计算时,需要存储大量的中间激活值(即前向传播过程中的输出)。这些激活值在反向传播阶段用来计算梯度,这对于更新网络权重至关重要。然而,随着网络层数的增加,这些中间激活值可能会占用大量的显存空间,导致显存不足的问题。

梯度检查点技术通过在训练过程中有选择性地丢弃一些中间激活值,并在需要时重新计算它们,从而减少内存使用。这种方法的核心思想是,在前向传播阶段不保存所有层的激活值,而是在反向传播时重新计算那些被丢弃的激活值。

具体来说,梯度检查点技术的工作流程如下:

  1. 选择检查点:在模型中选择某些层或模块作为检查点,这些检查点之间的激活值不会被保存。
  2. 前向传播:正常进行前向传播,但在到达检查点时,只保存检查点处的激活值。
  3. 反向传播:在反向传播时,当遇到一个检查点时,如果需要某个已经被丢弃的激活值,则重新从前向传播开始执行到该检查点,从而计算出所需的激活值。
  4. 梯度计算:一旦得到所需的激活值,就可以计算梯度,并继续反向传播过程。

这种方法的优势在于,它可以在一定程度上减少内存需求,因为不是所有的中间激活值都需要存储。但是,重新计算激活值会增加计算时间,因此这是一种时间和空间的权衡。

在您的代码中,--use_gradient_checkpointing 参数指示训练脚本在训练过程中启用梯度检查点技术,这意味着在训练过程中将会有选择性地丢弃某些中间激活值,并在需要时重新计算它们,以此来节省内存资源。这对于处理大规模模型尤其有用,因为在GPU内存有限的情况下,这种技术可以使得训练更大的模型成为可能。

 (6)加载lora微调之后的模型

# 加载lora微调后的模型
from diffsynth import ModelManager, SDXLImagePipeline # 导入ModelManager和SDXLImagePipeline
from peft import LoraConfig, inject_adapter_in_model # 导入LoraConfig和inject_adapter_in_model
import torch # 导入torch
# 加载LoRA配置并注入模型
def load_lora(model, lora_rank, lora_alpha, lora_path):
    lora_config = LoraConfig(
        r=lora_rank, # 设置LoRA的秩(rank)
        lora_alpha=lora_alpha, # 设置LoRA的alpha值,控制LoRA的影响权重
        init_lora_weights="gaussian", # 初始化LoRA权重为高斯分布
        target_modules=["to_q", "to_k", "to_v", "to_out"], # 指定要应用LoRA的模块
    )
    model = inject_adapter_in_model(lora_config, model) # 将LoRA配置注入到模型中
    state_dict = torch.load(lora_path, map_location="cpu") # 加载LoRA微调后的权重
    model.load_state_dict(state_dict, strict=False) # 将权重加载到模型中,允许部分权重不匹配
    return model # 返回注入LoRA后的模型

#-----------------------------------------------------------------------------
# 加载预训练模型
model_manager = ModelManager(
    torch_dtype=torch.float16, # 设置模型的数据类型为float16,减少显存占用
    device="cuda", # 指定使用GPU进行计算
    file_path_list=[
        "models/kolors/Kolors/text_encoder", # 文本编码器的路径
        "models/kolors/Kolors/unet/diffusion_pytorch_model.safetensors", # UNet模型的路径
        "models/kolors/Kolors/vae/diffusion_pytorch_model.safetensors" # VAE模型的路径
    ]
)
#-----------------------------------------------------------------------------
# 初始化图像生成管道
pipe = SDXLImagePipeline.from_model_manager(model_manager) # 从模型管理器中加载模型并初始化管道
# 加载并应用LoRA权重到UNet模型
pipe.unet = load_lora(
    pipe.unet, 
    lora_rank=16, # 设置LoRA的秩(rank),与训练脚本中的参数保持一致
    lora_alpha=2.0, # 设置LoRA的alpha值,控制LoRA对模型的影响权重
    lora_path="models/lightning_logs/version_0/checkpoints/epoch=0-step=500.ckpt" # 指定LoRA权重的文件路径
)

Step2 :进行提示词创作并文生图

1.提示词以及生成图

  1. 开场:古色古香的小镇

    • 古镇黄昏时分,炊烟袅袅升起,一群孩童在街道上追逐嬉戏,远处可见一座宏伟的城门。
  2. 主角登场:白马少年

    • 骑着一匹雪白骏马的少年身着青衣,眉宇间英气逼人,正从林间小道缓缓走出,阳光透过树叶洒在他的身上。
  3. 神秘相遇:月下湖畔

    • 月光如水,湖面波光粼粼,少年与一位手持长笛的少女不期而遇,两人目光交汇,周围似乎弥漫着淡淡的雾气。
  4. 危机四伏:密林追击

    • 密林之中,枝叶繁茂,少年带领众人躲避追兵,身后尘土飞扬,前路不明。
  5. 秘密基地:山洞内部

    • 山洞内部布置得温馨且充满神秘感,墙壁上挂着各式各样的武器和地图,火把照亮了洞内的每一个角落。
  6. 决斗:古战场遗迹

    • 在一处荒废的古战场遗址,少年与敌人展开激烈的对决,背景是断壁残垣,天空乌云密布。
  7. 情感高潮:悬崖边的誓言

    • 少年与少女站在悬崖边,背后是夕阳西下的壮丽景色,二人紧紧相拥,誓言永远不分离。
  8. 结局:和平归来的庆典

    • 小镇上举办盛大的庆典活动庆祝和平归来,人们载歌载舞,彩旗飘扬,少年和少女手牵手走在人群之中,脸上洋溢着幸福的笑容。

2.一点思考

通过不断地调整prompt ,发现还存在以下问题:

(1)对于在图片中添加文字的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")

(2)对于人种的混淆使用比较突出

torch.manual_seed(7)
image = pipe(
    prompt="中国风,英俊的青年与女人站在悬崖边,背后是夕阳西下的壮丽景色,二人紧紧相拥,誓言永远不分离",
    negative_prompt="丑陋、变形、嘈杂、模糊、低对比度",
    cfg_scale=4,
    num_inference_steps=50, height=1024, width=1024,
)
image.save("7.jpg")

(3)因为要构建完整的故事结构,应该是要人物协调的

比如说,男主幼年,青年,中年的相貌应有相似之处,当我前面生成了一张青年图,但是需要变换场景时,我希望模型能够保留之前的记忆,而不是出现一个新的人像。但是现在的结果显然不乐观,甚至故事的结局是两个女生的场景。

step3: Scepter 和 Web UI 工具箱的使用

使用了一下Scepter,感觉还是没有驯服这个工具,生图效果一般

  • 30
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值