cifar 图像分类

前言

cifar-9 分类图像数据集是从cifar10图像数据集中提取出的包含9个分类的图像数据集,cifar图像官网提供了cifar10图像数据集和cifar100图像数据集的下载。本次竞赛中,官方给定的数据集是从cifar10图像数据集中剔除掉“青蛙”这个类别的数据集。所有的图像都是32×32×3的RGB彩色图像。

数据预处理

比赛方提供的包含训练数据集和测试数据集的压缩包,每个目录的名称代表目录中数据的标签。在整个任务之前,首先,需要对数据集进行预处理。
数据的文件结构如下所示:



对原始的图像数据进行处理,主要分为以下几个步骤:

原始图像写入csv表格中

为了方便对数据进行操作,采用将图像数据以矩阵的方式写入csv中的方法,csv中,第一列表示图像的标签,用0-8这几个数字依次表示9个分类,1-3073类表示32×32×3的像素值。具体代码如下所示:

  • 解压图像数据
with zipfile.ZipFile("cifarData.zip") as zf:
    zf.extractall()
  • 获得训练集和测试集的所有标签
    按照文件目录,图像的标签即是当前图像所在文件夹(目录)的名称,则有如下代码:
#获得所有标签
train_label = [] #训练集标签
test_label = [] #测试集标签
for i in os.listdir('data/train'):
    train_label.append(i)
for i in os.listdir('data/test'):
    test_label.append(i)
    
  • 将图像数据写入csv文件中
    参数mode代表了写入数据集的类别,即训练集数据还是测试集数据

import cv
import csv
label_num = 0
def writeDataAsCsv(mode,fileName):
    with open(fileName,"w",newline="") as f:
        column_name=["lable"]
        for i in range(3072):
            column_name.extend(["pix"+str(i)])
        write = csv.writer(f)
        write.writerow(column_name)
       if mode==”test“:
        for i in test_label:
            for j in os.walk('data/'+str(mode)+'/'+str(i)):
                #print(i,j[2])
                #print(train_label.index(i))
                for k in j[2]:
                    img = cv2.imread("./data/"+str(mode)+"/"+str(i)+'/'+str(k))
                
                    row_data = [test_label.index(i)]
                    row_data.extend(img.flatten())
                    write.writerow(row_data)

  • 对数据集归一化和one-hot编码
    对数据集进行归一化和one-hot编码之前,首先需要加载csv格式的数据,为了加快加载数据的速度,可以采用dask.dataframe替代常用的pandas.DataFrame,并且需要对csv中数据的顺序随机调整(类似于洗牌操作)具体代码如下所示:
import dask.dataframe as dd
import numpy as np
import pandas as pd
train_data = dd.read_csv("train.csv",engine='python')
train_data = train_data.sample(frac=1)
test_data = dd.read_csv("test.csv",engine='python')
test_data = test_data.sample(frac=1)

#标签数据和图像数据进行划分
train_y = train_data['lable']
train_x = train_data.drop('lable',axis=1)
test_y = test_data['lable']
test_x = test_data.drop('lable',axis=1)

train_x = np.array(train_x).astype('float32')/255
test_x = np.array(test_x).astype('float32')/255

train_x = train_x.reshape(train_x.shape[0],32,32,3)
test_x = test_x.reshape((test_x.shape[0],32,32,3))
from keras.utils import np_utils
train_y = np_utils.to_categorical(train_y,9)
test_y = np_utils.to_categorical(test_y,9)

搭建模型

模型的结构是一个20层resnet的模型,每6层之间用一个shortcut路径进行连接,模型结构的代码如下所示:

# 残差模块
def resnet_block(inputs,num_filters=16, kernel_size=3,strides=1, activation='relu'):
    x = Conv2D(num_filters,kernel_size=kernel_size,strides=strides,padding='same',
           kernel_initializer='he_normal',kernel_regularizer=l2(1e-4))(inputs)
    x = BatchNormalization()(x)
    if(activation):
        x = Activation('relu')(x)
    return x
def resnet_v1(input_shape):
    inputs = Input(shape=input_shape)# Input层,用来当做占位使用

    #第一层
    x = resnet_block(inputs)
    print('layer1,xshape:',x.shape)
    # 第2~7层
    for i in range(6):
        a = resnet_block(inputs = x)
        b = resnet_block(inputs=a,activation=None)
        x = keras.layers.add([x,b])
        x = Activation('relu')(x)
    # out:32*32*16
    # 第8~13层
    for i in range(6):
        if i == 0:
            a = resnet_block(inputs = x,strides=2,num_filters=32)
        else:
            a = resnet_block(inputs = x,num_filters=32)
        b = resnet_block(inputs=a,activation=None,num_filters=32)
        if i==0:
            x = Conv2D(32,kernel_size=3,strides=2,padding='same',
                       kernel_initializer='he_normal',kernel_regularizer=l2(1e-4))(x)
        x = keras.layers.add([x,b])
        x = Activation('relu')(x)
    # out:16*16*32
    # 第14~19层
    for i in range(6):
        if i ==0 :
            a = resnet_block(inputs = x,strides=2,num_filters=64)
        else:
            a = resnet_block(inputs = x,num_filters=64)

        b = resnet_block(inputs=a,activation=None,num_filters=64)
        if i == 0:
            x = Conv2D(64,kernel_size=3,strides=2,padding='same',
                       kernel_initializer='he_normal',kernel_regularizer=l2(1e-4))(x)
        x = keras.layers.add([x,b])# 相加操作,要求x、b shape完全一致
        x = Activation('relu')(x)
    # out:8*8*64
    # 第20层 
    x = AveragePooling2D(pool_size=2)(x)
    # out:4*4*64
    y = Flatten()(x)
    # out:1024
    outputs = Dense(9,activation='softmax',
                    kernel_initializer='he_normal')(y)

    #初始化模型
    #之前的操作只是将多个神经网络层进行了相连,通过下面这一句的初始化操作,才算真正完成了一个模型的结构初始化
    model = Model(inputs=inputs,outputs=outputs)
    return model

拟合模型

模型实现之后,在拟合之前,可以实现数据增强增加模型的泛化能力,利用学习率衰减获得损失函数最优解,利用checkpoint保存模型的最佳的权重参数,具体如下代码所示:

checkpoint = ModelCheckpoint(filepath='./cifar10_resnet_ckpt.h5',monitor='val_acc',
                             verbose=1,save_best_only=True)
def lr_sch(epoch):
    #200 total
    if epoch <50:
        return 1e-3
    if 50<=epoch<100:
        return 1e-4
    if epoch>=100:
        return 1e-5
lr_scheduler = LearningRateScheduler(lr_sch)
lr_reducer = ReduceLROnPlateau(monitor='val_acc',factor=0.2,patience=5,
                               mode='max',min_lr=1e-3)
callbacks = [checkpoint,lr_scheduler,lr_reducer]

batch_size = 64
data_generator = tf.keras.preprocessing.image.ImageDataGenerator(width_shift_range=0.1, height_shift_range=0.1, horizontal_flip=True)
train_generator = data_generator.flow(train_x, train_y, batch_size)
steps_per_epoch = train_x.shape[0] // batch_size
model.fit_generator(train_generator, validation_data=(test_x, test_y), steps_per_epoch=steps_per_epoch, epochs=200,callbacks=callbacks)

做出预测

训练完成之后,利用保存好的模型权重参数进行预测,如下代码所示


from keras.models import load_model
load_model = load_model("./cifar9_resnet_ckpt.h5")
pred = load_model.predict(test_x)

模型预测的输出是one-hot形式的编码,对one-hot编码的形式进行整理,并将预测结果与对应图片名写入csv文件中,如下所示:

label = np.argmax(pred,axis=1)
data_row_img=[]
data_row_label=[]
path = "./data/test/"
for i in test_label:
    for j in os.walk(path+i+"/"):
        for k in j[2]:
            data_row_img.append(k)
        
for j in label:
    data_row_label.append(test_label[j])
pred_data = pd.DataFrame({"Img_file":data_row_img,"Label":data_row_label})

pred_data.to_csv("submission.csv",index=False)

参考:http://www.voidcn.com/article/p-cguqgdal-brn.html
https://arxiv.org/pdf/1512.03385.pdf

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容

  • 今天是什么日子 叫我起床的不是闹钟是梦想 今日三只青蛙/番茄钟 成功日志-记录三五件有收获的事务 财务检视 人际的...
    水畔青牛阅读 89评论 0 0
  • 人问客从何方来,侬家萍水曲处住。 青山妩媚水含情,赣风楚韵忍相顾。 今居江南水如碧,烟雨朦胧扬州路。 闻得淮戏声咿...
    程若尘阅读 334评论 0 1
  • •要感谢人生带给你的挫折和困难,因为它会让你重新看清楚一些事情,谁是真正对你,谁是假装对你 •命运负责洗牌,但玩牌...
    时空之零阅读 150评论 0 1
  • 原创: 啼眼 兰芳不厌谷幽 01 我好像很久没有记录有关爱情的一切了。 没再在空间里无端犯花痴,没再随时随刻都准备...
    我的白日梦少年阅读 242评论 0 2