深度学习系列之图像分类

      最近在学习深度学习相应的知识,为了巩固所学内容,打算从文本分类、图像分类等较为大众化的任务开始,并书写博客记录之,与博友共勉。本文介绍的就是使用keras框架进行图像分类(数据源mnist)的操作,下面通过几个章节分别介绍一些背景知识和具体的操作步骤。

       一.数据集和使用的框架的介绍

          1.keras:keras是一个深度学习框架,底层使用的是theano和tensorflow,keras可以理解成一个更高层的封装抽象,较为易于使用,具体了解该框架,可以参见相应的中文文档,其地址为:http://keras-cn.readthedocs.io/en/latest/。关于keras的安装稍微多说几句,keras安装需要numpy scipy  theano h5py等python库,其中h5py安装稍微复杂,如果安装不上可以使用anaconda这个数据集成软件包,里面已经安装了相应一些python库,还有就是tensorflow比theano稍微难安装一些,如果安装不上tensorflow可以使用theano后台的keras。

          2.mnist:本文使用的数据源是mnist数据,该数据是一个手写识别资料库,里面有很多0-9之间手写数据,很多论文和比赛使用的数据都是该数据,使用起来也较为方便,所以本文使用的是该数据,想了解mnist可以参见地址如下:http://yann.lecun.com/exdb/mnist/。因为minst数据不是直观可见的jpg格式,这里提供一个jpg格式minst数据,地址为:http://pan.baidu.com/s/1bI1H86

          3.本文使用的框架:

           主要使用keras+theano+skleran+numpy,开发环境为ubuntu,可以直接采用anaconda数据库包+安装keras+theano包。


       二.深度学习和图像分类的简要介绍

          1.深度学习:这是一个被炒作过度的概念,所谓深度学习其实并不完全是一个新鲜产物,和机器学习实际上一脉相承的,本质上是使用神经网络的方法来构建机器学习模型,神经网络虽然听起来很像是一个生物名词,但是实质上和生物学和人体科学的关系并不十分明显,作为初学者如果对深度学习一无所知的话,可以参见coursera上ng的视频教程,机器学习一课,其中就有关于神经网络的介绍,具体课程地址如下:https://www.coursera.org/learn/machine-learning/home

         2.图像分类:图像分类顾名思义,就是指给计算机一张图片,让其判断该图片是某一类的图片。具体而言比如手写识别:即给计算机一张手写数字,计算机能判断其是0-9之间的某一个数。或者如猫狗识别:即给计算机一张图片,让其判断其中的影响是猫还是狗。诸如此类即为图像分类,本文介绍的即是手写数字识别任务。


       三.手写识别任务的具体操作步骤

         1.mnist数据读取和训练集、测试集的构造:因为这里使用的mnist数据集的jpg格式,下载地址为:http://pan.baidu.com/s/1bI1H86,这里的mnist数据都是手写数字数据,存储格式为jpg,每张图片的命名格式 标签.编号.jpg,比如一张图片的命名为5.990.jpg,它的意思就是说该图片的内容是手写数字5,编号是990,扩展名是jpg。根据以上特点,我们首先书写一个mnist数据读取程序,将mnist文件下的数据读取成相应的numpy格式的矩阵(可以理解成是多维数组)。具体代码如下:

#coding:utf-8

import os
import numpy as np
import PIL 

def load_data():
    set = np.empty((42000,1,28,28),dtype="float32") //读取mnist数据,42000张,通道为1,尺寸为28*28
    label = np.empty((42000,),dtype="uint8") //每张图片标签的存储结构
    img_list = os.listdir("./mnist")
    count = len(img_list)
    for i in range(count):
        img = PIL.Image.open("./mnist/"+img_list[i])
        array = np.asarray(img,dtype="float32")
        set[i,:,:,:] = array
        label[i] = int(img_list[i].split('.')[0]) //根据mnist数据图片的明明特点,读取相应的mnist图片的标签
    return set,label

if __name__ == '__main__': //本程序的本地测试程序
    set,label = load_data()
    print set.shape // 输出图片数据矩阵的形状,结果为(42000,1,28,28)
    print label.shape //输出标签数据的形状,结果为(42000,)
    print label[0] //输出读入的第一张图片的标签,结果1(即手写数字1)
    print label[10000] //输出读入的第10000张图片的标签,结果为6(即手写数字6)
 上述代码,将mnist文件下的jpg格式的图片数据,分别分别读取为矩阵形式的数据和相应标签,该函数可以后续用于构建训练集和测试集。

2.根据keras构建神经网络用于训练图像分类模型
         这里构造的神经网络较为简单,为三层卷积层(后面紧跟着relu激活层和下采样层)+2个全连接层(最后一层后面紧跟着softmax激活层)组成。具体代码和注释如下:
#import
from __future__ import absolute_import
from __future__ import print_function
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.advanced_activations import PReLU
from keras.layers.convolutional import Convolution2D
from keras.layers import  MaxPooling2D
from keras.optimizers import SGD, Adadelta, Adagrad
from keras.utils import np_utils, generic_utils
from six.moves import range
from load_data import load_data
from keras.layers.advanced_activations import LeakyReLU  
from keras.models import model_from_json  
from keras.layers import *

import pandas as pd
import numpy as np
from sklearn import cross_validation
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.externals import joblib

import sys
import pdb


#创建一个keras模型
model = Sequential()

#第一层卷积神经网络,卷积核4个,滑动窗口(5,5),跟随一个leakyrelu,该层和relu类似
model.add(Convolution2D(4,5,5, border_mode='same',input_shape=(1,28,28))) #first conv layer
model.add(LeakyReLU(alpha=0.3))

#第二层卷积神经网络,卷积核8个,滑动窗口(3,3),跟随一个leakyrelu,该层和relu类似,而后跟一个下采样层(2,2)
model.add(Convolution2D(8,3,3, border_mode='same')) # second conv layer
model.add(LeakyReLU(alpha=0.3))
model.add(MaxPooling2D(pool_size=(2, 2)))

#第三层卷积神经网络,卷积核16个,滑动窗口(3,3),跟随一个leakyrelu,该层和relu类似,而后跟一个下采样层(2,2)
model.add(Convolution2D(16,3,3, border_mode='same')) #third conv layer
model.add(LeakyReLU(alpha=0.3))
model.add(MaxPooling2D(pool_size=(2, 2)))

#将卷积层展平,第一层全连接层输出为128个,跟随一个leakyrelu,改成和relu类似
model.add(Flatten())
model.add(Dense(128))
model.add(LeakyReLU(alpha=0.3))

#第二层全连接层输出为10个,跟随一个softmax的激活层,输出结果为识别为0-9之间某个数字的概率
model.add(Dense(10, activation='softmax'))

#编译神经网络
model.compile(optimizer='Adadelta',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

#读入mnist数据,得到data和label
data,label = load_data() # data=(42000,1,28,28)  label = (42000,10)
label = np_utils.to_categorical(label, 10)

#使用sklearn的包拆分训练集和验证集,比例为7:3,可不使用sklearn,结果类似
x_train, x_test, y_train, y_test = cross_validation.train_test_split(data, label, test_size=0.3, random_state=1)

#训练模型
model.fit(x_train, y_train, nb_epoch=10)

#对模型在训练集中进行评分,score[0]代表损失函数值(越接近0越好),score[1]代表训练集中的准确率,约为99%
score = model.evaluate(x_train, y_train, verbose=0) 
print('train score:', score[0])
print('train accuracy:', score[1])

#对模型在验证集中进行评分,score[0]代表损失函数值(越接近0越好),score[1]代表测试集中的准确率,约为98%
score = model.evaluate(x_test, y_test, verbose=0) 
print('Test score:', score[0])
print('Test accuracy:', score[1])


 
   
 
   
上述代码最后在训练集中准确率约为99%,测试集中准确率约为98%,因为模型是较为简单的模型,实际使用可以采用较为复杂的模型例如vgg16等。可以看出即使是很简单的模型,也可以达到很高的准确率,这就是深度学习的魅力。
需要注意的是,首先上述代码中中文注释部分,实际使用时最好删去,否则可能因为乱码问题报错。其次上述代码中,没有持久化模型(即保存模型到硬盘上),实际使用时应当持久化模型,但是持久化时需安装h5py,此模块安装较为复杂,这里就没有涉及该部分。

       四.总结与展望

1.本文工作总结:本文主要通过keras框架+mnist数据集(已经转换为jpg格式的)进行了一个简单的文本分类模型的设计与实现,使用3层卷积层+2层全连接层实现了98%左右的准确率的模型,初步感受了深度学习和keras框架的魅力

2.未来本博客会介绍深度学习在文本分类等方面领域的应用,希望大家多多关注,因为是深度学习领域的新人,希望大家多多批评指正,不吝赐教。

3.本文代码和数据地址罗列如下:

3.1.代码地址:https://github.com/894939677/deeplearning_by_diye

3.2本文所使用的mnist的jpg格式的地址为:http://pan.baidu.com/s/1bI1H86



你可能感兴趣的:(深度学习项目篇章)