Kaggle上的狗品种识别(ImageNet Dogs)

您所在的位置:网站首页 狗品种搜索 Kaggle上的狗品种识别(ImageNet Dogs)

Kaggle上的狗品种识别(ImageNet Dogs)

2024-07-10 09:25| 来源: 网络整理| 查看: 265

Kaggle上的狗品种识别(ImageNet Dogs) 在本节中,我们将解决Kaggle竞赛中的犬种识别挑战,比赛的网址是https://www.kaggle.com/c/dog-breed-identification 在这项比赛中,我们尝试确定120种不同的狗。该比赛中使用的数据集实际上是著名的ImageNet数据集的子集。

In [1]:

import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms import torchvision.models as models import os import shutil import time import pandas as pd import random

In [2]:

设置随机数种子 random.seed(0) torch.manual_seed(0) torch.cuda.manual_seed(0) 整理数据集

我们可以从比赛网址上下载数据集,其目录结构为:

| Dog Breed Identification | train | | 000bec180eb18c7604dcecc8fe0dba07.jpg | | 00a338a92e4e7bf543340dc849230e75.jpg | | … | test | | 00a3edd22dc7859c487a64777fc8d093.jpg | | 00a6892e5c7f92c1f465e213fd904582.jpg | | … | labels.csv | sample_submission.csv

train和test目录下分别是训练集和测试集的图像,训练集包含10,222张图像,测试集包含10,357张图像,图像格式都是JPEG,每张图像的文件名是一个唯一的id。labels.csv包含训练集图像的标签,文件包含10,222行,每行包含两列,第一列是图像id,第二列是狗的类别。狗的类别一共有120种。

我们希望对数据进行整理,方便后续的读取,我们的主要目标是:

从训练集中划分出验证数据集,用于调整超参数。划分之后,数据集应该包含4个部分:划分后的训练集、划分后的验证集、完整训练集、完整测试集 对于4个部分,建立4个文件夹:train, valid, train_valid, test。在上述文件夹中,对每个类别都建立一个文件夹,在其中存放属于该类别的图像。前三个部分的标签已知,所以各有120个子文件夹,而测试集的标签未知,所以仅建立一个名为unknown的子文件夹,存放所有测试数据。 我们希望整理后的数据集目录结构为:

| train_valid_test | train | | affenpinscher | | | 00ca18751837cd6a22813f8e221f7819.jpg | | | … | | afghan_hound | | | 0a4f1e17d720cdff35814651402b7cf4.jpg | | | … | | … | valid | | affenpinscher | | | 56af8255b46eb1fa5722f37729525405.jpg | | | … | | afghan_hound | | | 0df400016a7e7ab4abff824bf2743f02.jpg | | | … | | … | train_valid | | affenpinscher | | | 00ca18751837cd6a22813f8e221f7819.jpg | | | … | | afghan_hound | | | 0a4f1e17d720cdff35814651402b7cf4.jpg | | | … | | … | test | | unknown | | | 00a3edd22dc7859c487a64777fc8d093.jpg | | | …

In [3]:

data_dir = '/home/kesci/input/Kaggle_Dog6357/dog-breed-identification' # 数据集目录 label_file, train_dir, test_dir = 'labels.csv', 'train', 'test' # data_dir中的文件夹、文件 new_data_dir = './train_valid_test' # 整理之后的数据存放的目录 valid_ratio = 0.1 # 验证集所占比例

In [4]:

def mkdir_if_not_exist(path): # 若目录path不存在,则创建目录 if not os.path.exists(os.path.join(*path)): os.makedirs(os.path.join(*path)) def reorg_dog_data(data_dir, label_file, train_dir, test_dir, new_data_dir, valid_ratio): # 读取训练数据标签 labels = pd.read_csv(os.path.join(data_dir, label_file)) id2label = {Id: label for Id, label in labels.values} # (key: value): (id: label) # 随机打乱训练数据 train_files = os.listdir(os.path.join(data_dir, train_dir)) random.shuffle(train_files) # 原训练集 valid_ds_size = int(len(train_files) * valid_ratio) # 验证集大小 for i, file in enumerate(train_files): img_id = file.split('.')[0] # file是形式为id.jpg的字符串 img_label = id2label[img_id] if i 0 and epoch % lr_period == 0: # 每lr_period个epoch,学习率衰减一次 lr = lr * lr_decay for param_group in optimizer.param_groups: param_group['lr'] = lr for X, y in train_iter: X, y = X.to(device), y.to(device) optimizer.zero_grad() y_hat = net(X) l = loss(y_hat, y) l.backward() optimizer.step() train_l_sum += l.item() * y.shape[0] n += y.shape[0] time_s = "time %.2f sec" % (time.time() - start) if valid_iter is not None: valid_loss, valid_acc = evaluate_loss_acc(valid_iter, net, device) epoch_s = ("epoch %d, train loss %f, valid loss %f, valid acc %f, " % (epoch + 1, train_l_sum / n, valid_loss, valid_acc)) else: epoch_s = ("epoch %d, train loss %f, " % (epoch + 1, train_l_sum / n)) print(epoch_s + time_s + ', lr ' + str(lr)) 调参

In [12]:

num_epochs, lr_period, lr_decay = 20, 10, 0.1 lr, wd = 0.03, 1e-4 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') net = get_net(device) train(net, train_iter, valid_iter, num_epochs, lr, wd, device, lr_period, lr_decay) 在完整数据集上训练模型

In [14]:

# 使用上面的参数设置,在完整数据集上训练模型大致需要40-50分钟的时间 net = get_net(device) train(net, train_valid_iter, None, num_epochs, lr, wd, device, lr_period, lr_decay) 对测试集分类并提交结果

用训练好的模型对测试数据进行预测。比赛要求对测试集中的每张图片,都要预测其属于各个类别的概率。

In [15]:

preds = [] for X, _ in test_iter: X = X.to(device) output = net(X) output = torch.softmax(output, dim=1) preds += output.tolist() ids = sorted(os.listdir(os.path.join(new_data_dir, 'test/unknown'))) with open('submission.csv', 'w') as f: f.write('id,' + ','.join(train_valid_ds.classes) + '\n') for i, output in zip(ids, preds): f.write(i.split('.')[0] + ',' + ','.join( [str(num) for num in output]) + '\n')


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3