keras复现LeNet
具体结构如下:
conv + subsampling + conv + subsampling + fully connected
具体解释下LeNet-5结构, 一共是7层,除去输入层实际上是7个feature map。
1:Input
32 * 32 * 1 的灰度图像,输入前做归一化处理
2:C1卷积层
输入:32 * 32 * 1
卷积核大小为 5,步长 1
卷积核的数目:6
输出feature map: , “(32 - 5 + 1) / 1 = 28,每个卷积核一个feature map”
3:S2池化层
输入: 28 * 28 * 6
池化尺寸: 2 * 2
输出: (28/2 = 14)
4:C3卷积层
输入: 14 * 14 * 6
卷积核大小为 5, 步长 1
卷积核的数目:16
输出feature map: , (14 -5 + 1) /1 = 10
5:S4池化层
输入: 101016
池化尺寸: 2*2
输出: (10/2 = 5)
6:C5全连接层(特殊的卷积)
实际上是将输入的feature map flatten 了一下, 然后和下一层全连
输入:
输出: 120维向量
7:F6全连接
输入: 120维向量
输出: 84 维向量
8:输出层
输入:84维向量
输出: 10维向量
接下来直接看Keras复现代码
代码复现
1:模型结构定义
这里我们使用Keras内置的mnist数据集,默认是28 * 28大小,而原论文中是32 * 32,为了和原论文保持一致,我们在网络结构中加入ZeroPadding2D, 在原始输入上下左右补0,其他和原文一致。
import numpy
import pandas
from keras.models import Sequential,Model
from keras.layers import Dense,Input,Conv2D,MaxPooling2D,Flatten,ZeroPadding2D
from keras import callbacks
from keras.wrappers.scikit_learn import KerasRegressor,KerasClassifier
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import KFold,train_test_split
from sklearn.preprocessing import StandardScaler,LabelEncoder
from sklearn.pipeline import Pipeline
from keras.utils import np_utils
from keras.datasets import mnist
from keras.optimizers import RMSprop
def LeNet(input_tensor=None, input_shape=(32, 32, 1), activation='relu'):
act = activation
if input_tensor is None:
input_tensor = Input(shape = input_shape)
x = ZeroPadding2D(padding=(2,2), data_format='channels_last')(input_tensor)
x = Conv2D(filters=6, kernel_size=5, strides=1, activation=act)(x)
x = MaxPooling2D(pool_size=(2,2), strides=2)(x)
x = Conv2D(filters=16, kernel_size=5, strides=1, activation=act)(x)
x = MaxPooling2D(pool_size=2, strides=2)(x)
x = Flatten()(x)
x = Dense(units=120, activation=act)(x)
x = Dense(units=84, activation=act)(x)
x = Dense(units=10, activation='softmax')(x)
model = Model(inputs=input_tensor, outputs=x)
return model
if __name__ == '__main__':
#load mnist dataset
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = np.expand_dims(x_train, axis=3)
x_test = np.expand_dims(x_test, axis=3)
print(x_train.shape)
x_train,x_test = x_train.astype("float32"),x_test.astype("float32")
mean = np.mean(x_train, axis=(0,1,2,3))
std = np.std(x_train, axis=(0,1,2,3))
# standardlization
x_train = (x_train - mean)/(std + 1e-7)
x_test = (x_test - mean)/(std + 1e-7)
# one-hot encoding
y_train = np_utils.to_categorical(y_train,num_classes=10)
y_test = np_utils.to_categorical(y_test,num_classes=10)
model = LeNet(input_shape=(28,28,1))
# tensorboard callbacks
tensorboard_callback = callbacks.TensorBoard(log_dir='./logs', batch_size=10)
model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(x_train, y_train, batch_size=10, validation_data=(x_test, y_test), epochs=42,
callbacks=[tensorboard_callback])
model.save('lenet.h5')
(60000, 28, 28, 1)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-83-06b24fb3476e> in <module>()
22 model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])
23 model.fit(x_train, y_train, batch_size=10, validation_data=(x_test, y_test), epochs=42,
---> 24 callbacks=[tensorboard_callback])
25 # model.save('lenet.h5')
26
NameError: name 'tensorboard_callback' is not defined
模型测试
from keras.models import load_model
import cv2
import os
import numpy as np
from matplotlib import pyplot as plt
img_files = [f for f in os.listdir("./testSamples") if not f.startswith('.')]
model = load_model('*.h5')
model.summary()
for i,img_file in enumerate(img_file[:10]):
img = cv2.imread(os.path.join('./testSamples',img_file),-1)
plt.show(img)
img = np.expand_dims(img, 2)
img = np.expand_dims(img, 0)
img = (img - np.mean(img)) / np.std(img)
logits = model.predict(img, batch_size=1)
label = np.argmax(logits)
plt.subplot(1, 10, i+1)
plt.title(str(label))
plt.show()