一、第一部分讲解

!mkdir -p /kaggle/images/

from PIL import Image

from pathlib import Path

images = list(Path('/kaggle/input/stable-diffusion-image-to-prompts/images').glob('*.png'))

for path in images:

Image.open(path).save(f'/kaggle/images/{path.stem}.jpg'),逐行解读代码

第一行代码使用了 Linux 中的 mkdir 命令,其中选项 -p 表示如果要创建的目录已经存在则不会报错。

第二行代码导入了 Python 中的 PIL 库中的 Image 模块,该模块用于图像的读取、处理和保存。

第三行代码导入了 Python 中的 pathlib 库中的 Path 模块,该模块用于处理文件路径。

第四行代码使用 Path 类的 glob() 方法对指定文件夹下的所有 .png 文件进行了遍历,并将它们的文件路径保存在 list 类型的变量 images 中。

第五行代码使用 for 循环对每个文件路径进行遍历,并使用 Image 模块中的 open() 方法读取 png 格式的文件并将其转换成 jpg 格式,并将转换后的图像保存到指定文件夹中,其中 path.stem 表示 path 路径中的文件名(不包含扩展名)。因此,文件路径 “/kaggle/input/stable-diffusion-image-to-prompts/images/test.png” 在经过 stem() 函数处理后,返回的是 “test” 字符串。路径 “/kaggle/images/{path.stem}.jpg” 表示保存的目标路径,其中 {path.stem} 会被替换成文件名。

二、stem()函数介绍

在 Python 中,Path 类提供了 stem() 函数,该函数用于获取路径中的文件名,但不包括扩展名。 参数 path 表示完整的文件路径。当调用该函数时,函数会自动忽略文件路径中的目录名,只保留文件名及其扩展名部分。

例如,如果路径为 ‘C:/Users/Administrator/Desktop/test.txt’ ,则调用 stem() 函数后会返回 ‘test’ 。

可以通过与其他字符串进行拼接的方式来生成自定义的新路径字符串,如:‘C:/Users/Administrator/Desktop/’ + stem + ‘.jpg’ 。

stem() 函数非常实用,可用于很多业务场景中。例如,对文件进行批量处理时,我们可以先遍历文件夹,并使用 stem() 函数来获取每个文件的文件名,以方便后续对文件的操作。

三、调包部分

%%writefile conv_tta2.py

该代码是一个 Python 脚本,使用 Jupyter Notebook 或者 Google Colab 等工具创建并保存的。通过 %%writefile 指令将其保存到名为 conv_tta2.py 的文件中。

import numpy as np

import pickle

import pandas as pd

from tqdm import tqdm

import torch

from sklearn.model_selection import train_test_split

from glob import glob

from torch import nn

import torch.optim as optim

from torch.utils.data import DataLoader

from PIL import Image

from pathlib import Path

import open_clip

from transformers import AutoModel, AutoProcessor

这段代码中导入了多个 Python 库,包括 numpy、pickle、pandas、tqdm、torch、sklearn、glob、PIL、pathlib 和 transformers 等。下面逐行介绍它们的作用:

numpy:Python 中常用的数值计算库,提供高性能的数值计算功能。pickle:Python 中的一个序列化和反序列化库,可以将对象转换为字节流并保存到文件中,也可以从文件中读取字节流并重新构建为相应的对象。pandas:Python 中常用的数据处理库,提供高效处理结构化数据的功能和工具。tqdm:Python 中的进度条库,可以在循环中实时显示任务进度。torch:PyTorch 的主要库,提供了多种用于机器学习和深度学习的模型、函数和工具。sklearn:Python 中常用的机器学习库,提供了多种常用机器学习算法的实现。glob:Python 中用于遍历文件夹内文件的库。PIL:Python 中用于图像处理的库,提供了多种对图像进行操作的函数和工具。pathlib:Python 标准库中的文件路径处理库,提供了更为直观和友好的文件路径操作工具。transformers:PyTorch 中 NLP 任务开源工具库 Hugging Face 的一部分,提供了预训练模型、分词器、数据集等相关的工具。其中,AutoModel 用于自适应选择模型,AutoProcessor 用于自适应选择预处理器。

四、训练

BATCHSIZE=16

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

torch.backends.cuda.matmul.allow_tf32 = True # allow tf32 on matmul

torch.backends.cudnn.allow_tf32 = True # allow tf32 on cudnn

clip_model, _, clip_processor = open_clip.create_model_and_transforms('convnext_xxlarge', pretrained=None)

BATCHSIZE:表示训练时每批次输入的样本数量。device:用于将张量存储在 GPU 或 CPU 上。如果 GPU 可用,则选择 GPU,否则选择 CPU。torch.backends.cuda.matmul.allow_tf32:允许在图像运算中使用 TF32 的精度。torch.backends.cudnn.allow_tf32:允许在 cudnn 库中使用 TF32 的精度。clip_model:使用 OpenAI 的 CLIP 模型预训练模型,这里选择的是 convnext_xxlarge。clip_processor:使用 Hugging Face 的 AutoProcessor 处理器对 CLIP 模型进行预处理。

class Net(nn.Module):

def __init__(self):

super(Net, self).__init__()

clip = clip_model

self.vision = clip.visual

self.fc = nn.Linear(1024, 384)

def forward(self, x):

out = self.vision(x)

return self.fc(out)

def load_pretrained_model():

model = Net()

return model.to(device)

这段代码定义了一个名为 Net 的类,该类继承自 torch.nn.Module 类。Net 类中包含了构造函数 init() 和前向传播函数 forward() 。

在构造函数中,定义了一个名为 clip 的 CLIP 模型,并将其赋值给 self.vision 变量。然后,使用 torch.nn.Linear() 函数定义了一个线性转换层,输入大小为 1024 ,输出大小为 384 ,并将其赋值给 self.fc 变量。

前向传播函数 forward() 定义了一个输入张量 x 。首先使用 self.vision(x) 将输入张量 x 作为 CLIP 模型的输入,并返回模型的输出。接着,将该输出传入到 self.fc 中进行线性转换,并将结果返回。

load_pretrained_model() 函数定义了一个名为 model 的 Net 类的实例,并将其移动到指定的设备上进行计算,最后将其返回。

class IMGDataset:

def __init__(self, image_paths, clip_processor=clip_processor):

self.images = image_paths

self.input_processor = clip_processor

def __len__(self):

return len(self.images)

def __getitem__(self, item):

image = Image.open(self.images[item])

image = self.input_processor(image)

return image

这段代码定义了一个名为 IMGDataset 的类,该类实现了 PyTorch 的 Dataset 类,并重写了其中的 init() 、len() 和 getitem() 方法。

在构造函数 init() 中,定义了一个名为 image_paths 的变量,并将其赋值给 self.images 变量。 clip_processor 用于对输入图像进行预处理。

len() 方法返回数据集的大小,即包含多少张图片。

getitem() 方法定义了获取数据集中某一张图片的方式。首先,使用 PIL 库中的 Image.open() 函数打开图片,并将图像路径作为参数传入。接着,使用 self.input_processor 对图像进行预处理,并将结果返回。

images = list(Path('/kaggle/images').glob('*.jpg'))

model = Net()

model.load_state_dict(torch.load('/kaggle/input/notebook683363fc71/SD14/train_convnext_xxlarge_littleboat_on1764k_f0_cv0.6540_0.6691_ep3_unfree16.pt'))

这段代码首先使用 Path() 函数从指定目录 ‘/kaggle/images’ 中选取所有后缀为 ‘.jpg’ 的图片文件,并将其以列表的形式存储在 images 变量中。

接着,利用前面定义的 load_pretrained_model() 函数创建了一个名为 model 的 Net 类实例,并加载了预训练好的模型参数。这里使用 torch.load() 函数将保存的模型参数加载到新创建的模型实例中。其中, ‘/kaggle/input/notebook683363fc71/SD14/trainconvnextxxlargelittleboaton1764kf0cv0.65400.6691ep3_unfree16.pt’ 指定了保存模型参数的位置和文件名。

model.to(device)

model.eval()

test_dataloader = DataLoader(dataset=IMGDataset(images),

batch_size=BATCHSIZE, shuffle=False, num_workers=2)

这段代码将 model 模型移动到设备 (device) 上进行计算,并且将模型设置为评估模式 (model.eval()) 。

接下来,使用定义的 IMGDataset 类将所有选取的图片构成的列表 (images) 转为数据集,并使用 DataLoader 将数据集中的数据按照指定的步幅(batchsize = BATCHSIZE)进行加载。这里, shuffle = False 表示不随机打乱数据集中的数据,num_workers = 2 表示使用两个进程来预处理数据。预处理过程中,将图像的路径作为参数传递给 IMGDataset 类的 getitem() 方法,获取处理后的图像,并将结果用于训练和预测。

五、预测

preds = []

with torch.no_grad():

for batch_images in tqdm(test_dataloader):

batch_images = batch_images.to(device)

pred = model(batch_images).cpu().numpy()

pred2 = model(batch_images.flip(2)).cpu().numpy()

pred3 = model(batch_images.flip(3)).cpu().numpy()

ps = (pred+pred2+pred3)/3

preds.append(ps)

这段代码使用一个空的列表 preds 存储预测结果。

首先,对 DataLoader 对象中的所有数据进行迭代,每次取出一个 batch_size 大小的数据。同时,将该数据移动到设备 (device) 上进行计算。

接着,使用预训练好的模型 (model) 对取出的数据 (batch_images) 进行前向传播,并将得到的输出转换为 numpy 数组形式。注意,在得到预测结果之前,还对数据 (batch_images) 进行了翻转操作 (batch_images.flip(2) 和 batch_images.flip(3)) ,得到两个翻转后的预测结果 pred2 和 pred3,并将这三个预测结果取平均值 ps ,并将 ps 添加到列表 preds 中。在迭代完成后,preds 中存储了所有图片的预测结果。

imgIds = [i.stem for i in images]

EMBEDDING_LENGTH = 384

imgId_eId = [

'_'.join(map(str, i)) for i in zip(

np.repeat(imgIds, EMBEDDING_LENGTH),

np.tile(range(EMBEDDING_LENGTH), len(imgIds)))]

prompt_embeddings = np.vstack(preds).flatten()#predict(images, CFG.model_path, CFG.model_name, CFG.input_size, CFG.batch_size)

submission = pd.DataFrame(

index=imgId_eId,

data=prompt_embeddings,

columns=['val']

).rename_axis('imgId_eId')

submission.to_csv('submission.csv')

这段代码定义了 imgIds 列表,其中每个元素表示一个图片的文件名,该列表中的元素数量与 images 列表中的元素数量相同。

接下来,定义了 EMBEDDING_LENGTH 变量,其值为384。然后,使用 zip() 函数和 map() 函数将 imgIds 中的每个元素与 range(EMBEDDING_LENGTH) 中的每个元素进行组合,并使用 ‘’.join() 函数将其拼接成形如 ‘filename0’ 的字符串。最后,将所有字符串组成一个列表 imgId_eId。

prompt_embeddings 是一个一维的 numpy 数组,存储着所有图片的嵌入向量( embedding )。可以将这个嵌入向量提供给各种计算机视觉任务的模型,如分类、检索和聚类等。

最后,将嵌入向量和图片的文件名以及元素编号组成的索引存储在 DataFrame 对象中,并指定 csv 格式的文件名 ‘submission.csv’ ,并调用 to_csv() 方法将其保存到磁盘上。

参考链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: