load data

CIFAR-10数据集中包含了50000个训练数据与10000个测试数据。

图片是32*32大小的RGB图片,每个像素点由红色、绿色、蓝色通道3个数字组成(0-255)。

输出y由一个数字表示,0到9这10个数字分别代表10类物体。

0:飞机,1:汽车,2:鸟,3:猫,4:鹿,5:狗,6:青蛙,7:马,8:船,9:卡车

In [1]:
from keras.datasets import cifar10

(x_train, y_train), (x_test, y_test) = cifar10.load_data() #使用keras提供的api读取数据

num_classes = 10
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)
Using TensorFlow backend.
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
170500096/170498071 [==============================] - 6s 0us/step
(50000, 32, 32, 3)
(50000, 1)
(10000, 32, 32, 3)
(10000, 1)

visualization

In [2]:
import numpy as np
import matplotlib.pyplot as plt

fig, axes = plt.subplots(num_classes, 10, figsize=(15, 15)) # 新建一个包含100张子图的10行10列的画布
for i in range(num_classes): # 对于每一类物体
    indice = np.where(y_train == i)[0] #找到标签为i的图像下标
    for j in range(10): # 输出前10张图片
        axes[i][j].imshow(x_train[indice[j]])
        # 去除坐标刻度
        axes[i][j].set_xticks([]) 
        axes[i][j].set_yticks([])
plt.tight_layout()
plt.show()

preprocess

In [3]:
from keras.utils import to_categorical

#归一化
x_train = x_train / 255
x_test = x_test / 255

#将训练数据的标签独热编码
y_train = to_categorical(y_train, num_classes)
y_test = to_categorical(y_test, num_classes)
In [4]:
print(y_train.shape)
print(y_train[0])
(50000, 10)
[0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]

CNN

使用 Keras 搭建一个如下的卷积神经网络 cnn.png

In [5]:
from keras.models import Sequential
from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D, Dropout

model = Sequential()
# Conv2D: 卷积层
# - 32: 卷积核的个数
# - (3, 3): 卷积核大小
# - padding=’same‘:补齐模式图片卷积后大小不变
# - input_shape=x_train.shape[1:]: 将输入大小告诉网络的第一层,方便推导后面所需参数
# - activation="relu": 使用 relu 激活函数
model.add(Conv2D(32, (3, 3), padding="same", input_shape=x_train.shape[1:], activation="relu")) 
model.add(Conv2D(32, (3, 3), padding="same", activation="relu"))
model.add(MaxPooling2D(pool_size=2)) # 最大池化层,在2*2的区域中选取最大的数
model.add(Dropout(0.25)) # 丢弃层,随机将25%的神经元设为0

model.add(Conv2D(64, (3, 3), padding="same", activation="relu"))
model.add(Conv2D(64, (3, 3), padding="same", activation="relu"))
model.add(MaxPooling2D(pool_size=2))
model.add(Dropout(0.25))

model.add(Flatten()) # 转为一维数据
model.add(Dense(512, activation="relu")) # 全连接层
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation="softmax")) # 最后一个全连接层使用 softmax 激活函数,输出分类概率

# 使用 model.compile 编译模型
# - loss='categorical_crossentropy': 使用交叉熵为损失函数
# - optimizer="adam": 使用 adam 优化器
# - metrics=['accuracy']: 使用准确率为指标
model.compile(loss='categorical_crossentropy',
              optimizer="adam",
              metrics=['accuracy'])
In [6]:
model.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 32, 32, 32)        896       
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 32, 32, 32)        9248      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 16, 16, 32)        0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 16, 16, 32)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 16, 16, 64)        18496     
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 16, 16, 64)        36928     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 8, 8, 64)          0         
_________________________________________________________________
dropout_2 (Dropout)          (None, 8, 8, 64)          0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 4096)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 512)               2097664   
_________________________________________________________________
dropout_3 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 10)                5130      
=================================================================
Total params: 2,168,362
Trainable params: 2,168,362
Non-trainable params: 0
_________________________________________________________________
In [7]:
batch_size = 32
epochs = 5
history = model.fit(x_train, y_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose=1,
                    validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
Train on 50000 samples, validate on 10000 samples
Epoch 1/5
50000/50000 [==============================] - 15s 294us/step - loss: 1.4576 - accuracy: 0.4685 - val_loss: 1.0741 - val_accuracy: 0.6138
Epoch 2/5
50000/50000 [==============================] - 11s 222us/step - loss: 1.0576 - accuracy: 0.6255 - val_loss: 0.8799 - val_accuracy: 0.6905
Epoch 3/5
50000/50000 [==============================] - 11s 224us/step - loss: 0.9180 - accuracy: 0.6778 - val_loss: 0.8352 - val_accuracy: 0.7073
Epoch 4/5
50000/50000 [==============================] - 11s 225us/step - loss: 0.8164 - accuracy: 0.7118 - val_loss: 0.7573 - val_accuracy: 0.7358
Epoch 5/5
50000/50000 [==============================] - 11s 222us/step - loss: 0.7486 - accuracy: 0.7345 - val_loss: 0.7214 - val_accuracy: 0.7451
Test loss: 0.7214166352272033
Test accuracy: 0.7451000213623047