Keras搭建CNN:CIFAR-100数据集图像分类

CIFAR-100数据集:

训练集:5万张100个类别的32*32尺寸的图片,每类均为500张。

测试集:1万张同样100个类别的32*32尺寸的图片,每类均为100张。

数据集下载地址:http://www.cs.toronto.edu/~kriz/cifar.html

 

训练用的是TensorFlow的Keras接口,建议使用GPU来跑,需要安装GPU版的TensorFlow可参考本人另一篇文章:

https://blog.csdn.net/weixin_39671140/article/details/84585072

 

模型是一个有6层卷积的CNN,在CIFAR-100数据集上图像分类,准确率平均51%左右。

通过多次训练做ensemble,效果有提升,ensemble 11个模型后准确率就到了60%左右。

训练时间:一块1060显卡,单个模型训练5.5min。假如用CPU大概要20倍时间。(缩短时间而又不牺牲太多准确率的方法,就是将所有卷积层的卷积核数量都一起减半)

PS:目前来看,不加入残差,容易梯度消失,无法继续将CNN网络加深。

 

训练单个模型的代码如下:

from tensorflow.keras import layers, models
import pickle
import numpy as np
from matplotlib import pyplot as plt


#原始数据读入成字典
def unpickle(file:str) -> dict:
    with open(file, 'rb') as fo:
        dict = pickle.load(fo, encoding = 'bytes')
    return dict


#数据从多维数组转换成原图片shape
def reshape_data(data_set:np.ndarray) -> np.ndarray:
    return data_set.reshape(data_set.shape[0],3,32,32).transpose(0,2,3,1)


#从数据文件读取出数据和标签
def read_data(file_path:str) -> np.ndarray:
    data_set = {key.decode('utf8'):value for key,value in unpickle(file_path).items()}
    return np.array(data_set['fine_labels']),data_set['data']


#数据文件路径
train_set_path = 'cifar-100-python/train'
test_set_path = 'cifar-100-python/test'

#标签数字代表的细标签名称
fine_label_names = [i.decode('utf8') for i in unpickle('cifar-100-python/meta')[b'fine_label_names']]

#读取训练集和测试集
train_label,train_data = read_data(train_set_path)
test_label,test_data = read_data(test_set_path)

#按原图片的size来reshape多维数组
train_data = reshape_data(train_data)
test_data = reshape_data(test_data)

#图像的RGB值映射到(0,1)范围
train_data, test_data = train_data / 255.0, test_data / 255.0


#创建CNN模型
model = models.Sequential()
#底部添加作为特征提取器的卷积层

#卷积层1
model.add(layers.Conv2D(128, (3, 3),padding='same', activation='relu', input_shape=(32, 32, 3)))

#卷积层2
model.add(layers.Conv2D(128, (3, 3),padding='same'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Activation('relu'))

#卷积层3
model.add(layers.Conv2D(256, (3, 3),padding='same'))
model.add(layers.Activation('relu'))

#卷积层4
model.add(layers.Conv2D(256, (3, 3),padding='same'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Activation('relu'))

#卷积层5
model.add(layers.Conv2D(512, (3, 3),padding='same'))
model.add(layers.Activation('relu'))

#卷积层6
model.add(layers.Conv2D(512, (3, 3),padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Activation('relu'))
model.add(layers.Dropout(0.5))

#展平成一维数组
model.add(layers.Flatten())
#在顶部添加密集层
model.add(layers.Dense(800, activation='relu'))
model.add(layers.Dense(100, activation='softmax'))

#显示模型的架构
model.summary()

#编译和训练模型
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

history = model.fit(train_data, train_label, epochs=10 , batch_size=800)

#评估模型
test_loss, test_acc = model.evaluate(test_data, test_label)
print('\n\n',test_loss, test_acc)

# 绘制训练的精确度 & 损失值
plt.plot(history.history['acc'])
plt.plot(history.history['loss'])
plt.title('Model train')
plt.ylabel('Accuracy or loss')
plt.xlabel('Epoch')
plt.legend(['acc', 'loss'], loc='upper right')
plt.show()

 

多个模型集成的代码如下(涨点明显):

from tensorflow.keras import layers, models
import pickle
import numpy as np
from matplotlib import pyplot 


#原始数据读入成字典
def unpickle(file:str) -> dict:
    with open(file, 'rb') as fo:
        dict = pickle.load(fo, encoding = 'bytes')
    return dict

#数据从多维数组转换成原图片shape
def reshape_data(data_set:np.ndarray) -> np.ndarray:
    return data_set.reshape(data_set.shape[0],3,32,32).transpose(0,2,3,1)

#从数据文件读取出数据和标签
def read_data(file_path:str) -> np.ndarray:
    data_set = {key.decode('utf8'):value for key,value in unpickle(file_path).items()}
    return np.array(data_set['fine_labels']),data_set['data']
    

#数据文件路径
train_set_path = 'cifar-100-python/train'
test_set_path = 'cifar-100-python/test'

#标签数字代表的细标签名称
fine_label_names = [i.decode('utf8') for i in unpickle('cifar-100-python/meta')[b'fine_label_names']]

#读取训练集和测试集
train_label,train_data = read_data(train_set_path)
test_label,test_data = read_data(test_set_path)

#按原图片的size来reshape多维数组
train_data = reshape_data(train_data)
test_data = reshape_data(test_data)

#图像的RGB值映射到(0,1)范围
train_data, test_data = train_data / 255.0, test_data / 255.0


#训练9个模型来集成
n_estimators = 9
model_list = []

for n in range(n_estimators):
    
    #创建CNN模型
    model = models.Sequential()
    #底部添加作为特征提取器的卷积层
    
    #卷积层1
    model.add(layers.Conv2D(128, (3, 3),padding='same', activation='relu', input_shape=(32, 32, 3)))
    
    #卷积层2
    model.add(layers.Conv2D(128, (3, 3),padding='same'))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Activation('relu'))
    
    #卷积层3
    model.add(layers.Conv2D(256, (3, 3),padding='same'))
    model.add(layers.Activation('relu'))
    
    #卷积层4
    model.add(layers.Conv2D(256, (3, 3),padding='same'))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Activation('relu'))
    
    #卷积层5
    model.add(layers.Conv2D(512, (3, 3),padding='same'))
    model.add(layers.Activation('relu'))
    
    #卷积层6
    model.add(layers.Conv2D(512, (3, 3),padding='same'))
    model.add(layers.BatchNormalization())
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Activation('relu'))
    model.add(layers.Dropout(0.5))
    
    #展平成一维数组
    model.add(layers.Flatten())
    #在顶部添加密集层
    model.add(layers.Dense(800, activation='relu'))
    model.add(layers.Dense(100, activation='softmax'))
    #显示模型的架构
    model.summary()
    
    #编译和训练模型
    model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])
    
    print(f'train model {n+1} now')
    
    model.fit(train_data, train_label, epochs=10 , batch_size=800)
    
    model_list.append(model)

    
#多个模型的预测做voting
def ensemble_prediction(test_data:np.ndarray) -> list:
    bincount = np.bincount
    result = np.array([model.predict_classes(test_data) for model in model_list])
    result = result.transpose(1,0)
    return [bincount(i).argmax() for i in result]
    
#评估模型
result = ensemble_prediction(test_data)
test_acc = sum([result[i] == test_label[i] for i in range(test_label.shape[0])])/test_label.shape[0]
print('accuracy:',test_acc)


#可视化看第n张图与预测标签是否符合
n = 9
print('predict:',fine_label_names[result[n]],', ground truth:',fine_label_names[test_label[n]])
pyplot.imshow(test_data[n])

欢迎指正。

  • 0
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值