本文为自学碰壁的完成任务的一个记录总结,无任何参考价值
写在前面:本文章是跟着《动手深度学习》(李沐)学习过程中的动手实操,前因是对一个树叶数据集分类,但是由于自己太小白(太菜了)折腾了两三周才弄出来,但是觉得还是值得记录一下,对整个过程中自己碰壁过程进行一个总结。由于对于树叶分类的那个问题自己有点雨里雾里的,觉得没达到效果,所以才有了在 Kaggle 上 ImageNet Dog Breed Classification 的分类,本文同样也记录了树叶分类
总结:
- 多去论坛或者说竞赛地址看看别人写的代码,多看多练
- 出现问题第一时间应该去查找,可以去IDE debug ,实在不行就Print 大法,我这次有个很关键的问题就是,在树叶分类任务过程中能够,我没有将树叶类别转化为数字而是直接传入Tensor,当然结果注定是失败的,还有就是我在提取类别的时候用了一个for 循环去一个元素一个元素的遍历,花费了大量时间,而在人家的baseline 当中用一个集合思想不能有重复元素就可以解决,效率大大提升,所以多看多练
- 在这个过程中有个自定义dataset类,但是自己不知道是哪里出问题了,导致传入网络的数据是错误的,验证精度从一开始就为零,而训练精度是从0慢慢提升上去,到后面才发现可能是dataset将类别和图片对应传入出问题,所以出问题要有针对性的解决,不要盲目性的瞎捣鼓
ImageNet Dogs Breed Classification
自定义Dataset
from torch.utils.data import Dataset, DataLoader
import numpy as np
from PIL import Image
import pandas as pd
from torchvision import transforms
# 读取标签
dog_dataframe = pd.read_csv('../input/dog-breed-identification/labels.csv')
# 将标签转化为集合获取所有类的集合,然后再转化list进行排序
dog_labels = sorted(list(set(dog_dataframe['breed'])))
# 狗的种类数量
n_class = len(dog_labels)
# 需向将string类型的量转化为数字才能ToTensor
class_to_num = dict(zip(dog_labels,range(n_class)))
class DogsData(Dataset):
def __init__(self, csv_path, file_path, mode='train', valid_ratio=0.1, resize_height=224, resize_width=224):
"""
Args:
csv_path (string): csv 文件路径
img_path (string): 图像文件所在路径
mode (string): 训练模式还是测试模式
valid_ratio (float): 验证集比例
"""
# 调整图片大小
self.resize_height = resize_height
self.resize_width = resize_width
# 图片所在文件夹
self.file_path = file_path
self.valid_ratio = valid_ratio
# 数据是用来训练还是验证
self.mode = mode
# 去掉frame头部份,将从1开始排序
self.data_info = pd.read_csv(csv_path, header=None)
# 得到训练数据的长度(个数)
self.data_len = len(self.data_info.index) - 1
self.train_len = int(self.data_len * (1 - valid_ratio))
# 将数据集分为训练集和验证集
if mode == 'train':
self.train_image = np.asarray(self.data_info.iloc[1:self.train_len, 0])
self.train_label = np.asarray(self.data_info.iloc[1:self.train_len, 1])
self.image_arr = self.train_image
self.label_arr = self.train_label
elif mode == 'valid':
self.valid_image = np.asarray(self.data_info.iloc[self.train_len:, 0])
self.valid_label = np.asarray(self.data_info.iloc[self.train_len:, 1])
self.image_arr = self.valid_image
self.label_arr = self.valid_label
self.real_len = len(self.image_arr)
print('Finished reading the {} set of Leaves Dataset ({} samples found)'
.format(mode, self.real_len))
def __getitem__(self, index):
single_image_name = self.image_arr[index]
# 打开某个具体图片,给出了完整路径
image = Image.open(self.file_path + single_image_name + '.jpg')
#transform 采用了图像增强方法,包括大小,翻转,对比度,亮度,色调,以及正则化
if self.mode == 'train':
transform = transforms.Compose([
transforms.RandomResizedCrop((224), scale=(0.64, 1), ratio=(0.8, 1.0)),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
else:
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224)