在上一篇文章《深度学习中超大规模数据集的处理》中讲到采用HDF5文件处理大规模数据集。有朋友问到:HDF5文件是一次性读入内存中,然后通过键进行访问吗?答案当然不是,在前面的文章中也提到过,最后生成的train.hdf5文件高达30G,如果全部加载到内存,内存会撑爆。实际上,由于HDF5采用了特殊的文件格式,这样我们可以在一次读操作中加载一个批量(比如128)的图片,而不用一个个的读取。也就是说采用这种方式,只是减少了IO操作次数,另外加载的图片是RAW图像数据,减少了解码时间。

在这篇文章中,我们将说明如何读取HDF5文件,从头实现一个AlexNet网络模型。掌握了这些知识,你也可以去挑战一下Kaggle竞赛。需要指出的是,在ImageNet超大规模数据集上训练,特别是深度模型,非常耗时!!!周末在我的机器(配置为CPU: i7 6700, GPU: GTX960, MEM: 8G)上从头训练AlexNet模型,一个Epoch下来,都要花上一天的时间,结果搭上整个周末,也就跑了两个Epoch,更别提对比使用HDF5文件前后的效果。看样子该升级一下机器配置:(

图像预处理

在实现AlexNet网络模型之前,先介绍几个图像预处理方法,这些预处理在计算机视觉深度学习中应用十分广泛,可以有效的提高图像分类的准确率。

  • 均值减法(mean subtraction)

    在上一篇文章中,在处理图像文件的过程中,计算了所有图像的RGB通道的均值。而所谓的均值减法预处理就是将图像的每个像素点RGB通道值减去对应通道的均值,简单说,公式如下:

    比如一张狗狗的图片,经过均值预处理,得到了右边的图像。

    均值减法是一种数据归一化技巧,可以减少光线变化造成的影响。

    借助于opencv的处理函数,实现均值减法非常简单:

    (B, G, R) = cv2.split(image.astype("float32"))# subtract the means for each channelR -= self.r_meanG -= self.g_meanB -= self.b_mean# merge the channels back and return the imagereturn cv2.merge([B, G, R])
  • 切片(patch)

    切片预处理就是在训练过程中随机截取图像M x N区域内的像素值。我们知道,CNN模型要求图像输入尺寸是一个固定值,如果我们使用的图像大小和输入尺寸不一致,通常的处理方法是对图像进行缩放。但是,如果使用的图像比输入尺寸大,还有一种更好的方法就是进行随机截取部分图像,这可以有效的降低过拟合。

    上图中,随机裁剪256x256的图像到227x227大小。因为是随机裁剪,所以网络每次训练的图像不同,相当于一种数据扩充技术,可以减少过拟合。

    我们也不需要从头实现,借助与sklearn中的实用函数,一句话就可以搞定:

  def preprocess(self, image):# extract a random crop from the image with the target width and heightreturn extract_patches_2d(image, (self.width, self.height), max_patches=1)[0]
  • 裁切(cropp)

    裁切预处理有点类似上面的切片预处理。不过有两点不同:

    1. 本预处理应用于验证数据集,而切片预处理应用在训练数据上。
    2. 本预处理固定截取4个角及正中间区域,在加上水平翻转,这样每张图片可以得到10张采样。

    还记得《提高模型准确率:组合模型》这篇文章讲到,通过组合多个网络的输出可以提高分类准确率,这里就是计算10张采样的分类概率平均值,从而达到提高分类准确率的效果。

    该预处理没有现成的函数可用,不过写起来也不难:

  def preprocess(self, image):crops = []# grab the width and height of the image then use these dimensions to# define the corners of the image based(h, w) = image[:2]coords = [[0, 0, self,width, self.height],[w - self.width, 0, w, self.height],[w - self.width, h - self.height, w, h],[0, h - self.height, self.width, h]]# compute the center crop of the image as welldw = int(0.5 * (w - self.width))dh = int(0.5 * (h - self.height))coords.append([dw, dh, w - dw, h - dh])for (startx, starty, endx, endy) in coords:crop = image[startx:endx, starty:endy]crop = cv2.resize(crop, (self.width, self.height), interpolation=self.inter)crops.append(crop)if self.horiz:# compute the horizontal mirror flips for each cropmirrors = [cv2.flip(c, 1) for c in crops]crops.extend(mirrors)return np.array(crops)

HDF5数据集生成器

《深度学习中超大规模数据集的处理》中,我们将数据集存成HDF5文件格式,这里,我们需要从HDF5文件中按照批次读取图像数据及类别标签。

      # loop over the HDF5 datasetfor i in np.arange(0, self.num_images, self.batch_size):# extract the images and labels from HDF5 datasetimages = self.db["images"][i : i + self.batch_size]labels = self.db["labels"][i : i + self.batch_size]if self.binarize:labels = np_utils.to_categorical(labels, self.classes)if self.preprocessors is not None:proc_images = []for image in images:for p in self.preprocessors:image = p.preprocess(image)proc_images.append(image)images = np.array(proc_images)

每次读取batch_size个图像数据和类别标签,并进行预处理,代码中对images和labels的访问有点类似数组,[i : i + self.batch_size]读取第i到第(i+batch_size)个元素。

AlexNet

相对于我们之前实现的深度学习模型,AlexNet相当复杂,图的层如下表所示:

当AlexNet首次提出来时,还没有出现批量归一化等技术。在实现中,我们将在激活后加入批量归一化,对于使用卷积神经网络的大多数图像分类任务而言,这是非常标准的处理。另外,我们还会在每次POOL操作后做一些dropout,以进一步减少过拟合。

在前面的文章中,我们已经见识过keras的简洁之处,即使是AlexNet这样复杂的网络,对keras而言只是多几行代码而已。

class AlexNet:@staticmethoddef build(width, height, depth, classes, reg=0.0002):model = Sequential()input_shape = (width, height, depth)channel_dim = -1if K.image_data_format() == "channels_first":input_shape = (depth, width, height)channel_dim = 1# block #1: CONV => RELU => POOLmodel.add(Conv2D(96, (11, 11), strides=(4, 4), input_shape=input_shape,padding="same", kernel_regularizer=l2(reg)))model.add(Activation("relu"))model.add(BatchNormalization(axis=channel_dim))model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))model.add(Dropout(0.25))# block #2: CONV => RELU => POOLmodel.add(Conv2D(256, (5, 5),padding="same", kernel_regularizer=l2(reg)))model.add(Activation("relu"))model.add(BatchNormalization(axis=channel_dim))model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))model.add(Dropout(0.25))# block #3: CONV => RELU => CONV => RELU => CONV => RELU => POOLmodel.add(Conv2D(384, (3, 3),padding="same", kernel_regularizer=l2(reg)))model.add(Activation("relu"))model.add(BatchNormalization(axis=channel_dim))model.add(Conv2D(384, (3, 3),padding="same", kernel_regularizer=l2(reg)))model.add(Activation("relu"))model.add(BatchNormalization(axis=channel_dim))model.add(Conv2D(256, (3, 3),padding="same", kernel_regularizer=l2(reg)))model.add(Activation("relu"))model.add(BatchNormalization(axis=channel_dim))model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))model.add(Dropout(0.25))# block #4: FC => RELUmodel.add(Flatten())model.add(Dense(4096, kernel_regularizer=l2(reg)))model.add(Activation("relu"))model.add(BatchNormalization())model.add(Dropout(0.5))# block #5: FC => RELUmodel.add(Dense(4096, kernel_regularizer=l2(reg)))model.add(Activation("relu"))model.add(BatchNormalization())model.add(Dropout(0.5))# softmax classifiermodel.add(Dense(classes, kernel_regularizer=l2(reg)))model.add(Activation("softmax"))return model

接下来就是训练和测试模型,对于深度学习而言,不管是复杂还是简单的模型,其训练和测试过程都是大同小异,所以在这里我也不再罗嗦,有兴趣的同学可以参考我在github上的完整代码。但是需要注意,这个训练非常耗时,如果没有极其牛的显卡,还是不要轻易尝试。其实对于图片分类任务来说,最好还是采用迁移学习,站在巨人的肩膀上,不仅省力,效果还更好一些。

以上实例均有完整的代码,点击阅读原文,跳转到我在github上建的示例代码。
另外,我在阅读《Deep Learning for Computer Vision with Python》这本书,在微信公众号后台回复“计算机视觉”关键字,可以免费下载这本书的电子版。

往期回顾

  1. 深度学习中超大规模数据集的处理
  2. 提高模型准确率:组合模型
  3. 再谈迁移学习:微调网络
  4. 站在巨人的肩膀上:迁移学习
  5. 聊一聊rank-1和rank-5准确度
  6. 使用数据增强技术提升模型泛化能力

试试kaggle竞赛:辨别猫狗相关推荐

  1. 基于kaggle数据集的猫狗识别(超详细版本)

    目录 下载kaggle数据集 创建新的小数据集 构建猫狗分类的小型卷积神经网络 猫狗分类的网络架构 模型的配置 图像的预处理 利用批量生成器拟合模型 绘制精度和损失 结果显示 随机增强后的训练图像显示 ...

  2. tensorflow kaggle猫狗大战识别猫狗

    一,Kaggle猫狗大战数据集: 下载地址:https://www.kaggle.com/c/dogs-vs-cats 下载解压后会有两个文件目录,一个测试数据,一个训练数据: 训练数据: 二,训练代 ...

  3. kaggle项目实战——猫狗分类检测

    主要参考:<深度学习--caffe之经典模型详解与实战> kaggle数据集下载链接:https://www.kaggle.com/c/dogs-vs-cats-redux-kernels ...

  4. 华为云深度学习kaggle猫狗识别

    使用华为云深度学习服务完成kaggle猫狗识别竞赛 参考: kaggle猫狗竞赛kernel第一名的代码 Tensorflow官网代码 华为云DLS服务github代码 1. 环境配置与数据集处理 首 ...

  5. 【深度学习】猫狗识别TensorFlow2实验报告

    实验二:猫狗识别 一.实验目的 利用深度学习实现猫狗动物识别,采用Kaggle提供的公开数据集,训练深度学习模型,对测试集猫狗中的图片准确分类.通过该实验掌握深度学习中基本的CV处理过程. 二.实验原 ...

  6. AlexNet 实现猫狗分类(keras and pytorch)

    AlexNet 实现猫狗分类 前言 在训练网络过程中遇到了很多问题,先在这里抱怨一下,没有硬件条件去使用庞大的ImageNet2012 数据集 .所以在选择合适的数据集上走了些弯路,最后选择有kagg ...

  7. 猫狗大战(kaggle竞赛-猫狗图像分类)

    本实验使用kaggle中猫狗大战中的部分数据集(2000张训练数据+500张测试数据) 本次实验中使用了DNN.CNN.RNN分别进行了图像识别,具体代码如下: DNN模型: 全连接层 神经元个数 F ...

  8. 毕设:基于CNN卷积神经网络的猫狗识别、狗品种识别(Tensorflow、Keras、Kaggle竞赛)

    基于卷积神经网络的图像识别算法及其应用研究 毕业快一年了,拿出来分享给大家,我和网上唯一的区别就是,我能够同时实现两个方案(猫狗识别和狗品种识别),我当时也是网上各种查,花了2,3个月的时间,一个萝卜 ...

  9. Kaggle深度学习与卷积神经网络项目实战-猫狗分类检测数据集

    Kaggle深度学习与卷积神经网络项目实战-猫狗分类检测数据集 一.相关介绍 二.下载数据集 三.代码示例 1.导入keras库,并显示版本号 2.构建网络 3.数据预处理 4.使用数据增强 四.使用 ...

最新文章

  1. uniapp在低版本android,uni-app离线打包Android平台注意事项
  2. 11.4 专利法与反不正当竞争法解读
  3. SAP License:你熟悉SAP的统驭科目吗?
  4. Echarts数据可视化tooltip提示框,开发全解+完美注释
  5. wordpress字体_如何在WordPress中使用网络字体
  6. 计算机桌面变小了是怎么回事啊,电脑桌面整体变小了要怎么调回来的
  7. [转]二十四式太极拳攻防含义拆解
  8. IKBC DC-108改装锂电池
  9. 前端架构师的YY定义
  10. AD20 制作 Logo
  11. Android如何设置按钮图片(控件图片)大小自适应
  12. 树莓派 电脑 文件共享 搬移
  13. Didn't find class android.support.v7.widget.RecyclerView 解决办法 ———————————————— 版权声明:本文为CSDN博主「eag
  14. Qt修改可执行程序的图标 生成的exe使用自定义的Ico文件
  15. npm start 报错解决方案
  16. 在Word中撰写论文插入MathType公式,使得公式居中编号右对齐教程
  17. 将页面中的指定 div 下载为图片
  18. 如何来投放广告更赚钱
  19. FME学习资料……new
  20. 在Centos7上安装osp

热门文章

  1. 上学还是坐牢?百年老校“监控”学生惹争议
  2. Java根据奖品权重计算中奖概率实现抽奖(适用于砸金蛋、大转盘等抽奖活动)
  3. 杜克大学计算机专业本科入学条件,杜克大学计算机专业基本信息详解以及入学要求汇总介绍...
  4. 什么计算机玩游戏好,电脑玩游戏什么配置好
  5. 菌群分析Linux,Qiime1-13.菌群组成与指标相关性分析(自带命令及MaAslin)
  6. 爬取网易云音乐两万条评论储存在MySQL服务器上
  7. ognl表达式的简单用法
  8. 数据结构课程设计:1、单位员工通讯录管理系统(线性表的应用)
  9. 汇川AM401非标准协议通讯socket_client
  10. 查看linux centos ftp服务,Centos7开启FTP服务