DataWhale X 魔搭 AI夏令营第四期Task2

一、认识通义千问

1、通义千问的自我介绍

Prompt1:通义千问,请介绍一下自己。

回答效果不是很好,重新调调整提示词

Prompt2:通义千问,请介绍一下自己,并讲述一下自己有什么能力。

可以看到,这次的回答相比较前面的回答详细了许多。然后,可以聚焦到知识问答,让通义千问回答的更详细一些。

Prompt3:通义千问,请详细介绍一下你的“知识问答”的能力。

二、利用通义千问辅助阅读代码

首先,将baseline1的代码整理为一段代码:

!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

1、分析代码的主体结构

Prompt1

你是一个优秀的python开发工程师,现在我们需要你帮我们分析这个代码的主体框架,你需要把代码按照工作流分成几部分,用中文回答我的问题。{此处替换前面的代码}

返回结果

这段代码可以分为以下几个主要的工作流程部分:

1. 环境设置与依赖安装:

  • 安装必要的Python包,如`simple-aesthetics-predictor`, `data-juicer`, `peft`, `lightning`, `pandas`, `torchvision`, `DiffSynth-Studio`。
  • 卸载`pytorch-lightning`并重新安装。

2. 数据集加载与处理:

  • 从ModelScope加载`lowres_anime`数据集。
  • 遍历数据集,将图像转换为RGB格式并保存到磁盘,同时创建一个JSONL文件存储每张图片的路径和对应的描述文本。

3. 数据过滤与转换:

  • 创建`data_juicer`配置文件,用于定义数据处理规则,包括图像尺寸过滤和宽高比过滤。
  • 使用`data_juicer`工具处理数据,应用过滤器,并输出处理后的结果。

4. 数据整理与特征提取:

  • 将处理后的数据读取到Pandas DataFrame中,方便后续操作。
  • 利用CLIP模型(Contrastive Language-Image Pre-training)计算图像和文本的相似度分数。

5. 自定义数据集与DataLoader:

  • 创建一个自定义PyTorch数据集`CustomDataset`,用于封装图像和文本数据。
  • 构建`DataLoader`以便于批处理和数据加载。

6. 图像生成:

  • 使用`StableDiffusionPipeline`从`diffusers`库生成图像,根据给定的提示和负面提示生成二次元风格的图像。
  • 保存生成的图像到磁盘,并进行多次尝试以生成不同场景下的图像。

7. 图像拼接:

  • 最后,将生成的图像按行和列拼接成一个大的图像,并调整大小,以方便展示或进一步处理。

整个流程涉及数据集的加载、预处理、特征提取、自定义数据集构建、图像生成以及最终的图像拼接,覆盖了从数据处理到深度学习模型应用的完整过程。

可以看到,统一千问有较强的代码理解能力,概括了代码不同功能模块。

 2、逐行解释代码

Prompt2

你是一个优秀的python开发工程师,现在我们需要你帮我们逐行分析这个代码,并返回注释后的代码清单。用中文回答我的问题。{此处替换前面的代码}

返回结果

以下是带有更详细注释的代码清单:

# 使用pip命令行工具安装simple-aesthetics-predictor库
!pip install simple-aesthetics-predictor

# 以可编辑模式安装data-juicer库及其依赖项,并在安装过程中显示详细输出
!pip install -v -e data-juicer

# 卸载pytorch-lightning库,使用-y参数确认卸载而无需交互式确认
!pip uninstall pytorch-lightning -y

# 安装peft(用于微调模型)、lightning(PyTorch Lightning库)、pandas(数据分析库)和torchvision(计算机视觉库)等库
!pip install peft lightning pandas torchvision

# 再次以可编辑模式安装DiffSynth-Studio库,这通常意味着从本地文件系统或版本控制系统安装
!pip install -e DiffSynth-Studio

# 导入ModelScope的数据集模块,用于加载和管理数据集
from modelscope.msdatasets import MsDataset

# 加载名为'AI-ModelScope/lowres_anime'的数据集,选择默认子集的训练数据,缓存目录设置为"/mnt/workspace/kolors/data"
ds = MsDataset.load(
    'AI-ModelScope/lowres_anime',
    subset_name='default',
    split='train',
    cache_dir="/mnt/workspace/kolors/data"
)

# 导入json模块,用于处理JSON数据;os模块,用于操作系统相关功能;SpecialTokens类,可能用于标记特殊符号;tqdm库,用于显示进度条
import json, os
from data_juicer.utils.mm_utils import SpecialTokens
from tqdm import tqdm

# 创建训练图像存储目录,如果目录已经存在,则exist_ok=True参数确保不会抛出错误
os.makedirs("./data/lora_dataset/train", exist_ok=True)

# 创建data-juicer输入数据目录,同样如果目录存在则不会引发异常
os.makedirs("./data/data-juicer/input", exist_ok=True)

# 打开"data/data-juicer/input/metadata.jsonl"文件以写入模式,准备记录元数据
with open("./data/data-juicer/input/metadata.jsonl", "w") as f:

    # 遍历数据集中的每一个元素,使用tqdm显示进度条
    for data_id, data in enumerate(tqdm(ds)):

        # 将图像转换为RGB颜色模式,这是许多图像处理库的常用要求
        image = data["image"].convert("RGB")

        # 将图像保存到指定目录下,文件名为数据ID对应的.jpg格式
        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"]}

        # 将元数据字典转换为JSON字符串,写入文件,每条数据后追加换行符
        f.write(json.dumps(metadata))
        f.write("\n")

# 定义一个YAML格式的字符串,作为data-juicer的数据处理配置文件
data_juicer_config = """
# 全局参数
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:  # 过滤图像尺寸不符合要求的数据
        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
"""

# 将配置字符串写入"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())

# 调用dj-process命令,使用上述配置文件来处理数据集
!dj-process --config data/data-juicer/data_juicer_config.yaml

# 导入pandas库,用于数据处理和分析;再次导入os和json模块;导入PIL库的Image模块,用于图像处理
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)

# 打开"data/data-juicer/output/result.jsonl"文件,读取处理后的数据
with open("./data/data-juicer/output/result.jsonl", "r") as f:

    # 遍历文件的每一行,使用tqdm显示进度条
    for line in tqdm(f):

        # 解析每一行的JSON数据,将其转换为Python字典
        metadata = json.loads(line)

        # 将文本信息添加到texts列表中
        texts.append(metadata["text"])

        # 将图像文件路径添加到file_names列表中
        file_names.append(metadata["image"][0])

# 使用texts和file_names列表创建一个DataFrame,列名分别为"text"和"file_name"
df = pd.DataFrame({"text": texts, "file_name": file_names})

# 将DataFrame保存为CSV文件,不保存索引
df.to_csv("./data/data-juicer/output/result.csv", index=False)

# 显示DataFrame的内容
df

# 导入CLIP模型和处理器类
from transformers import CLIPProcessor, CLIPModel
import torch

# 加载预训练的CLIP模型,使用"openai/clip-vit-base-patch32"版本
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")

# 加载预训练的CLIP处理器,用于数据预处理,同样使用"openai/clip-vit-base-patch32"版本
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")

# 从DataFrame中读取图像文件路径,打开图像并存储为列表
images = [Image.open(img_path) for img_path in df["file_name"]]

# 使用处理器预处理图像和文本数据,返回PyTorch的张量,设置return_tensors参数为"pt"表示返回PyTorch的Tensor类型
inputs = processor(text=df["text"].tolist(), images=images, return_tensors="pt", padding=True)

# 将预处理后的数据送入CLIP模型,获取模型输出
outputs = model(**inputs)

# 获取图像和文本之间的相似度得分
logits_per_image = outputs.logits_per_image

# 计算图像和文本匹配的概率分布
probs = logits_per_image.softmax(dim=1)

# 显示计算出的概率分布
probs

# 导入PyTorch的Dataset和DataLoader类,用于构建数据集和数据加载器
from torch.utils.data import Dataset, DataLoader

# 定义自定义数据集类CustomDataset,继承自Dataset类
class CustomDataset(Dataset):

    # 初始化方法,接收DataFrame和处理器作为参数
    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

# 使用CustomDataset类创建数据集实例
dataset = CustomDataset(df, processor)

# 创建数据加载器,用于在训练时批量加载数据,设置批处理大小为8
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库,用于生成随机种子
import torch

# 设置随机种子,确保生成结果的可重复性
torch.manual_seed(1)

# 加载预训练的Stable Diffusion模型,使用"CompVis/stable-diffusion-v-1-4"版本,使用半精度浮点数(float16)
pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v-1-4", torch_dtype=torch.float16)

# 将模型移动到CUDA设备上,以便在GPU上运行
pipe = pipe.to("cuda")

# 设置生成图像的提示(prompt),负面提示(negative prompt),指导尺度(guidance scale),推理步数(inference steps)等参数
prompt = "二次元,一个紫色长发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌,手持话筒"
negative_prompt = "丑陋、变形、嘈杂、模糊、低对比度"
guidance_scale = 4
num_inference_steps = 50

# 使用Stable Diffusion模型生成图像,参数包括prompt、negative_prompt、guidance_scale、num_inference_steps等
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

# 使用相同的逻辑生成多个图像,每次使用不同的prompt和文件名保存图像
# 下面的代码重复了上述过程,生成多个图像并保存到磁盘

# 导入numpy库,用于数组操作;再次导入PIL库的Image模块,用于图像处理
import numpy as np
from PIL import Image

# 加载所有生成的图像,并将它们转换为NumPy数组形式
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)

# 将拼接后的图像调整大小为1024x2048像素
image = Image.fromarray(image).resize((1024, 2048))

# 显示最终拼接后的图像
image

三、实战演练——基于话剧的连环画制作

1、数据准备

Prompt

尺寸1024*768  CFG=4.08 采样步数30

Positive Prompt:
1、沙漠,卡通风格,两人,坠毁的飞机,一名飞行员穿着黑色飞行服和黑色手套,一个小王子有黄色头发,穿着红色披肩和绿色长衫,两人正对,飞行员在沙地上画画
2、卡通风格,在光秃秃的小行星上,一个小王子有黄色头发,穿着红色披肩和绿色长衫,除了一朵玫瑰花盛开,别无他物
3、卡通风格,在光秃秃的小行星上,一个小王子有黄色头发,穿着红色披肩和绿色长衫,一朵玫瑰花盛开,玫瑰花说谎,小王子感到被欺骗
4、卡通风格,在小行星上,两个人,一个小王子有黄色头发,穿着红色披肩和绿色长衫,脸上露出不安。一个酒鬼穿着破烂的灰色衣服,拿着酒瓶,酩酊大醉
5、卡通风格,在沙漠中,一个小王子有黄色头发,穿着红色披肩和绿色长衫,一条蛇在地上说话,远处的高山上有一座玫瑰庄园
6、卡通风格,在玫瑰园中,一个小王子有黄色头发,穿着红色披肩和绿色长衫,与一只狐狸说话,王子感到豁然开朗
7、沙漠,卡通风格,两人,一个小王子有黄色头发,穿着红色披肩和绿色长衫,一名穿着黑色飞行服和黑色手套的飞行员,两人在一口井旁边休息,非常满足
8、沙漠,卡通风格,穿着黑色飞行服和黑色手套的飞行员,脸上很悲伤,一个小王子有黄色头发,穿着红色披肩和绿色长衫,被蛇咬了,躺在旁边的地上,脸上很安详

Negative Prompt:
统一为  模糊,低分辨率

结果展示

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值