adverb
【Kaggle竞赛树叶分类Baline】上万⽚树叶分为⼀百七⼗六类【Kaggle竞赛树叶分类1】
任务是预测叶⼦图像的类别。该数据集包含 176 个类别、18353 张训练图像、8800 张测试图像。每个类别⾄少有 50 张图像⽤于训练。测试集平均分为公共和私⼈排⾏榜。本次⽐赛的评估指标是分类准确度。本章的内容是介绍Baline。下⼀章将介绍提升分类准确度的tricks和模型
环境:将使⽤google colab pro作为代码运⾏和云服务器平台。
#先分配GPU
!nvidia-smi
lab import drive
⾸先,将导⼊colab云端硬盘中,其中有⼀个images⽂件夹,⼀个train表格,test表格,和1个上交预测结果的表格。
可以看到Images⽂件夹中有很多形状不同的叶⼦。
1.Baline(简单的resnet)
⾸先导⼊需要的包
# ⾸先导⼊包
import torch
as nn
import pandas as pd
import numpy as np
暮光之城介绍
from torch.utils.data import Datat, DataLoader
from torchvision import transforms
from PIL import Image
import os
import matplotlib.pyplot as plt
dels as models
# This is for the progress bar.
from tqdm import tqdm
import aborn as sns
使⽤pd.read_csv将训练集表格读⼊,然后看看label⽂件长啥样,image栏是图⽚的名称,label是图⽚的分类标签。
labels_dataframe = pd.read_csv('/content/drive/MyDrive/classify-leaves/train.csv')
labels_dataframe.head(5)
使⽤pd.describe()函数⽣成描述性统计数据,统计数据集的集中趋势,分散和⾏列的分布情况,不包括 NaN值。可以看到训练集总共有18353张图⽚,标签有176类。
labels_dataframe.describe()
⽤条形图可视化176类图⽚的分布(数⽬)。
#function to show bar length
def barw(ax):
for p in ax.patches:
val = p.get_width()#height of the bar
x = p.get_x()+ p.get_width()# x- position
y = p.get_y()+ p.get_height()/2#y-position
ax.annotate(round(val,2),(x,y))
#finding top leaves
plt.figure(figsize =(15,30))
#类别特征的频数条形图(x轴是count数,y轴是类别。)
ax0 =untplot(y=labels_dataframe['label'],order=labels_dataframe['label'].value_counts().index)
barw(ax0)
plt.show()
把label标签按字母排个序,这⾥仅显⽰前10个。
#把label⽂件排个序
leaves_labels =sorted(list(t(labels_dataframe['label'])))
n_class =len(leaves_labels)
print(n_class)
leaves_labels[:10]
176
[‘abies_concolor’,
‘abies_nordmanniana’,
‘acer_campestre’,
‘acer_ginnala’,
‘acer_grium’,
‘acer_negundo’,
‘acer_palmatum’,
‘acer_pensylvanicum’,
‘acer_platanoides’,
纠结英文
privates‘acer_pudoplatanus’]
把label和176类zip⼀下再字典,把label转成对应的数字。
把label转成对应的数字
class_to_num =dict(zip(leaves_labels,range(n_class)))
class_to_num
{‘abies_concolor’: 0,
‘abies_nordmanniana’: 1,
‘acer_campestre’: 2,
‘acer_ginnala’: 3,
‘acer_grium’: 4,
‘acer_negundo’: 5,
‘acer_palmatum’: 6,
‘acer_pensylvanicum’: 7,
‘acer_platanoides’: 8,
‘acer_pudoplatanus’: 9,
‘acer_rubrum’: 10,
…
‘ulmus_pumila’: 173,
‘ulmus_rubra’: 174,
‘zelkova_rrata’: 175}
再将类别数转换回label,⽅便最后预测的时候使⽤。
# 再转换回来,⽅便最后预测的时候使⽤
num_to_class ={v : k for k, v in class_to_num.items()}
创建树叶数据集类LeavesData(Datat),⽤来批量管理训练集、验证集和测试集。
1.定义__init__初始化函数
其中,csv_path是csv⽂件路径,file_path是图像⽂件所在路径,valid_ratio是验证集⽐例为0.2,resize_height和resize_width是调整后的照⽚尺⼨256×256,mode参数最重要,这⾥决定是“训练数据集”还是“验证数据集”还是“测试数据集”:(train/val/test_datat = LeavesData(train_path, img_path, mode='train/valid/test')。
⽤pandas读取csv⽂件,lf.data_info = pd.read_csv(csv_path, header=None) 去掉表头部分。(注意test的cvs路径是不⼀样的)
然后计算数据集的长度,例如读取data的长度乘上(1-0.2)就是训练集数据的长度lf.train_len。
当mode==“train”:
使⽤np.asarray(lf.data_info.iloc[ain_len, 0])读取第1列(图⽚名称列),从第2⾏开始读到lf.train_len是训练集的图像名称。
使⽤np.asarray(lf.data_info.iloc[ain_len, 1])读取第2列(图⽚标签列),从第2⾏开始读到lf.train_len是训练集的图像标签。
当mode==“valid”:
使⽤np.asarray(lf.data_info.ain_len:, 0])读取第1列(图⽚名称列),从第lf.train_len⾏开始读完是验证集的图像名称。
使⽤np.asarray(lf.data_info.ain_len:, 1])读取第2列(图⽚标签列),从第lf.train_len⾏开始读完是验证集的图像标签。
befriend当mode==“test”:
test的cvs路径不同,有⼀个另外的test.csv,使⽤np.asarray(lf.data_info.iloc[1:, 0])读取测试集图像名称列的所有名称。
2.定义__getitem__函数, ⽰例对象p可以通过p[key]取值,这⾥返回每⼀个index对应的图⽚数据和对应的标签。
single_image_name = lf.image_arr[index]从image_arr中得到index对应的⽂件名,然后使⽤img_as_img = Image.open(lf.file_path +
single_image_name)读取图像⽂件。
对训练集的图⽚,定义⼀系列的transform。包括resize到224×224,0.5的概率随机⽔平翻转,ToTensor等。(这个Baline其实只做了随机⽔平翻转的图像增强,没有其他操作,有改进余地)
对验证集和测试集的图⽚,transform⾥不做数据增强,仅resize后ToTensor。
保存transform后的图像img_as_img = transform(img_as_img)
对于训练集和验证集,通过label = lf.label_arr[index]返回图像的string label和 number_label = class_to_num[label]返回number label。⽽测试集,直接返回img_as_img。
# 继承pytorch的datat,创建⾃⼰的
class LeavesData(Datat):
def__init__(lf, csv_path, file_path, mode='train', valid_ratio=0.2, resize_height=256, resize_width=256):
"""
Args:
csv_path (string): csv ⽂件路径
img_path (string): 图像⽂件所在路径
mode (string): 训练模式还是测试模式
valid_ratio (float): 验证集⽐例
"""
# 需要调整后的照⽚尺⼨,我这⾥每张图⽚的⼤⼩尺⼨不⼀致#
lf.file_path = file_path
# 读取 csv ⽂件
# 利⽤pandas读取csv⽂件
lf.data_info = pd.read_csv(csv_path, header=None)#header=None是去掉表头部分
# 计算 length
lf.data_len =len(lf.data_info.index)-1
if mode =='train':
# 第⼀列包含图像⽂件的名称
#lf.data_info.iloc[1:,0]表⽰读取第⼀列,从第⼆⾏开始到train_len
# 第⼆列是图像的 label
lf.image_arr = lf.train_image
lf.label_arr = lf.train_label
elif mode =='valid':
lf.valid_image = np.asarray(lf.data_info.ain_len:,0])
lf.valid_label = np.asarray(lf.data_info.ain_len:,1])
lf.image_arr = lf.valid_image
丰溪里lf.label_arr = lf.valid_label
elif mode =='test':
lf.image_arr = lf.test_image
print('Finished reading the {} t of Leaves Datat ({} samples found)'
.format(mode, lf.real_len))
def__getitem__(lf, index):
# 从 image_arr中得到索引对应的⽂件名
single_image_name = lf.image_arr[index]
# 读取图像⽂件
img_as_img = Image.open(lf.file_path + single_image_name)
#如果需要将RGB三通道的图⽚转换成灰度图⽚可参考下⾯两⾏
butcher怎么读
# if img_de != 'L':
# img_as_img = img_vert('L')
#设置好需要转换的变量,还可以包括⼀系列的nomarlize等等操作
de =='train':
transform = transforms.Compo([
transforms.Resize((224,224)),
transforms.RandomHorizontalFlip(p=0.5),#随机⽔平翻转选择⼀个概率
transforms.ToTensor()
])
el:
# valid和test不做数据增强
transform = transforms.Compo([
transforms.Resize((224,224)),
transforms.ToTensor()
])
img_as_img = transform(img_as_img)
de =='test':
return img_as_img
el:
melody什么意思# 得到图像的 string label
label = lf.label_arr[index]
乡村路带我回家
# number label
number_label = class_to_num[label]
return img_as_img, number_label #返回每⼀个index对应的图⽚数据和对应的label
def__len__(lf):
al_len
定义⼀下不同数据集的csv_path,并通过更改mode修改数据集类的实例对象。
train_path ='/content/drive/MyDrive/classify-leaves/train.csv'
test_path ='/content/drive/MyDrive/classify-leaves/test.csv'
# csv⽂件中已经images的路径了,因此这⾥只到上⼀级⽬录
img_path ='/content/drive/MyDrive/classify-leaves/'
train_datat = LeavesData(train_path, img_path, mode='train')
val_datat = LeavesData(train_path, img_path, mode='valid')
test_datat = LeavesData(test_path, img_path, mode='test')
print(train_datat)
print(val_datat)
boughtprint(test_datat)