基于Kaggle的图像分类(CIFAR-10)

Image Classification (CIFAR-10) on Kaggle

一直在使用Gluon’s data package数据包直接获得张量格式的图像数据集。然而,在实际应用中,图像数据集往往以图像文件的形式存在。将从原始图像文件开始,逐步组织、读取并将文件转换为张量格式。对CIFAR-10数据集进行了一个实验。这是计算机视觉领域的一个重要数据集。现在,将应用前面几节中所学的知识来参加Kaggle竞赛,该竞赛解决CIFAR-10图像分类问题。

比赛的网址是https://www.kaggle.com/c/cifar-10

图1显示了比赛网页上的信息。为了提交结果,请先在Kaggle网站注册一个帐户。

Fig. 1 CIFAR-10 image classification competition webpage
information. The dataset for the competition can be accessed by clicking the “Data” tab.

首先,导入比赛所需的软件包或模块。

import collections

from d2l
import mxnet as d2l

import math

from mxnet
import autograd, gluon, init, npx

from mxnet.gluon
import nn

import os

import pandas
as pd

import shutil

import time

npx.set_np()

  1. Obtaining and Organizing the Dataset

比赛数据分为训练集和测试集。训练集包含50000帧图像。测试集包含30万帧图像,其中10000帧图像用于评分,而其29万帧包括非评分图像,以防止手动标记测试集和提交标记结果。两个数据集中的图像格式都是PNG,高度和宽度都是32个像素和三个颜色通道(RGB)。图像覆盖1010类别:飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船和卡车。图中左上角显示了数据集中飞机、汽车和鸟类的一些图像。

1.1. Downloading the Dataset

登录Kaggle后,点击图1所示CIFAR-10图像分类竞赛网页上的“数据”选项卡,点击“全部下载”按钮下载数据集。在…/data中解压缩下载的文件,并在其中解压缩train.7z和test.7z之后,将在以下路径中找到整个数据集:
· …/data/cifar-10/train/[1-50000].png

· …/data/cifar-10/test/[1-300000].png

· …/data/cifar-10/trainLabels.csv

· …/data/cifar-10/sampleSubmission.csv

这里的“训练”和“测试”文件夹分别包含训练和测试图像,trainLabels.csv有训练图像的标签和sample_submission.csv是提交的样本。为了便于入门,提供了一个小规模的数据集示例:包含第一个1000帧训练图像和55随机测试图像。要使用Kaggle竞赛的完整数据集,需要将以下demo变量设置为False。

#@save

d2l.DATA_HUB[‘cifar10_tiny’] = (d2l.DATA_URL
‘kaggle_cifar10_tiny.zip’,

‘2068874e4b9a9f0fb07ebe0ad2b29754449ccacd’)

# If you use the full dataset downloaded for the Kaggle
competition, set the

# demo variable to False

demo = True

if demo:

data_dir = d2l.download_extract('cifar10_tiny')

else:

data_dir = ‘…/data/cifar-10/’

1.2. Organizing the Dataset

需要组织数据集来促进模型的训练和测试。让首先从csv文件中读取标签。以下函数返回一个字典,该字典将不带扩展名的文件名映射到其标签。

#@save

def read_csv_labels(fname):

"""Read

fname to return a name to label dictionary."""

with open(fname, 'r')

as f:
# Skip the file header line (column name)

    lines = f.readlines()[1:]tokens = [l.rstrip().split(',') for l in lines]return

dict(((name, label) for name, label in tokens))

labels = read_csv_labels(os.path.join(data_dir, ‘trainLabels.csv’))

print(’#training examples:’, len(labels))

print(’# classes:’, len(set(labels.values())))

# training examples: 1000
# classes: 10

接下来,定义reorg_train_valid函数来从原始训练集中分割验证集。此函数中的参数valid_ratio是验证集中的示例数与原始训练集中的示例数的比率。特别是让n是具有最少示例的类的图像数,以及r是比率,那么将使用最大值(⌊nr⌋,1),每个类的图像作为验证集。让以valid_ratio=0.1为例。从最初的训练开始50000帧图像,会有45000帧。当调整超参数时,用于训练并存储在路径“train_valid_test/train”中的图像,而另一个5000帧图像将作为验证集存储在“train_valid_test/train”路径中。组织好数据后,同一类的图像将被放在同一个文件夹下,以便以后阅读。

#@save

def copyfile(filename, target_dir):

"""Copy a file into a target directory."""d2l.mkdir_if_not_exist(target_dir)shutil.copy(filename, target_dir)

#@save

def reorg_train_valid(data_dir, labels, valid_ratio):

# The number of examples of the class with the least examples in the# training datasetn = collections.Counter(labels.values()).most_common()[-1][1]# The number of examples per class for the validation setn_valid_per_label = max(1, math.floor(n * valid_ratio))label_count = {}for train_file in os.listdir(os.path.join(data_dir, 'train')):label = labels[train_file.split('.')[0]]fname = os.path.join(data_dir, 'train', train_file)# Copy to train_valid_test/train_valid with a subfolder per classcopyfile(fname, os.path.join(data_dir, 'train_valid_test','train_valid', label))if label not in label_count or label_count[label] < n_valid_per_label:# Copy to train_valid_test/validcopyfile(fname, os.path.join(data_dir, 'train_valid_test','valid', label))label_count[label] = label_count.get(label, 0) + 1else:# Copy to train_valid_test/traincopyfile(fname, os.path.join(data_dir, 'train_valid_test','train', label))return n_valid_per_label

下面的reorg_test函数用于组织测试集,以便于预测期间的读数。

#@save

def reorg_test(data_dir):

for test_file in os.listdir(os.path.join(data_dir, 'test')):copyfile(os.path.join(data_dir, 'test', test_file),os.path.join(data_dir, 'train_valid_test', 'test','unknown'))

使用一个函数来调用先前定义的read_csv_labels、reorg_train_valid和reorg_test函数。

def reorg_cifar10_data(data_dir, valid_ratio):

labels = read_csv_labels(os.path.join(data_dir, 'trainLabels.csv'))reorg_train_valid(data_dir, labels, valid_ratio)

reorg_test(data_dir)

只将批量大小设置1为演示数据集。在实际训练和测试过程中,应使用Kaggle竞赛的完整数据集,并将批次大小设置为更大的整数,例如128。使用10%作为调整超参数的验证集。

batch_size = 1 if demo else 128

valid_ratio = 0.1

reorg_cifar10_data(data_dir, valid_ratio)

  1. Image Augmentation

为了解决过度拟合的问题,使用图像增强技术。例如,通过添加transforms.RandomFlipLeftRight(),图像可以随机翻转。还可以使用transforms.Normalize()。下面,将列出其中一些操作,可以根据需要选择使用或修改这些操作。

transform_train = gluon.data.vision.transforms.Compose([

# Magnify the image to a square of 40 pixels in both height and widthgluon.data.vision.transforms.Resize(40),# Randomly crop a square image of 40 pixels in both height and width to# produce a small square of 0.64 to 1 times the area of the original# image, and then shrink it to a square of 32 pixels in both height and# widthgluon.data.vision.transforms.RandomResizedCrop(32, scale=(0.64, 1.0),ratio=(1.0, 1.0)),gluon.data.vision.transforms.RandomFlipLeftRight(),gluon.data.vision.transforms.ToTensor(),# Normalize each channel of the imagegluon.data.vision.transforms.Normalize([0.4914, 0.4822, 0.4465],[0.2023, 0.1994, 0.2010])])

为了保证测试过程中输出的确定性,只对图像进行归一化处理。

transform_test = gluon.data.vision.transforms.Compose([

gluon.data.vision.transforms.ToTensor(),gluon.data.vision.transforms.Normalize([0.4914, 0.4822, 0.4465],[0.2023, 0.1994, 0.2010])])
  1. Reading the Dataset

接下来,可以创建ImageFolderDataset实例来读取包含原始图像文件的有组织的数据集,其中每个示例都包含图像和标签。

train_ds, valid_ds, train_valid_ds, test_ds = [

gluon.data.vision.ImageFolderDataset(os.path.join(data_dir, 'train_valid_test', folder))

for folder in [‘train’, ‘valid’, ‘train_valid’, ‘test’]]

在DataLoader中指定定义的图像增强操作。在训练过程中,只使用验证集来评估模型,所以需要确保输出的确定性。在预测过程中,将在组合训练集和验证集上训练模型,以充分利用所有标记数据。

train_iter, train_valid_iter = [gluon.data.DataLoader(

dataset.transform_first(transform_train), batch_size, shuffle=True,last_batch='keep') for dataset in (train_ds, train_valid_ds)]

valid_iter, test_iter = [gluon.data.DataLoader(

dataset.transform_first(transform_test), batch_size, shuffle=False,last_batch='keep') for dataset in (valid_ds, test_ds)]
  1. Defining the Model

基于HybridBlock类构建剩余块,这样做是为了提高执行效率。

class Residual(nn.HybridBlock):

def __init__(self, num_channels, use_1x1conv=False, strides=1, **kwargs):super(Residual, self).__init__(**kwargs)self.conv1 = nn.Conv2D(num_channels, kernel_size=3, padding=1,strides=strides)self.conv2 = nn.Conv2D(num_channels, kernel_size=3, padding=1)if use_1x1conv:self.conv3 = nn.Conv2D(num_channels, kernel_size=1,strides=strides)else:self.conv3 = Noneself.bn1 = nn.BatchNorm()self.bn2 = nn.BatchNorm()def hybrid_forward(self, F, X):Y = F.npx.relu(self.bn1(self.conv1(X)))Y = self.bn2(self.conv2(Y))if self.conv3:X = self.conv3(X)return F.npx.relu(Y + X)

定义ResNet-18模型。

def resnet18(num_classes):

net = nn.HybridSequential()net.add(nn.Conv2D(64, kernel_size=3, strides=1, padding=1),nn.BatchNorm(), nn.Activation('relu'))def resnet_block(num_channels, num_residuals, first_block=False):blk = nn.HybridSequential()for i in range(num_residuals):if i == 0 and not first_block:blk.add(Residual(num_channels, use_1x1conv=True, strides=2))else:blk.add(Residual(num_channels))return blknet.add(resnet_block(64, 2, first_block=True),resnet_block(128, 2),resnet_block(256, 2),resnet_block(512, 2))net.add(nn.GlobalAvgPool2D(), nn.Dense(num_classes))return net

CIFAR-10图像分类挑战赛使用10个类别。在训练开始之前,将对模型执行Xavier随机初始化。

def get_net(ctx):

num_classes = 10net = resnet18(num_classes)net.initialize(ctx=ctx, init=init.Xavier())return net

loss = gluon.loss.SoftmaxCrossEntropyLoss()

  1. Defining the Training Functions

将根据模型在验证集上的性能来选择模型并调整超参数。其次,定义了模型训练函数训练。记录了每个时代的训练时间,这有助于比较不同模型的时间成本。

def train(net, train_iter, valid_iter, num_epochs, lr, wd, ctx, lr_period,

      lr_decay):trainer = gluon.Trainer(net.collect_params(), 'sgd',{'learning_rate': lr, 'momentum': 0.9, 'wd': wd})for epoch in range(num_epochs):train_l_sum, train_acc_sum, n, start = 0.0, 0.0, 0, time.time()if epoch > 0 and epoch % lr_period == 0:trainer.set_learning_rate(trainer.learning_rate * lr_decay)for X, y in train_iter:y = y.astype('float32').as_in_ctx(ctx)with autograd.record():y_hat = net(X.as_in_ctx(ctx))l = loss(y_hat, y).sum()l.backward()trainer.step(batch_size)train_l_sum += float(l)train_acc_sum += float((y_hat.argmax(axis=1) == y).sum())n += y.sizetime_s = "time %.2f sec" % (time.time() - start)if valid_iter is not None:valid_acc = d2l.evaluate_accuracy_gpu(net, valid_iter)epoch_s = ("epoch %d, loss %f, train acc %f, valid acc %f, "% (epoch + 1, train_l_sum / n, train_acc_sum / n,valid_acc))else:epoch_s = ("epoch %d, loss %f, train acc %f, " %(epoch + 1, train_l_sum / n, train_acc_sum / n))print(epoch_s + time_s + ', lr ' + str(trainer.learning_rate))
  1. Training and Validating the Model

现在可以对模型进行验证。可以调整以下超参数。例如,可以增加纪元的数量。由于lr_period和lr_decay分别设置为80和0.1,因此每80个周期后,优化算法的学习速率将乘以0.1。为了简单起见,在这里只训练了一个时代。

ctx, num_epochs, lr, wd = d2l.try_gpu(), 1, 0.1, 5e-4

lr_period, lr_decay, net = 80, 0.1, get_net(ctx)

net.hybridize()

train(net, train_iter, valid_iter, num_epochs, lr, wd, ctx, lr_period,

  lr_decay)

epoch 1, loss 2.859060, train acc 0.100000, valid acc 0.100000, time 9.51 sec, lr 0.1

  1. Classifying the Testing Set and Submitting Results on Kaggle

在获得满意的模型设计和超参数后,使用所有训练数据集(包括验证集)对模型进行再训练并对测试集进行分类。

net, preds = get_net(ctx), []

net.hybridize()

train(net, train_valid_iter, None, num_epochs, lr, wd, ctx, lr_period,

  lr_decay)

for X, _ in test_iter:

y_hat = net(X.as_in_ctx(ctx))preds.extend(y_hat.argmax(axis=1).astype(int).asnumpy())

sorted_ids = list(range(1, len(test_ds) + 1))

sorted_ids.sort(key=lambda x: str(x))

df = pd.DataFrame({‘id’: sorted_ids, ‘label’: preds})

df[‘label’] = df[‘label’].apply(lambda x: train_valid_ds.synsets[x])

df.to_csv(‘submission.csv’, index=False)

epoch 1, loss 2.873863, train acc 0.106000, time 9.55 sec, lr 0.1

执行上述代码后,将得到一个“submission.csv “文件。此文件的格式符合Kaggle竞赛要求。

  1. Summary

We can create an ImageFolderDataset instance to read the dataset containing the original image files.
We can use convolutional neural networks, image augmentation, and hybrid programming to take part in an image classification competition.

基于Kaggle的图像分类(CIFAR-10)相关推荐

  1. 【项目实战课】人人免费可学!基于Pytorch的图像分类简单任务数据增强实战

    欢迎大家来到我们的项目实战课,本期内容是<基于Pytorch的图像分类简单任务数据增强实战>.所谓项目实战课,就是以简单的原理回顾+详细的项目实战的模式,针对具体的某一个主题,进行代码级的 ...

  2. Python 计算机视觉(十七)—— 基于KNN的图像分类

    参考的一些文章以及论文我都会给大家分享出来 -- 链接就贴在原文,论文我上传到资源中去,大家可以免费下载学习,如果当天资源区找不到论文,那就等等,可能正在审核,审核完后就可以下载了.大家一起学习,一起 ...

  3. numpy找到矩阵中不同元素的种类_基于NumPy和图像分类的人工神经网络构建

    基于NumPy和图像分类的人工神经网络构建 本文利用NumPy系统在Python中构建人工神经网络,以便为Fruits360数据集执行图像分类应用程序. 本文提及的所有内容(即图像和源代码,不包括Fr ...

  4. 基于pytorch实现图像分类——理解自动求导、计算图、静态图、动态图、pytorch入门

    1. pytorch入门 什么是PYTORCH? 这是一个基于Python的科学计算软件包,针对两组受众: 替代NumPy以使用GPU的功能 提供最大灵活性和速度的深度学习研究平台 1.1 开发环境 ...

  5. 毕业设计 - 基于人工智能的图像分类算法研究与实现 - 深度学习卷积神经网络图像分类

    文章目录 0 简介 1 常用的分类网络介绍 1.1 CNN 1.2 VGG 1.3 GoogleNet 2 图像分类部分代码实现 2.1 环境依赖 2.2 需要导入的包 2.3 参数设置(路径,图像尺 ...

  6. 基于Kaggle心脏病数据集的数据分析和分类预测-StatisticalLearning统计学习实验报告

    基于Kaggle心脏病数据集的数据分析和分类预测-StatisticalLearning统计学习实验报告 一.实验准备 本数据来源于kaggle,包含14个维度,303个样本,具体的变量说明如下表所示 ...

  7. 基于MegEngine实现图像分类【附部分源码及模型】

    文章目录 前言 图像分类发展史及意义 一.数据集的准备 1.数据集描述 2.数据集准备 二.基于MegEngine的图像分类框架构建 1.引入库 2.CPU/GPU配置 3.设置模型字典 4.解析数据 ...

  8. 基于Python的图像分类 项目实践——图像分类项目的指导文档

    基于Python的图像分类 项目实践--图像分类项目https://blog.csdn.net/aiqq136/article/details/114597818 第一节 实践环境和项目初识 一.采用 ...

  9. 图像检索:几类基于内容的图像分类技术

    FROM: http://blog.csdn.net/leixiaohua1020/article/details/16847823 一共有四种基于内容的图像分类方法,即颜色.纹理.形状和空间关系. ...

最新文章

  1. android 如何把回调赋值另一个_android 两个界面回调实现
  2. 控制台输出覆盖当前行显示
  3. 设计模式[20]-Builder
  4. HDU 1565 状态压缩
  5. 【推荐系统(二)】协同过滤之隐语义模型(LFM)
  6. Web框架——Flask系列之设置和读取cookie(十五)
  7. rotateleft_Java Integer类rotateLeft()方法与示例
  8. Aspose填充word数据
  9. 【clickhouse】clickhouse 如何实现tcp方式发送数据
  10. 使用dataadapter和dataset更新数据库
  11. 南阳理工oj 题目26 孪生素数问题 素数筛选法
  12. 博客首页全新改版;博客代码片支持折叠;原创博文新增打赏功能……【2022.1.17】
  13. Win10搜索框图案有广告的解决办法
  14. 草图大师(2018)
  15. python浙江大学出版社_大学计算机公共基础课如何改革?浙江高校积极探索以Python课程为主导的教学实践...
  16. 论“詹姆斯*哈登”到底是不是球队毒瘤
  17. 同义词转换不再有效_中考英语丨初中英语句型转换大全
  18. PHP开发环境的搭建
  19. 用于跑深度学习的嵌入式硬件平台资料整理(一)
  20. 第十一届蓝桥杯C++国赛C题:阶乘约数(唯一分解)

热门文章

  1. 【ReactiveX】基于Golang pmlpml/RxGo程序包的二次开发
  2. Go 学习笔记(68)— goroutine 并发控制神器 Context
  3. 经济独立,是你最大的底气
  4. 经历能让人变得更理智更成熟
  5. GPT3 api接口调用
  6. PyTorch学习之六个学习率调整策略
  7. 命名实体识别入门教程(必看)
  8. LeetCode简单题之设计停车系统
  9. TVM,Relay,Pass
  10. 对端边缘云网络计算模式:透明计算、移动边缘计算、雾计算和Cloudlet