论文笔记 —— Dense Caption

任何学习都应该从接口开始,而非实现

首先从 CNN 开始。

Applied Deep Learning Resources 上列举了最新的 CNN 算法在 ImageNet 上的效果,得分最高的三个分别是 ResNet (152 layers),GoogleNet (22 layers) 和 VGG (22 weight layers)。

ResNet 网络太深,训练和测试时间太久,不适合入门。VGG 虽然层数比 GoogleNet 少,但参数(144m parameters)却比 GoogleNet(7m parameters)多太多,且效果并不如后者好。我们可以以 GoogleNet 为基准尝试 CNN 模型。但在此之前,我们先实现用于 MNIST 手写字体分类的简单 LeNet-5 模型,作为 “Hello World” 式的热身练习。

Keras 实现 LeNet-5

LeNet-5 的网络结构如下图所示:

The structure of LeNet 5

包含卷积层、最大值池化层(Subsampling)、激活层和全连接层。

首先 import 相关库并下载 MNIST 数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten, Reshape
from keras.layers.convolutional import Convolution2D, MaxPooling2D, ZeroPadding2D, AveragePooling2D
from keras.optimizers import SGD, RMSprop
from keras.utils import np_utils
from keras.regularizers import l2
from keras.callbacks import EarlyStopping
from keras.preprocessing.image import ImageDataGenerator
from keras.layers.normalization import BatchNormalization
from PIL import image
(X_train, y_train), (X_test, y_test) = mnist.load_data()
print X_train.shape
print X_test.shape
X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32') / 255
X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype('float32') / 255
Y_train = np_utils.to_categorical(y_train, 10)
Y_test = np_utils.to_categorical(y_test, 10)

会看到 X_train.shape 为 (60000, 28, 28), 而 X_test.shape 为 (10000, 28, 28)。图像大小 并非 LeNet-5 示意图中的 32x32 而是 28x28,我们需要对参数进行细微的调整。

参考 LeNet-5 的示意图构建模型 model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
model = Sequential()
model.add(Convolution2D(6, 5, 5, border_mode='valid', input_shape = (1, 28, 28)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Activation("sigmoid"))
model.add(Convolution2D(16, 5, 5, border_mode='valid'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Activation("sigmoid"))
model.add(Dropout(0.5))
model.add(Convolution2D(120, 1, 1, border_mode='valid'))
model.add(Flatten())
model.add(Dense(84))
model.add(Activation("sigmoid"))
model.add(Dense(10))
model.add(Activation('softmax'))

任何一个主流机器学习算法可由三部分组成:得分函数(score function)、损失函数(loss function)和优化算法(optimization)。以上代码中定义的 model 决定了 LeNet-5 的网络结构,实际上是它的得分函数,我们还需要指定损失函数和优化算法来学习得到模型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
l_rate = 1
sgd = SGD(lr=l_rate, mu=0.8)
model.compile(loss='categorical_crossentropy', optimizer=sgd)
model.fit(X_train, Y_train, batch_size=32, nb_epoch=2,
verbose=1, show_accuracy=True, validation_data=(X_test, Y_test))
sgd = SGD(lr=0.8 * l_rate, mu=0.8)
model.compile(loss='categorical_crossentropy', optimizer=sgd)
model.fit(X_train, Y_train, batch_size=32, nb_epoch=3,
verbose=1, show_accuracy=True, validation_data=(X_test, Y_test))
sgd = SGD(lr=0.4 * l_rate, mu=0.8)
model.compile(loss='categorical_crossentropy', optimizer=sgd)
model.fit(X_train, Y_train, batch_size=32, nb_epoch=3,
verbose=1, show_accuracy=True, validation_data=(X_test, Y_test))
sgd = SGD(lr=0.2 * l_rate, mu=0.8)
model.compile(loss='categorical_crossentropy', optimizer=sgd)
model.fit(X_train, Y_train, batch_size=32, nb_epoch=4,
verbose=1, show_accuracy=True, validation_data=(X_test, Y_test))
sgd = SGD(lr=0.08 * l_rate, mu=0.8)
model.compile(loss='categorical_crossentropy', optimizer=sgd)
model.fit(X_train, Y_train, batch_size=32, nb_epoch=8,
verbose=1, show_accuracy=True, validation_data=(X_test, Y_test))

在测试集上看看准确率:

1
print("Test classification rate %0.05f" % model.evaluate(X_test, Y_test, show_accuracy=True)[1])

不出意外的话应该在 0.99 左右。再来看看那些被错分的样本:

1
2
3
4
5
6
7
8
9
10
11
12
y_hat = model.predict_classes(X_test)
test_wrong = [im for im in zip(X_test,y_hat,y_test) if im[1] != im[2]]
plt.figure(figsize=(10, 10))
for ind, val in enumerate(test_wrong[:100]):
plt.subplots_adjust(left=0, right=1, bottom=0, top=1)
plt.subplot(10, 10, ind + 1)
im = 1 - val[0].reshape((28,28))
plt.axis("off")
plt.text(0, 0, val[2], fontsize=14, color='blue')
plt.text(8, 0, val[1], fontsize=14, color='red')
plt.imshow(im, cmap='gray')

到此,我们就用 Keras 实现了 LeNet-5。

Keras 实现 GoogLeNet