作者:欧新宇(Xinyu OU)
当前版本:Release v1.0
开发平台:Paddle 2.3.2
运行环境:Intel Core i7-7700K CPU 4.2GHz, nVidia GeForce GTX 1080 Ti
本教案所涉及的数据集仅用于教学和交流使用,请勿用作商用。
最后更新:2022年12月31日
垃圾分类数据集Garbage 是一个包含有40个类别,14802张图像的数据集。该数据集已经事先实现了训练(train)
和测试(test)
的分割,其中测试集没有类别标签。数据集没有给出验证集的划分建议,因此在进行数据列表生成的时候,可以自行按照一定的比列来将官方提供的训练集看作是trainval进行二次划分,即将原来的 train
文件夹划分为训练集train和验证集val。使用train和val完成训练之后,再按照训练获得超参数,对整个训练验证集trainval进行训练,完成后直接输出 测试集结果
到平台进行评估。注意,本数据集给出了类别的标签字典,因此在生成和划分数据子集的时候,建议考虑基于该类别标签字典而非遍历文件夹的方式来完成。
# pcodes004001_train_initialization
import os
import cv2
import json
import numpy as np
import matplotlib.pyplot as plt
import sys
sys.path.append(r'D:\WorkSpace\DeepLearning\WebsiteV2') # 定义课程自定义模块保存位置
from codes.paddle import common, datasets
import paddle
import paddle.vision.transforms as T
import paddle.vision.transforms.functional as F
plt.rcParams['font.sans-serif'] = ['simhei']
plt.rcParams['font.size'] = 14
paddle.vision.set_image_backend('cv2')
# 1. 定义数据集基本信息
dataset_name = 'Garbage'
dataset_path = 'D:\\Workspace\\ExpDatasets\\'
dataset_root_path = os.path.join(dataset_path, dataset_name)
dataset_info_path = os.path.join(dataset_root_path, 'dataset_info.json')
# 2. 图像基本信息
args = {
'input_size': [3, 227, 227], # 定义图像输入模型时的尺寸
'mean_value': [0.485, 0.456, 0.406], # Imagenet均值
'std_value': [0.229, 0.224, 0.225], # Imagenet标准差
}
【关于中文字体的设置说明】
在使用 python 的绘图包 matplotlib 绘制图形时,若要使用中文标签,需要手动指定中文字体。这个操作在Windows和Linux中略有不同。
matplotlib
自带的字体设置命令指定系统自带的字体即可。plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['font.size'] = 14
work
目录,你可以和直接对它进行引用。此外,在使用该字体的位置,还需要手动指定字体的配置信息。# 1. 初始化部分设置
from matplotlib.font_manager import FontProperties
fontpath = '/home/aistudio/work/msyh.ttc'
myFont = FontProperties(fname=fontpath, size=14)
# 2. 显示中文的代码处进行指定
ax.set_title('中文标题', fontproperties=myFont)
plt.title('中文标题', fontproperties=myFont)
plt.ylabel('y轴标签', fontproperties=myFont)
在调用数据集的样本前需要先手动解压数据集到工作目录,
/home/aistudio/work/Garbage
目录..\Workspace\ExpDataset\Garbage
目录此外,完成数据集的解压后,还需要生成数据列表,此处可以直接使用目录下的 generate_annotation.py
文件来实现,但注意需要将文件中的默认路径 dataset_path
修改为当前数据集的保存路径。
注意,以上生成过程,只需要执行一次即可。
在AIStudio上,可以使用以下命令对数据集进行解压
!unzip /home/aistudio/data/data71361/Garbage.zip -d /home/aistudio/work/Garbage/
# !python /home/aistudio/work/Garbage/generate_annotation.py
!python D://Workspace/ExpDatasets/Garbage/generate_annotation.py #
图像列表已生成, 其中训练验证集样本14402,训练集样本11504个, 验证集样本2898个, 测试集样本400个, 共计14802个。
实验难度: 中等
实验摘要: 编写Python代码,实现数据集的定义
实验目标:
实验要求:
.txt
列表文件,并返回图像绝对路径和图像的标签,对于没有标签的测试集,返回值为-1。 ([Your codes 1])(10分)__getitem__
,返回单条数据,包括返回样本数据和对应的标签。返回的图像需要能够应用Q1-2中所定义的数据预处理, ([Your codes 3])(10分)# pcodes00402_DatasetGarbage class DatasetGarbage(paddle.io.Dataset): """定义十二生肖Zodiac数据集""" # args: 数据集定义所使用的相关超参数 # isTransforms=[0|1|2]: 定义Transforms类型,选择是否使用数据增广和数据归约 # 0:仅使用必要的数据规约,包括尺度变换、数据格式和数据类型变换。用于不使用图像变换的特殊场景。 # 1:仅使用数据规约,包括尺度变换、数据格式和数据类型变换、均值消除。用于train和trainval # 2:使用完整的数据归约和数据增广。用于test和val def __init__(self, dataset_root_path, mode='test', args=None, isTransforms=2): assert mode in ['train', 'val', 'test', 'trainval'] self.data = [] # 定义数据序列,用于保存数据的路径和标签 self.args = args # 定义超参数列表 self.isTransforms = isTransforms # 定义transforms类型 # [Q1-1] 读取数据列表文件,将每一行都按照路径和标签进行拆分成两个字段的序列,并将序列依次保存至data序列中 # 1) 若列表信息长度为2,则表示包含路径和标签信息。 # 2) 若列表信息长度为1,则表示只包含路径,不包含标签。一般正式的测试文件都只包含路径,不包含标签。 # [Your codes 1] # [Q1-2] 对训练数据和验证、测试数据采用不同的数据预处理方法 # 1) train和trainval:执行随机裁剪,并完成标准化预处理 # 2) train和trainval:直接执行尺度缩放,并完成标准化预处理 # [Your codes 2] inputSize = self.args['input_size'][1:3] if len(self.args['input_size'])==3 else self.args['input_size'] if self.isTransforms == 0: elif self.isTransforms == 1 or (self.isTransforms == 2 and mode in ['val', 'test']): elif self.isTransforms == 2 and mode in ['train', 'trainval']: # [Q1-3] 定义数据获取函数,返回单条数据,并对图像执行数据预处理,返回样本数据和对应的标签 # [Your codes 3] def __getitem__(self, index): image_path, label = self.data[index] # 根据索引,从列表中取出指定[index]图像,并将数据拆分成路径和列表 img = cv2.imread(image_path, 1) # 使用cv2进行数据读取,0为灰度模式,1为彩色模式 img = self.transforms(img) # 执行数据预处理 label = np.array(label, dtype='int64') # 将标签转换为64位整型 return img, label # 获取数据集的样本总数 def __len__(self): return len(self.data)
实验难度: 中等
实验摘要: 编写Python代码,实现数据集的测试
实验目标:
实验要求:
# pcodes00403_create_DataReader_and_DataLoader # 1. 生成数据读取器 [Q1-4] # [Your codes 4] # 2. 生成数据迭代读取器 [Q1-5] # [Your codes 5] # 3. 生成测试数据 [Q1-6] # [Your codes 6]
训练集样本数:12944,验证集样本数:1458
训练集batch_0的图像形态:[32, 3, 227, 227], 标签形态:[32]
训练集batch_1的图像形态:[32, 3, 227, 227], 标签形态:[32]
训练集batch_2的图像形态:[32, 3, 227, 227], 标签形态:[32]
验证集batch_0的图像形态:[32, 3, 227, 227], 标签形态:[32]
验证集batch_1的图像形态:[32, 3, 227, 227], 标签形态:[32]
# pcodes00404_get_Garbage_labelname def get_Garbage_labelname_from_labelID_by_json(label_id, dataset_info_path): # 1. 根据标签ID,返回Zodiac数据集的文本标签,标签信息来源于dataset_info.json [Q1-7] # [Your codes 7] # 2. 测试标签获取函数
标签 15 的名称为:可回收物/包。
# pcodes00405_show_dataset_images def show_dataset_images(reader, num_rows=2, num_cols=6, scale=1.5): "显示数据集中的图像文件" # 1. 从迭代读取器中迭代地获取数据 _, (image, label) = next(enumerate(reader)) num_images = num_rows*num_cols image = np.transpose(image[0:num_images], (0,2,3,1)) label = label[0:num_images] # 2. 展示获取到的图像 [Q1-8] # [Your codes 8] # 3. 调用可视化函数展示图像数据 [Q1-9] # [Your codes 9]
# pcodes00406_test_initialization
import os
import cv2
import numpy as np
import random
import matplotlib.pyplot as plt
import paddle
import paddle.vision.transforms as T
import paddle.vision.transforms.functional as F
plt.rcParams['font.sans-serif'] = ['simhei']
plt.rcParams['font.size'] = 14
# 1. 定义数据集基本信息
dataset_name = 'Garbage'
dataset_path = 'D:\\Workspace\\ExpDatasets\\'
dataset_root_path = os.path.join(dataset_path, dataset_name)
# 2. 图像基本信息
args = {
'input_size': [3, 227, 227], # 定义图像输入模型时的尺寸
'mean_value': [0.485, 0.456, 0.406], # Imagenet均值
'std_value': [0.229, 0.224, 0.225], # Imagenet标准差
}
title = ['左上', '右上', '左下', '右下', '中央', '左上翻转', '右上翻转', '左下翻转', '右下翻转', '中央翻转']
实验难度: 中等
实验摘要: 编写Python代码,定义推理阶段的数据预处理,包括十重切割函数和基本数据预处理函数
实验目标:
实验要求:
# pcodes00407_function_TenCrop def TenCrop(img, crop_size=227): """AlexNet模型种定义的十重切割法,用于分类预测的测试过程""" # 1. 实现从256像素的输入图像中切割出10个224×224的patch # input_data: Height x Width x Channel img_size = 256 img = F.resize(img, (img_size, img_size)) blob = np.zeros([10, crop_size, crop_size, 3]) # 2. 获取左上、右上、左下、右下、中央及其对应的翻转,共计10个切片样本 [Q2-1] # [Your codes 10] blob[0] = F.crop(img,0,0,crop_size,crop_size) return blob
# pcodes00408_function_SimplePreprocessing def SimplePreprocessing(img, args=None, isTenCrop=True): # 1. 定义数据预处理功能,包含尺度规约、数据类型变换和均值消除 [Q2-2] # [Your codes 11] # 2. 根据超参数iSTenCrop判断是否对数据进行十重切割处理 [Q2-3] # [Your codes 12] if isTenCrop: else: return fake_data
实验难度: 中等
实验摘要: 编写Python代码,输出测试集中任意一个样本的统计和可视化信息。
实验目标:学会使用定义好的数据预处理函数对测试集数据进行统计测试和可视化测试。
实验要求:
提示:
数据预处理前的数据形态: (227, 227, 3)
仅十重切割后的数据形态: (10, 227, 227, 3)
数据预处理后的数据形态: (10, 3, 227, 227)
# pcodes00409_print_results # 1. 从测试集中随机获取一个样本用于统计和可视化测试 [Q2-4] # [Your codes 13.1] # 2. 对数据执行数据预处理 # 2.1 对数据执行十重切割,用于显示未做预处理的样本 # [Your codes 13.2] # 2.2 对数据执行十重切割,并进行简单预处理 # [Your codes 13.3] # 3. 输出预处理后的数据形态 print('数据预处理前的数据形态: {}'.format(img.shape)) print('仅十重切割后的数据形态: {}'.format(fake_blob.shape)) print('数据预处理后的数据形态: {}'.format(fake_data.shape))
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). Got range [-2.117904..2.4945679].
注意,在以下的图像可视化过程中,可能会出现如上的 [Warning] 信息,主要原因是我们进行预处理后,数据可能会偏离图像像数值的规定取值范围 [0, 1] 或 [0, 255],此时若强制进行可视化,则会出现警告信息,这属于正常现象。
# pcodes00410_visualization # 1. 可视化仅执行十重切割后的图像切片 [Q2-5.1] # [Your codes 14.1] plt.figure(1, figsize=(18, 8)) # 2. 可视化执行数据预处理后的图像切片 [Q2-5.2] # [Your codes 14.2] plt.figure(2, figsize=(18, 8))