【动手学PaddlePaddle2.0系列】手把手教你自定义数据集

【动手学Paddle2.0系列】手把手教你自定义数据集

本次将带领大家进行自定义数据集教程,并完整的走完整个项目流程。

# 解压数据集,大家此处可以视自己的情况决定是不是要重新解压。
!unzip -q data/data42610/foods.zip

1 数据集预处理

此部分首先对数据集进行简单的整理,在food_data.csv中写入图像路径,以及对应的标签。

import os


all_file_dir = 'foods'

# f = open(r'train.txt', 'w')



img_list = []
label_list = []

label_id = 0

class_list = [c for c in os.listdir(all_file_dir) if os.path.isdir(os.path.join(all_file_dir, c))]

# print(class_list)
for class_dir in class_list:


    image_path_pre = os.path.join(all_file_dir, class_dir)

    for img in os.listdir(image_path_pre):
        # print(img)
        # f.write("{0}\t{1}\n".format(os.path.join(image_path_pre, img), label_id))
        img_list.append(os.path.join(image_path_pre, img))
        label_list.append(label_id)
    label_id += 1


生成包含数据集信息的csv文件。

import pandas as pd
import numpy as np



img_df =  pd.DataFrame(img_list)
label_df = pd.DataFrame(label_list)

img_df.columns = ['images']
label_df.columns = ['label']

df = pd.concat([img_df, label_df], axis=1)

df = df.reindex(np.random.permutation(df.index))

df.to_csv('food_data.csv', index=0)


# 读取数据
df = pd.read_csv('food_data.csv')
image_path_list = df['images'].values
label_list = df['label'].values

# 划分训练集和校验集
all_size = len(image_path_list)
train_size = int(all_size * 0.8)
train_image_path_list = image_path_list[:train_size]
train_label_list = label_list[:train_size]
val_image_path_list = image_path_list[train_size:]
val_label_list = label_list[train_size:]

2 自定义数据集

import numpy as np
from PIL import Image
from paddle.io import Dataset
import paddle.vision.transforms as T
import paddle as pd

class MyDataset(Dataset):
    """
    步骤一:继承paddle.io.Dataset类
    """
    def __init__(self, image, label, transform=None):
        """
        步骤二:实现构造函数,定义数据读取方式,划分训练和测试数据集
        """
        super(MyDataset, self).__init__()
        # imgs = []
        # f = open(txt, 'r')
        # for line in f:
        #     line = line.strip('\n')
        #     line = line.rstrip('\n')
        #     words = line.split()
        #     imgs.append((words[0], int(words[1])))
        imgs = image
        labels = label
        
        self.labels = labels
        self.imgs = imgs
        self.transform = transform
            # self.loader = loader
    def __getitem__(self, index):  # 这个方法是必须要有的,用于按照索引读取每个元素的具体内容
        fn = self.imgs
        label = self.labels
        # fn是图片path #fn和label分别获得imgs[index]也即是刚才每行中word[0]和word[1]的信息
        for im,la in zip(fn, label):
            img = Image.open(im)
            img = img.convert("RGB")
            img =  np.array(img)
            label = np.array([la]).astype(dtype='int64')
        # 按照路径读取图片
        if self.transform is not None:
            img = self.transform(img)
            # 数据标签转换为Tensor
        return img, label
        # return回哪些内容,那么我们在训练时循环读取每个batch时,就能获得哪些内容
        # **********************************  #使用__len__()初始化一些需要传入的参数及数据集的调用**********************

    def __len__(self):
        # 这个函数也必须要写,它返回的是数据集的长度,也就是多少张图片,要和loader的长度作区分
        return len(self.imgs)

3 数据加载

import paddle

from paddle.metric import Accuracy
from paddle.vision.models import resnet18


import warnings
warnings.filterwarnings("ignore")

import warnings

warnings.filterwarnings("ignore")


import paddle.vision.transforms as T



transform = T.Compose([
    T.Resize([224, 224]),
    T.ToTensor(),
    T.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
    # T.Transpose(),
])



train_dataset = MyDataset(image=train_image_path_list, label=train_label_list ,transform=transform)

train_loader = paddle.io.DataLoader(train_dataset, places=paddle.CPUPlace(), batch_size=8, shuffle=True)

# build model
model = resnet18(pretrained=True, num_classes=102, with_pool=True)

model = paddle.Model(model)
optim = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters())

4 模型训练&验证

此步骤对模型进行训练,并保存为推理模型。(和checkpoint不同,注意区分)。

此处仅进行了两次迭代,大家有兴趣可以自行调整迭代次数。

# 配置模型
model.prepare(
    optim,
    paddle.nn.CrossEntropyLoss(),
    Accuracy(topk=(1, 2))
    )

model.fit(train_loader,
        epochs=2,
        verbose=1,
        )

model.evaluate(train_dataset, batch_size=8, verbose=1)


model.save('inference_model', False)

5 模型预测推理

在模型预测推理中,最后生成的CSV文件是一个较为通用的竞赛提交文件,大家可以根据自己的需要进行相应的更改。也算是一个小小的福利吧。

import warnings
warnings.filterwarnings('ignore')
import sys
import paddle.fluid as fluid
import paddle
import numpy as np
import os
import pandas as pd

paddle.enable_static()

def load_img(img):
    is_color = True
    resize_size = 320
    crop_size = 100  # 剪切尺寸,最后图片的size是这个值,不是resize_size
    img = paddle.dataset.image.load_image(file=img, is_color=is_color)
    img = paddle.dataset.image.simple_transform(im=img,
                                                resize_size=resize_size, crop_size=crop_size,
                                                is_color=is_color, is_train=False)
    img = img.astype('float32') / 255.0
    return img

def pred_data(path_img_test):
# 构建执行器
    USE_GPU = False
    place = fluid.CUDAPlace(0) if USE_GPU else fluid.CPUPlace()  # 使用CPU执行训练
    infer_exe = fluid.Executor(place)
    inference_scope = fluid.core.Scope()
    # 载入model
    with fluid.scope_guard(scope=inference_scope):
        currentpath = os.path.dirname(sys.argv[0])
        [inference_program,
         feed_target_names,
         fetch_targets] = fluid.io.load_inference_model(
            dirname=os.path.join(currentpath, 'model_'), executor=infer_exe)

        test_imgs_dir = path_img_test
        img_data, img_paths, img_names = [], [], []
        for img_name in os.listdir(test_imgs_dir):
            img_path = os.path.join(test_imgs_dir, img_name)
            img_paths.append(img_path)
            img_data.append(load_img(img_path))
            img_names.append(img_name.split('.')[0])
        img_data = np.array(img_data).astype("float32")

        result = infer_exe.run(program=inference_program,
                               feed={
     feed_target_names[0]: img_data},
                               fetch_list=fetch_targets)
    infer_label = [np.argmax(x) for x in result[0]]
    class_dict = {
     0: 'neg', 1: 'pos'}
    pred_class = []
    for i in infer_label:
        pred_class.append(class_dict[i])
    submit = pd.DataFrame({
     'id': img_names, 'label': pred_class})
    return submit

def main(path_img_test, path_submit):
    # 预测图片
    result = pred_data(path_img_test)
    # 写出预测结果
    result.to_csv(path_submit, index=None, encoding='utf-8')
	
if __name__ == "__main__":

    path_img_test = 'foods/beef_carpaccio'
    path_submit = 'test.csv'
    main(path_img_test, path_submit)

总结

本次实践主要讲解一下如何自定义数据集,并对一个图像分类项目的完整流程进行了讲解。需要注意的几点如下:

(1)在本项目中保存的是推理模型,和checkpoint是不同的,具体的讲解大家可以查看官方API讲解。

(2)数据集中,label的类型需要是int64格式,并且需要扩充一个维度。

(3)关于模型的详细训练过程讲解以及高层API的详细讲解,大家可以参考Paddle2.0应用案例–迁移学习。

一点小小的宣传

我目前在上海,感兴趣的领域包括模型压缩、小目标检测、嵌入式,欢迎交流关注。来AI Studio互粉吧等你哦


你可能感兴趣的:(飞桨炼丹童子的成长之路,python,paddlepaddle,计算机视觉)