文章目录

  • 一、数据加载
  • 二、模型构建与训练
    • 1. resnet
      • 1.1 ResNet-50模型微调+冻结
      • 1.2 五折交叉验证
      • 1.3 模型预测
      • 1.4 利用K-Fold结果投票获取最终提交数据
      • 1.5 kaggle提交
    • 2. resnext
      • 2.1 resnext50_32x4d模型微调+冻结层
      • 2.2 五折交叉验证
      • 2.3 Resnext模型预测
      • 2.4 K-Fold模型投票获取最优解
  • 三、总结

  趁假期的最后一天填上kaggle叶子分类的坑,本来想把这个比赛的成绩刷到95%以上再写这篇Blog记录的,但是后面学习工作比较多,刷比赛可能并不是很划算。这里基于Charlesyyun提供的baseline代码进行了模型设计和训练。主体思路其实没什么多说的,只是通过比赛可以将之前学到的东西融合整理起来,这能够较大地提高动手的能力。

7th: ResNeSt+ResNeXt+DenseNet (0.98840)

数据分析请参考前一篇Blog: 玩转Kaggle:Classify Leaves(叶子分类)——数据分析篇

一、数据加载

import torch.utils.data as Data
from torchvision import transforms
import torchvision
from PIL import Image
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import LabelEncoder,OneHotEncoder
import torch
from torch import nn
import d2l.torch as d2l
from sklearn.model_selection import train_test_split,KFold
from torch.optim.lr_scheduler import CosineAnnealingLR
from tqdm import tqdm
import ttach as tta
  1. 首先构建自己的数据加载器,基于pytorch的dataset类进行复写是个不错的方法
  2. 由于训练数据的标签是用得字符表示,在训练的时候我们需要将其映射到对应的数值上,使用labelencoder = LabelEncoder()可以得到这样一个映射表
  3. 由于我们的训练数据集太小,需要适当地对数据进行数据增强。由于我是在我个人电脑上进行跑模型,GPU算力有限,所以为了保证内存不溢出,我将图片裁减到了128*128大小,这极大地影响了我最后结果地精度,如果有条件,请裁减到224*224比较合适
class LeavesSet(Data.Dataset):"""construct the dataset"""def __init__(self,images_path,images_label,transform=None,train=True):self.imgs = [os.path.join('/data/liufeng/project/MachineLearning/LiMu/data/classify-leaves/',"".join(image_path)) for image_path in images_path] # if train dataset : get the appropriate labelif train:self.train = Trueself.labels = images_labelelse:self.train = False# transformself.transform = transformdef __getitem__(self,index):image_path = self.imgs[index]pil_img = Image.open(image_path)if self.transform:transform = self.transformelse:# if not define the transform:default resize the figure(224,224) and ToTensortransform = transforms.Compose([transforms.Resize((224,224)),transforms.ToTensor()])data = transform(pil_img)if self.train:image_label = self.labels[index]return data,image_labelelse:return data def __len__(self):return len(self.imgs)# load initial data to dataloader,and encode the label
def load_data_leaves(train_transform=None,test_transform=None):train_data = pd.read_csv('./data/classify-leaves/train.csv')test_data = pd.read_csv('./data/classify-leaves/test.csv')# encode the train labellabelencoder = LabelEncoder()labelencoder.fit(train_data['label'])train_data['label'] = labelencoder.transform(train_data['label'])label_map = dict(zip(labelencoder.classes_,labelencoder.transform(labelencoder.classes_)))label_inv_map = {v:k for k,v in label_map.items()}# get the train data and transorm it as a batch train_dataSet = LeavesSet(train_data['image'],train_data['label'],transform=train_transform,train=True)test_dataSet = LeavesSet(test_data['image'],images_label=0,transform=test_transform,train=False)return (train_dataSet,test_dataSet ,label_map,label_inv_map,)

定义一下训练数据和测试数据需要进行怎样的数据转换/增强。需要注意一点:一般情况下validation data 应该和test data 使用相同的transform,但是我这里发现的时候已经写好了后面的内容,偷懒不想更改了也就将错就错了。如果有人复写,可以自己考虑一下,其实也不难。

# define the transform
train_transform = transforms.Compose([# 随机裁剪图像,所得图像为原始面积的0.08到1之间,高宽比在3/4和4/3之间。# 然后,缩放图像以创建224 x 224的新图像transforms.RandomResizedCrop(128, scale=(0.08, 1.0), ratio=(3.0 / 4.0, 4.0 / 3.0)),transforms.RandomHorizontalFlip(),# 随机更改亮度,对比度和饱和度transforms.ColorJitter(brightness=0.4, contrast=0.4, saturation=0.4),# 添加随机噪声transforms.ToTensor(),# 标准化图像的每个通道transforms.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225])])test_transform = transforms.Compose([transforms.Resize(256),# 从图像中心裁切224x224大小的图片transforms.CenterCrop(128),transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225])])train_dataset,test_dataset,label_map,label_inv_map = load_data_leaves(train_transform,test_transform)

二、模型构建与训练

1. resnet

1.1 ResNet-50模型微调+冻结

微调+冻结部分层:

# 是否要冻住模型的前面一些层
def set_parameter_requires_grad(model, feature_extracting):if feature_extracting:model = modelfor param in model.parameters():param.requires_grad = False# ResNeSt模型
def resnet_model(num_classes, feature_extract = False):model_ft = torchvision.models.resnet50(pretrained=True)set_parameter_requires_grad(model_ft, feature_extract)num_ftrs = model_ft.fc.in_featuresmodel_ft.fc = nn.Sequential(nn.Linear(num_ftrs, num_classes))return model_ft

定义超参数

# Configuration options
k_folds = 5
num_epochs = 20
learning_rate = 1e-4
weight_decay = 1e-3
loss_function = nn.CrossEntropyLoss()
# For fold results
results = {}# Set fixed random number seed
torch.manual_seed(1)# devices
device = d2l.try_gpu()# Define the K-fold Cross Validator
kfold = KFold(n_splits=k_folds, shuffle=True)

1.2 五折交叉验证

# Start print
print('--------------------------------------')# K-fold Cross Validation model evaluation
for fold, (train_ids,valid_ids) in enumerate(kfold.split(train_dataset)):# Printprint(f'FOLD {fold}')print('--------------------------------------')# Sample elements randomly from a given list of ids, no replacement.train_subsampler = torch.utils.data.SubsetRandomSampler(train_ids)valid_subsampler = torch.utils.data.SubsetRandomSampler(valid_ids)# Define data loaders for training and testing data in this foldtrainloader = torch.utils.data.DataLoader(train_dataset,batch_size=64, sampler=train_subsampler, num_workers=4)validloader = torch.utils.data.DataLoader(train_dataset,batch_size=64, sampler=valid_subsampler, num_workers=4)# Initialize a model and put it on the device specified.model = resnet_model(176)model = model.to(device)model.device = device# Initialize optimizeroptimizer = torch.optim.Adam(model.parameters(),lr=learning_rate,weight_decay= weight_decay)#   optimizer = SWA(our_optimizer, swa_start=5, swa_freq =5, swa_lr=0.05)scheduler = CosineAnnealingLR(optimizer,T_max=10)# Run the training loop for defined number of epochsfor epoch in range(0,num_epochs):model.train()# Print epochprint(f'Starting epoch {epoch+1}')# These are used to record information in trainingtrain_losses = []train_accs = []# Iterate the training set by batchesfor batch in tqdm(trainloader):# Move images and labels to GPUimgs, labels = batchimgs = imgs.to(device)labels = labels.to(device)# Forward the datalogits = model(imgs)# Calculate lossloss = loss_function(logits,labels)# Clear gradients in previous stepoptimizer.zero_grad()# Compute gradients for parametersloss.backward()# Update the parameters with computed gradientsoptimizer.step()# Compute the accuracy for current batch.acc = (logits.argmax(dim=-1) == labels).float().mean()# Record the loss and accuracy.train_losses.append(loss.item())train_accs.append(acc)
#         print("第%d个epoch的学习率:%f" % (epoch+1,optimizer.param_groups[0]['lr']))scheduler.step()# The average loss and accuracy of the training set is the average of the recorded values.train_loss = np.sum(train_losses) / len(train_losses)train_acc = np.sum(train_accs) / len(train_accs)# Print the information.print(f"[ Train | {epoch + 1:03d}/{num_epochs:03d} ] loss = {train_loss:.5f}, acc = {train_acc:.5f}")
#     print(f"[ Train | {epoch + 1:03d}/{num_epochs:03d} ] loss = {train_loss:.5f}")# Train process (all epochs) is completeprint('Training process has finished. Saving trained model.')print('Starting validation')# Saving the modelprint('saving model with loss {:.3f}'.format(train_loss))save_path = f'./model/leaf/resnet-fold-{fold}.pth'torch.save(model.state_dict(),save_path)# Start Validationmodel.eval()valid_losses = []valid_accs = []with torch.no_grad():for batch in tqdm(validloader):imgs, labels = batch# No gradient in validationlogits = model(imgs.to(device))loss = loss_function(logits,labels.to(device))acc = (logits.argmax(dim=-1) == labels.to(device)).float().mean()# Record loss and accuracyvalid_losses.append(loss.item())        valid_accs.append(acc)# The average loss and accuracyvalid_loss = np.sum(valid_losses)/len(valid_losses)valid_acc = np.sum(valid_accs)/len(valid_accs)print(f"[ Valid | {epoch + 1:03d}/{num_epochs:03d} ] loss = {valid_loss:.5f}, acc = {valid_acc:.5f}")print('Accuracy for fold %d: %d' % (fold, valid_acc))print('--------------------------------------')results[fold] = valid_acc
# Print fold results
print(f'K-FOLD CROSS VALIDATION RESULTS FOR {k_folds} FOLDS')
print('--------------------------------')
total_summation = 0.0
for key, value in results.items():print(f'Fold {key}: {value} ')total_summation += value
print(f'Average: {total_summation/len(results.items())} ')
--------------------------------------
FOLD 0
--------------------------------------
...
--------------------------------------
K-FOLD CROSS VALIDATION RESULTS FOR 5 FOLDS
--------------------------------
Fold 0: 0.7646294236183167
Fold 1: 0.772324800491333
Fold 2: 0.7688811421394348
Fold 3: 0.7619268894195557
Fold 4: 0.7501959204673767
Average: 0.7635916471481323

1.3 模型预测

使用训练得到的五个模型进行预测结果,并将结果分别保存好

testloader = torch.utils.data.DataLoader(test_dataset,batch_size=64, num_workers=4)
## predict
model = resnet_model(176)# create model and load weights from checkpoint
model = model.to(device)
# load the all folds
for test_fold in range(k_folds):model_path = f'./model/leaf/model-fold-{test_fold}.pth'saveFileName = f'./kaggle_submission/leaf/submission-fold-{test_fold}.csv'model.load_state_dict(torch.load(model_path))# Make sure the model is in eval mode.# Some modules like Dropout or BatchNorm affect if the model is in training mode.model.eval()tta_model = tta.ClassificationTTAWrapper(model, tta.aliases.five_crop_transform(200,200)) # Test-Time Augmentation# Initialize a list to store the predictions.predictions = []# Iterate the testing set by batches.for batch in tqdm(testloader):imgs = batchwith torch.no_grad():logits = tta_model(imgs.to(device))# Take the class with greatest logit as prediction and record it.predictions.extend(logits.argmax(dim=-1).cpu().numpy().tolist())preds = []for i in predictions:preds.append(label_inv_map[i])test_data = pd.read_csv('./data/classify-leaves/test.csv')test_data['label'] = pd.Series(preds)submission = pd.concat([test_data['image'], test_data['label']], axis=1)submission.to_csv(saveFileName, index=False)print("ResNeSt Model Results Done!!!!!!!!!!!!!!!!!!!!!!!!!!!")
100%|██████████| 138/138 [01:08<00:00,  2.02it/s]ResNeSt Model Results Done!!!!!!!!!!!!!!!!!!!!!!!!!!!

1.4 利用K-Fold结果投票获取最终提交数据

加载预测结果

# load the result of 5-fold cross validation
df0 = pd.read_csv('./kaggle_submission/leaf/submission-fold-0.csv')
df1 = pd.read_csv('./kaggle_submission/leaf/submission-fold-1.csv')
df2 = pd.read_csv('./kaggle_submission/leaf/submission-fold-2.csv')
df3 = pd.read_csv('./kaggle_submission/leaf/submission-fold-3.csv')
df4 = pd.read_csv('./kaggle_submission/leaf/submission-fold-4.csv')
#convert the  result to a number
list_num_label0,list_num_label1,list_num_label2,list_num_label3,list_num_label4 = [],[],[],[],[]
for i in range(len(df0)):list_num_label0.append(label_map[df0['label'][i]])list_num_label1.append(label_map[df1['label'][i]]) list_num_label2.append(label_map[df2['label'][i]])list_num_label3.append(label_map[df3['label'][i]])list_num_label4.append(label_map[df4['label'][i]])
# concate all the data
df_all = df0.copy()
df_all.drop(['label'],axis=1,inplace=True)
df_all['num_label0'] = list_num_label0
df_all['num_label1'] = list_num_label1
df_all['num_label2'] = list_num_label2
df_all['num_label3'] = list_num_label3
df_all['num_label4'] = list_num_label4
df_all.head()
image num_label0 num_label1 num_label2 num_label3 num_label4
0 images/18353.jpg 22 22 22 22 22
1 images/18354.jpg 26 169 29 26 26
2 images/18355.jpg 120 120 120 120 120
3 images/18356.jpg 102 102 112 102 102
4 images/18357.jpg 121 120 120 121 120
# transpose the predict result (for calculate the mode of result easier)
df_all_transpose = df_all.copy().drop(['image'],axis=1).transpose()
df_all_transpose.head()
0 1 2 3 4 5 6 7 8 9 ... 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799
num_label0 22 26 120 102 121 74 84 91 165 169 ... 119 53 117 53 73 119 53 77 73 45
num_label1 22 169 120 102 120 74 83 91 165 170 ... 119 53 110 53 73 110 48 117 73 73
num_label2 22 29 120 112 120 74 83 91 165 169 ... 117 53 117 53 73 77 53 117 73 73
num_label3 22 26 120 102 121 74 50 91 165 169 ... 117 53 117 53 73 117 53 117 73 73
num_label4 22 26 120 102 120 74 83 91 165 169 ... 119 53 119 53 46 119 48 117 46 73

5 rows × 8800 columns

# vote the best result(mode)
df_mode = df_all_transpose.mode().transpose()
df_mode.head()
0 1 2 3 4
0 22.0 NaN NaN NaN NaN
1 26.0 NaN NaN NaN NaN
2 120.0 NaN NaN NaN NaN
3 102.0 NaN NaN NaN NaN
4 120.0 NaN NaN NaN NaN
# conver the best result back to text
voting_class = []
for each in df_mode[0]:voting_class.append(label_inv_map[each])
df_all['label'] = voting_class
df_all.head()
image num_label0 num_label1 num_label2 num_label3 num_label4 label
0 images/18353.jpg 22 22 22 22 22 asimina_triloba
1 images/18354.jpg 26 169 29 26 26 betula_nigra
2 images/18355.jpg 120 120 120 120 120 platanus_acerifolia
3 images/18356.jpg 102 102 112 102 102 pinus_bungeana
4 images/18357.jpg 121 120 120 121 120 platanus_acerifolia
# save the best result as csv
# choose columns image and lable as the result
df_submission = df_all[['image','label']].copy()
# save the the result file
df_submission.to_csv('./kaggle_submission/leaf/submission-resnet.csv', index=False)
print('Voting results of resnest successfully saved!')
Voting results of resnest successfully saved!

1.5 kaggle提交

2. resnext

2.1 resnext50_32x4d模型微调+冻结层

# 是否要冻住模型的前面一些层
def set_parameter_requires_grad(model, feature_extracting):if feature_extracting:model = modelfor param in model.parameters():param.requires_grad = False# resnext50_32x4d模型
def resnext_model(num_classes, feature_extract = False, use_pretrained=True):model_ft = torchvision.models.resnext50_32x4d(pretrained=use_pretrained)set_parameter_requires_grad(model_ft, feature_extract)num_ftrs = model_ft.fc.in_featuresmodel_ft.fc = nn.Sequential(nn.Linear(num_ftrs, num_classes))return model_ft
# Configuration options
k_folds = 5
num_epochs = 30
learning_rate = 1e-3
weight_decay = 1e-3
loss_function = nn.CrossEntropyLoss()
# For fold results
results = {}# Set fixed random number seed
torch.manual_seed(42)# Define the K-fold Cross Validator
kfold = KFold(n_splits=k_folds, shuffle=True)

2.2 五折交叉验证

# Start print
print('--------------------------------------')# K-fold Cross Validation model evaluation
for fold, (train_ids,valid_ids) in enumerate(kfold.split(train_dataset)):# Printprint(f'FOLD {fold}')print('--------------------------------------')# Sample elements randomly from a given list of ids, no replacement.train_subsampler = torch.utils.data.SubsetRandomSampler(train_ids)valid_subsampler = torch.utils.data.SubsetRandomSampler(valid_ids)# Define data loaders for training and testing data in this foldtrainloader = torch.utils.data.DataLoader(train_dataset,batch_size=64, sampler=train_subsampler, num_workers=4)validloader = torch.utils.data.DataLoader(train_dataset,batch_size=64, sampler=valid_subsampler, num_workers=4)# Initialize a model and put it on the device specified.model = resnext_model(176)model = model.to(device)model.device = device# Initialize optimizeroptimizer = torch.optim.Adam(model.parameters(),lr=learning_rate,weight_decay= weight_decay)#   optimizer = SWA(our_optimizer, swa_start=5, swa_freq =5, swa_lr=0.05)scheduler = CosineAnnealingLR(optimizer,T_max=10)# Run the training loop for defined number of epochsfor epoch in range(0,num_epochs):model.train()# Print epochprint(f'Starting epoch {epoch+1}')# These are used to record information in trainingtrain_losses = []train_accs = []# Iterate the training set by batchesfor batch in tqdm(trainloader):# Move images and labels to GPUimgs, labels = batchimgs = imgs.to(device)labels = labels.to(device)# Forward the datalogits = model(imgs)# Calculate lossloss = loss_function(logits,labels)# Clear gradients in previous stepoptimizer.zero_grad()# Compute gradients for parametersloss.backward()# Update the parameters with computed gradientsoptimizer.step()# Compute the accuracy for current batch.acc = (logits.argmax(dim=-1) == labels).float().mean()# Record the loss and accuracy.train_losses.append(loss.item())train_accs.append(acc)
#         print("第%d个epoch的学习率:%f" % (epoch+1,optimizer.param_groups[0]['lr']))scheduler.step()# The average loss and accuracy of the training set is the average of the recorded values.train_loss = np.sum(train_losses) / len(train_losses)train_acc = np.sum(train_accs) / len(train_accs)# Print the information.print(f"[ Train | {epoch + 1:03d}/{num_epochs:03d} ] loss = {train_loss:.5f}, acc = {train_acc:.5f}")
#     print(f"[ Train | {epoch + 1:03d}/{num_epochs:03d} ] loss = {train_loss:.5f}")# Train process (all epochs) is completeprint('Training process has finished. Saving trained model.')print('Starting validation')# Saving the modelprint('saving model with loss {:.3f}'.format(train_loss))save_path = f'./model/leaf/resneXt-fold-{fold}.pth'torch.save(model.state_dict(),save_path)# Start Validationmodel.eval()valid_losses = []valid_accs = []with torch.no_grad():for batch in tqdm(validloader):imgs, labels = batch# No gradient in validationlogits = model(imgs.to(device))loss = loss_function(logits,labels.to(device))acc = (logits.argmax(dim=-1) == labels.to(device)).float().mean()# Record loss and accuracyvalid_losses.append(loss.item())        valid_accs.append(acc)# The average loss and accuracyvalid_loss = np.sum(valid_losses)/len(valid_losses)valid_acc = np.sum(valid_accs)/len(valid_accs)print(f"[ Valid | {epoch + 1:03d}/{num_epochs:03d} ] loss = {valid_loss:.5f}, acc = {valid_acc:.5f}")print('Accuracy for fold %d: %d' % (fold, valid_acc))print('--------------------------------------')results[fold] = valid_acc
# Print fold results
print(f'K-FOLD CROSS VALIDATION RESULTS FOR {k_folds} FOLDS')
print('--------------------------------')
total_summation = 0.0
for key, value in results.items():print(f'Fold {key}: {value} ')total_summation += value
print(f'Average: {total_summation/len(results.items())} ')
--------------------------------------
FOLD 0
--------------------------------------
...
--------------------------------------
K-FOLD CROSS VALIDATION RESULTS FOR 5 FOLDS
--------------------------------
Fold 0: 0.7881605625152588
Fold 1: 0.7917798757553101
Fold 2: 0.807229220867157
Fold 3: 0.7923932075500488
Fold 4: 0.7697393894195557
Average: 0.7898604273796082

2.3 Resnext模型预测

testloader = torch.utils.data.DataLoader(test_dataset,batch_size=64, num_workers=4)
## predict
model = resnext_model(176)# create model and load weights from checkpoint
model = model.to(device)
# load the all folds
for test_fold in range(k_folds):model_path = f'./model/leaf/resneXt-fold-{test_fold}.pth'saveFileName = f'./kaggle_submission/leaf/resneXt-submission-fold-{test_fold}.csv'model.load_state_dict(torch.load(model_path))# Make sure the model is in eval mode.# Some modules like Dropout or BatchNorm affect if the model is in training mode.model.eval()tta_model = tta.ClassificationTTAWrapper(model, tta.aliases.five_crop_transform(200,200)) # Test-Time Augmentation# Initialize a list to store the predictions.predictions = []# Iterate the testing set by batches.for batch in tqdm(testloader):imgs = batchwith torch.no_grad():logits = tta_model(imgs.to(device))# Take the class with greatest logit as prediction and record it.predictions.extend(logits.argmax(dim=-1).cpu().numpy().tolist())preds = []for i in predictions:preds.append(label_inv_map[i])test_data = pd.read_csv('./data/classify-leaves/test.csv')test_data['label'] = pd.Series(preds)submission = pd.concat([test_data['image'], test_data['label']], axis=1)submission.to_csv(saveFileName, index=False)print("ResNeSt Model Results Done!!!!!!!!!!!!!!!!!!!!!!!!!!!")
100%|██████████| 138/138 [01:45<00:00,  1.31it/s]ResNeSt Model Results Done!!!!!!!!!!!!!!!!!!!!!!!!!!!

2.4 K-Fold模型投票获取最优解

# load the result of 5-fold cross validation
df0 = pd.read_csv('./kaggle_submission/leaf/resneXt-submission-fold-0.csv')
df1 = pd.read_csv('./kaggle_submission/leaf/resneXt-submission-fold-1.csv')
df2 = pd.read_csv('./kaggle_submission/leaf/resneXt-submission-fold-2.csv')
df3 = pd.read_csv('./kaggle_submission/leaf/resneXt-submission-fold-3.csv')
df4 = pd.read_csv('./kaggle_submission/leaf/resneXt-submission-fold-4.csv')
#convert the  result to a number
list_num_label0,list_num_label1,list_num_label2,list_num_label3,list_num_label4 = [],[],[],[],[]
for i in range(len(df0)):list_num_label0.append(label_map[df0['label'][i]])list_num_label1.append(label_map[df1['label'][i]]) list_num_label2.append(label_map[df2['label'][i]])list_num_label3.append(label_map[df3['label'][i]])list_num_label4.append(label_map[df4['label'][i]])
# concate all the data
df_all = df0.copy()
df_all.drop(['label'],axis=1,inplace=True)
df_all['num_label0'] = list_num_label0
df_all['num_label1'] = list_num_label1
df_all['num_label2'] = list_num_label2
df_all['num_label3'] = list_num_label3
df_all['num_label4'] = list_num_label4
df_all.head()
image num_label0 num_label1 num_label2 num_label3 num_label4
0 images/18353.jpg 22 22 22 22 22
1 images/18354.jpg 26 121 26 15 121
2 images/18355.jpg 120 120 120 120 120
3 images/18356.jpg 102 102 102 102 102
4 images/18357.jpg 120 120 120 120 120
# transpose the predict result (for calculate the mode of result easier)
df_all_transpose = df_all.copy().drop(['image'],axis=1).transpose()
df_all_transpose.head()
0 1 2 3 4 5 6 7 8 9 ... 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799
num_label0 22 26 120 102 120 74 83 91 165 169 ... 117 53 117 53 73 119 53 117 73 73
num_label1 22 121 120 102 120 74 83 91 165 169 ... 117 53 117 53 73 117 53 117 73 73
num_label2 22 26 120 102 120 74 50 91 165 169 ... 117 53 117 53 73 117 53 117 73 73
num_label3 22 15 120 102 120 74 83 91 165 169 ... 117 53 117 53 73 117 53 117 73 73
num_label4 22 121 120 102 120 74 83 91 165 169 ... 117 53 117 53 73 119 53 112 73 73

5 rows × 8800 columns

# vote the best result(mode)
df_mode = df_all_transpose.mode().transpose()
df_mode.head()
0 1 2 3 4
0 22.0 NaN NaN NaN NaN
1 26.0 121.0 NaN NaN NaN
2 120.0 NaN NaN NaN NaN
3 102.0 NaN NaN NaN NaN
4 120.0 NaN NaN NaN NaN
# conver the best result back to text
voting_class = []
for each in df_mode[0]:voting_class.append(label_inv_map[each])
df_all['label'] = voting_class
df_all.head()
image num_label0 num_label1 num_label2 num_label3 num_label4 label
0 images/18353.jpg 22 22 22 22 22 asimina_triloba
1 images/18354.jpg 26 121 26 15 121 betula_nigra
2 images/18355.jpg 120 120 120 120 120 platanus_acerifolia
3 images/18356.jpg 102 102 102 102 102 pinus_bungeana
4 images/18357.jpg 120 120 120 120 120 platanus_acerifolia
# save the best result as csv
# choose columns image and lable as the result
df_submission = df_all[['image','label']].copy()
# save the the result file
df_submission.to_csv('./kaggle_submission/leaf/submission-resneXt.csv', index=False)
print('Voting results of resnest successfully saved!')
Voting results of resnest successfully saved!

一言难尽这个模型的精度还没有resnet高,就不贴出来了

三、总结

  1. 数据增强对于数据量小的数据集训练特别重要
  2. 由于GPU受限,对原始数据做了小裁减很大程度上影响了我最终的精度。
  3. 对于数据的增强采用cutmix也是很好的方法
  4. resnet和resnext模型对于图片分类是应用非常广的模型。
  5. 微调模型是我们常用的方法,将类似的数据集中训练好的模型直接迁移过来可以极大地节省训练的时间和消耗,同时初始值更加符合数据的分布,更容易获得全局最优解。
  6. 使用K-Fold交叉验证,然后进行模型结果投票,得到的结果更加准确。当然也可以使用多个不同类型的模型的结果进行投票,这样得到的结果往往误差更小。

玩转Kaggle:Classify Leaves(叶子分类)——模型设计与训练相关推荐

  1. 李沐动手学深度学习V2-实战Kaggle比赛:叶子分类(Classify Leaves)和代码实现

    一. 叶子分类 预测叶子图像的类别,该数据集包含 176 个类别,18353 个训练图像,8800 个测试图像.每个类别至少有 50 张图像用于训练,测试集平均分为公共和私人排行榜,网址为:https ...

  2. 玩转Kaggle:Classify Leaves(叶子分类)——数据分析篇

    文章目录 一.Classify Leaves竞赛介绍 二.数据分析 2.1 训练数据信息统计和查看 2.2 测试数据统计和分析 2.3 可视化训练数据 三.整理 一.Classify Leaves竞赛 ...

  3. ML之xgboost:基于xgboost(5f-CrVa)算法对HiggsBoson数据集(Kaggle竞赛)训练实现二分类预测(基于训练好的模型进行新数据预测)

    ML之xgboost:基于xgboost(5f-CrVa)算法对HiggsBoson数据集(Kaggle竞赛)训练实现二分类预测(基于训练好的模型进行新数据预测) 目录 输出结果 设计思路 核心代码 ...

  4. ML之二分类预测:以岩石水雷数据集(RockMine)为例从0到1深入理解科学预测之分类问题的思路框架(特征工程详细步骤(特征分析与特征处理)+分类模型设计)

    ML之二分类预测:以岩石水雷数据集(RockMine)为例从0到1深入理解科学预测之分类问题的思路框架(特征工程详细步骤+分类模型设计) 目录 一.总体思路框架 二.特征工程详细步骤(特征分析与特征处 ...

  5. 【数据竞赛】kaggle竞赛宝典-多分类相关指标优化​

    ↑↑↑关注后"星标"kaggle竞赛宝典 kaggle竞赛宝典 作者: 尘沙杰少.谢嘉嘉.DOTA.有夕 赛题理解,分析,规划之多分类相关指标优化 这是一个系列篇,后续我们会按照我 ...

  6. 3.4 Kaggle自然场景图片分类

    3.4 Kaggle自然场景图片分类 自然场景识别数据集来自kaggle竞赛平台,最初是由Intel举办的一个图片分类竞赛数据集,它的训练集有14034张图片,测试集有3000张图片,未标注数据集有7 ...

  7. 简单分类模型设计与实现

    摘要:本Task通过训练DenseNet网络结构,对具有100个标签值的CIFAR-100图像分类数据集进行分类.DenseNet作为一种强大的CNN分类模型可以训练出更深的网络结构,得益于其密集连接 ...

  8. 在机器学习分类中如何处理训练集中不平衡问题

    版权声明:未经许可, 不能转载 目录(?)[-] 在分类中如何处理训练集中不平衡问题 Jason Brownlee的回答 什么是类别不均衡问题 类别不均衡问题是现实中很常见的问题 八大解决方法 选择某 ...

  9. 在分类中如何处理训练集中不平衡问题

    原文地址:一只鸟的天空,http://blog.csdn.net/heyongluoyao8/article/details/49408131 在分类中如何处理训练集中不平衡问题   在很多机器学习任 ...

最新文章

  1. Java子线程中的异常处理(通用)
  2. vSphere利用NTP为主机同步时间
  3. python 测试用例怎么输入两个_python selenium多个测试用例
  4. apache mysql python win10_Win10 MySQL-python
  5. 面试官:什么是对象池?有什么用?别说你还不会!
  6. iphone快捷指令蚂蚁森林能量_iPhone「快捷指令」怎么玩?玩法太多,别让这个功能吃灰...
  7. php里style标签,style标签怎么用?
  8. linux系统下能玩网页游戏下载软件,最适合玩游戏的Linux 系统
  9. Lua程序设计读书 随笔
  10. Python实现GWO智能灰狼优化算法优化支持向量机回归模型(svr算法)项目实战
  11. OnInitDialog()中SetFocus()不起作用解决方法
  12. keil 5 报错记录:..\OBJ\templiate.axf: Error: L6218E: Undefined symbol PcdHalt (referred from rc522.o).
  13. 【地理信息系统GIS专业的10个发展方向:】
  14. Golang的压测工具 hey
  15. 女巫煎蛋(omelette for a witch)
  16. 如何查看计算机在广域网的地址,如何知道本机当前局域网IP地址和广域网IP地址...
  17. CentOS7没有图形化界面,怎么安装图形化界面
  18. 摄影笔记一:《李元谈摄影修炼之道》
  19. python3 采集 中国天气网 七天预报和当天生活指数
  20. 浅谈软件开发者应具备的基本素质

热门文章

  1. 司新颖:当番茄遭遇鸡蛋
  2. G-LAB有CCNP题库服务么?
  3. FCPX插件:屏幕分屏特效插件Stupid Raisins Split Pop
  4. 说明T1线路的传输速率是1.544Mbps
  5. 侃一侃人工智能2-零散的人工智能概念
  6. 我挑了 10 本数据库类好书,来送你
  7. ICAP client 获取ICAP server 的Options
  8. Armijo-Goldstein法则和Wolfe-power法则图解
  9. 轻量快速的CI工具Drone快速入门
  10. 搭建无线监控云存储服务器,mac 篇二:自建docker视频录像机NVR存储-家用摄像头云存储服务zoneminder...