Keras搭建CNN:CIFAR-100数据集图像分类
CIFAR-100数据集:
训练集:5万张100个类别的32*32尺⼨的图⽚,每类均为500张。
测试集:1万张同样100个类别的32*32尺⼨的图⽚,每类均为100张。
训练⽤的是TensorFlow的Keras接⼝,建议使⽤GPU来跑,需要安装GPU版的TensorFlow可参考本⼈另⼀篇⽂章:
模型是⼀个有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 shape(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)
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()
#底部添加作为特征提取器的卷积层import pickle
#卷积层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()
#编译和训练模型
modelpile(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()
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 shape(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()
#编译和训练模型
modelpile(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 = anspose(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])
欢迎指正。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。