Datawhale X 魔搭 AI夏令营--task01、02笔记

目录

task01

1.开通阿里云PAI-DSW试用并在魔搭社区进行授权;

2.创建PAI实例,以上过程较为简单,略;

3.执行baseline

4.但这是第二次运行成果,第一次出现了一些报错,在下图所示代码下方报错:

5.而整个模型微调训练过程如下:

6.将结果上传魔搭社区:

7.最后别忘记关闭pai实例,整个过程结束,结尾附高清图:

task02

1.认识通义千问

2.精度baseline,从零入门AI生图

(1)向通义千问询问代码整体架构:

(2)向通义千问请求逐行解释代码:

(3)追问

3.实战演练-基于话剧的连环画制作

结果如下:


task01

从零入门AI生图原理&实践 是Datawhile 2024年AI夏令营第四期AIGC方向学习活动,基于魔搭社区“可图Kolors-LoRA风格故事挑战赛”开展的时间学习。

Datawhile官方速通链接:Datawhale (linklearner.com)icon-default.png?t=N7T8https://linklearner.com/activity/14/10/24

下面是学习笔记:

1.开通阿里云PAI-DSW试用并在魔搭社区进行授权;
2.创建PAI实例,以上过程较为简单,略;
3.执行baseline

(1)创建实例后输入以下代码以下载baseline文件:

git lfs install
git clone https://www.modelscope.cn/datasets/maochase/kolors.git

这是为了拉取远程baseline文件,回车运行等待就好

3eb1c16ae522487693cf355c47bd6a20.png

之后打开baseline文件;

(2)安装环境并重启kernel

包括安装 Data-Juicer 和 DiffSynth-Studio

其中Data-Juicer为数据处理和转换工具,旨在简化数据的提取、转换和加载过程

DiffSynth-Studio为高效微调训练大模型工具

04ff47e075474c9f9a4a60e11d9bc9fd.png

不过这一步可能会因为网络问题导致环境安装缺漏,重启是为了防止显存溢出影响后续运行

(3)调整prompt,设置想要的图片风格,依次修改8张图片的描述,包括正面和负面

c3adec7ec2e742668f65885ae88204f7.png

这里我修改了图1的八个描述想看看能否成功生成想要的大致类型,我将其修改为:

"二次元,一个紫色长发女性,在草地中站着,双手拿着刀,很严肃,全身,粉色汉服”

e04f9488629b43f8ae1ff9fed812b4e9.png

点击运行后成功运行

4.但这是第二次运行成果,第一次出现了一些报错,在下图所示代码下方报错:

No module named 'data_juicer'

1b8ef771b1fe4cc9a23848e3d4dc8846.png

尝试过后发现只需要restart实例并重新运行便可解决

5.而整个模型微调训练过程如下:

首先下载模型、查看训练脚本传入参数,然后开始训练;调参是很重要的环节但学习任务暂时没到所以很期待之后学习内容

6.将结果上传魔搭社区:

创建新的实例并运行:

mkdir /mnt/workspace/kolors/output & cd 
cp /mnt/workspace/kolors/models/lightning_logs/version_0/checkpoints/epoch\=0-step\=500.ckpt /mnt/workspace/kolors/output/
cp /mnt/workspace/kolors/1.jpg /mnt/workspace/kolors/output/

之后在output文件夹下载jpg文件和ckpt文件,在魔搭社区创建并上传两个文件即可

0c25f8908b4e4ad4918964b8254c3530.png

7.最后别忘记关闭pai实例,整个过程结束,结尾附高清图:

8468d8df4f36441986c8f5f57cdaa11d.jpeg

task02

此任务旨在对baseline的代码有一个更加细致的理解,并学习如何借助AI来提升我们的自学习能力。且通过任务一的学习我们知道数据集的重要性,我们可以在魔搭社区的开源数据集中寻找我们所需要的数据。

下面是正式的学习:

1.认识通义千问

2.精度baseline,从零入门AI生图

task01只是跑了一遍模型,但不知道哪个模块究竟何用,下面将进行系统学习

文生图代码框架如下:

全部代码如下:

!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)向通义千问询问代码整体架构:

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

### 1. 环境和依赖包安装
首先,代码通过`!pip install`命令安装了一系列的Python包,包括`simple-aesthetics-predictor`, `data-juicer`, `peft`, `lightning`, `pandas`, `torchvision`, 和 `DiffSynth-Studio`。

### 2. 数据集加载与预处理
接着,从ModelScope加载了一个名为`lowres_anime`的数据集,并将数据转换为适合进一步处理的格式。具体步骤包括:
- 将数据集中的图像转换为RGB模式并保存到磁盘。
- 创建一个JSONL文件,其中包含每张图片的路径和相关文本描述。

### 3. 数据清洗与过滤
使用`data-juicer`工具对数据进行清洗,包括尺寸和长宽比的过滤,以确保所有图像满足特定的质量标准。这一步骤是通过读取配置文件`data_juicer_config.yaml`来实现的,该配置文件定义了过滤规则和输出路径。

### 4. 数据整理与特征提取
接下来,代码将处理后的数据集整理成DataFrame格式,并使用CLIP模型提取图像和文本的嵌入向量。这些向量用于计算图像和文本之间的相似度。

### 5. 自定义数据集与数据加载器
创建一个自定义的PyTorch数据集类`CustomDataset`,用于封装DataFrame中的数据,并构建一个数据加载器`DataLoader`,以便在训练模型时高效地提供批处理数据。

### 6. 图像生成
最后,利用`StableDiffusionPipeline`生成二次元风格的图像。这部分代码使用了不同的提示(prompt)和负面提示(negative prompt)来指导图像生成过程,从而创造出符合特定描述的二次元图像。

### 7. 结果展示
代码还包含了将生成的多个图像拼接在一起,形成一个大的图像,用于结果展示或进一步分析。

整个工作流涉及数据集的获取、预处理、特征提取、数据集构建以及基于深度学习的图像生成。

(2)向通义千问请求逐行解释代码:

这段代码执行了一系列的任务,从环境设置、数据集处理到图像生成。下面是对每一部分的逐行分析:

### 环境设置

!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

这些命令用于安装必要的Python包,包括`simple-aesthetics-predictor`,`data-juicer`,`peft`,`lightning`,`pandas`,`torchvision`,和`DiffSynth-Studio`。同时卸载了旧版本的`pytorch-lightning`,并重新安装。

### 数据集加载与预处理

from modelscope.msdatasets import MsDataset

ds = MsDataset.load(
    'AI-ModelScope/lowres_anime',
    subset_name='default',
    split='train',
    cache_dir="/mnt/workspace/kolors/data"
)

这里从ModelScope加载了`lowres_anime`数据集,并指定了缓存目录。

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

这部分代码创建了两个目录用于存储处理过的图像和元数据文件。然后遍历数据集,将图像转换为RGB模式并保存,同时生成一个JSONL格式的元数据文件,其中包含每张图像的路径和文本描述“二次元”。

### 数据清洗与过滤

data_juicer_config = """
...
"""
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

这里定义了`data_juicer`的配置文件,包括数据集路径、预处理操作(如图像尺寸和长宽比过滤)等。然后运行`dj-process`命令来应用这些预处理操作。

### 数据整理与特征提取

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`创建DataFrame,将数据写入CSV文件,并显示DataFrame的内容。

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  # 图像文本相似度得分
probs = logits_per_image.softmax(dim=1)  # 计算概率

probs

使用预训练的CLIP模型来计算图像和文本的相似度。

### 自定义数据集与数据加载器

from torch.utils.data import Dataset, DataLoader

class CustomDataset(Dataset):
    ...
    
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)

创建自定义的PyTorch数据集和数据加载器,用于批量处理数据,并再次计算图像与文本的相似度。

### 图像生成

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

使用`StableDiffusionPipeline`生成二次元风格的图像,基于不同的提示和负面提示。

### 结果展示

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

最后,将生成的图像拼接成一张大图,用于展示或进一步分析。

整个代码流程涵盖了从数据集的加载和预处理,到特征提取,再到图像生成和展示的完整过程。

(3)追问

pipe是什么?

pipe是一个StableDiffusionPipeline实例,这是一个深度学习模型,能够根据给定的文本描述(prompt)生成对应的图像。这个模型是在大量数据上预训练的,能够理解和生成与文本相关的视觉内容。

prompt参数

prompt是一个字符串,它包含了您想要生成图像的主题描述。例如,"二次元,一个紫色长发小女孩穿着粉色吊带漏肩连衣裙,在练习室练习唱歌,手持话筒" 这个prompt告诉模型您希望看到的图像内容。

negative_prompt参数

negative_prompt也是一个字符串,但它包含了您不希望在生成的图像中出现的元素或属性。例如,"丑陋、变形、嘈杂、模糊、低对比度" 这个negative_prompt告诉模型避免生成质量差、细节不清楚或有视觉噪音的图像。

guidance_scale参数

guidance_scale是一个浮点数,控制生成图像时promptnegative_prompt的影响程度。较高的guidance_scale意味着模型更严格地遵循promptnegative_prompt,而较低的值则允许更多的随机性和变化。

num_inference_steps参数

num_inference_steps是一个整数,表示在生成图像的过程中迭代的次数。更多的步数通常会导致更精细的图像细节,但也会增加生成所需的时间。

heightwidth参数

这两个参数分别设置了输出图像的高度和宽度,单位是像素。在这个例子中,图像的大小被设定为1024x1024像素。

images[0]

pipe方法返回一个列表,其中包含了生成的图像。由于我们只请求生成一幅图像,所以通过[0]访问列表中的第一个(也是唯一一个)元素。

综上所述,这行代码的作用是根据提供的promptnegative_prompt生成一幅1024x1024像素的图像,并且通过调整guidance_scalenum_inference_steps来控制生成过程的确定性和质量。生成的图像会被保存到变量image中,之后可以进行保存、显示或进一步处理。

如果您需要查看生成的图像,我们可以使用wand或者matplotlib这样的库来显示图像。不过,由于当前的对话环境中无法直接显示图像,您可以运行这段代码在您的本地环境中,并使用适当的图像查看函数来观察结果。如果需要,我也可以帮助您构建一个简单的图像显示脚本。

3.实战演练-基于话剧的连环画制作

基于您的要求,以下是针对每个场景的生图提示词建议,结合古风元素以及场景的描述:

1. **古风,工笔画,一个着汉服的少女,端坐于书斋之中,手执毛笔,凝视着竹简,上半身,周围摆放着砚台和书籍。**
   
   这幅画面聚焦于女主的专注神情和她所在的古典书斋环境,强调了学习的氛围。

2. **古风,淡雅的色彩,同一个少女,趴在桌上,双眸微闭,呼吸轻柔,上半身,身穿蓝色绸缎长袍,桌面上散落着未完成的诗稿。**

   描述了少女在课堂上的小憩,画面温柔,突出其安静的睡态。

3. **古风,云雾缭绕的背景,少女站立于青石小径旁,衣袂飘飘,神色迷离,全身,身后是繁花似锦的春景。**

   场景转换到了梦中,展现了一种超现实的美感,少女仿佛置身于仙境。

4. **古风,骏马驰骋于林间小道,一位英俊少年骑在马上,眼神坚定,全身,背景是翠绿的山林,阳光透过树梢洒下斑驳光影。**

   描述了王子的出场,强调了其英勇的形象和自然的壮丽背景。

5. **古风,二人并肩而立于花园之中,对话亲密无间,全身,背景是盛开的牡丹和精致的亭台楼阁,少女面带微笑,少年神情专注。**

   展现了二人在梦中的愉快交谈,场景充满了浪漫的气息。

6. **古风,二人共乘一骑,少女轻倚在少年身后,双手环绕腰际,全身,背景是广阔的田野和远山,夕阳映照天际。**

   描述了他们共同旅行的情景,画面温馨且充满动感。

7. **古风,少女突然睁眼,从梦中惊醒,上半身,表情惊讶,身着学习时的素色衣裳,周围是熟悉的教室环境。**

   突出了梦醒瞬间的反应,与之前梦幻般的场景形成鲜明对比。

8. **古风,少女重新投入到学习中,与同学们围坐讨论,全身,背景是充满书香气息的教室,桌上堆满卷轴和书籍。**

   描述了女主回到现实世界后,继续与同学们共同学习的场景,强调了团结和学术的氛围。

这些提示词试图捕捉每个场景的精髓,同时保持一致的古风艺术风格,既描绘了人物也展现了环境,还融入了动作和情感的表达。希望这些建议能帮助您实现预期的话剧视觉效果。

将上述关键词,简单修改成自己想要的,如我在每句话中都加入了“水墨画”关键词。运用task01的学习过程中:

结果如下:

1.

2.

3.

4.

5.

6.

7.

8.

4.尝试微调图片

魔搭体验网址:https://www.modelscope.cn/studios/iic/scepter_studio

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值