目录
1.卷积神经网络特点概述
2.卷积神经网络在图像任务方面的优势概述
3.传统神经网络的缺点
3.1.庞大的参数
3.2.丢失像素间的信息
3.3.制约网络深度的发展
4.卷积神经网络的三大核心思想
4.1.局部感知
4.2.权值共享
4.3.下采样技术
5.可视化手写字体的网络特征
5.1.LeNet5的训练
5.2.可视化特征向量
5.3.获取最好的保存的模型
5.4.获取特征的输出
卷积神经网络的强大之处在于它的多层网络结构能自动学习输入数据的深层特征,不同层次的网络可以学习到不同层次的特征:
浅层网络层的感知区域较小,可以学习到输入特征的局部区域特征,如图像物体的颜色、几何形状等;
深层网络层的感知区域较大,可以学习到输入数据更加抽象的特征,如图像物体的属性、轮廓特点、位置信息等高维信息;
深层次的抽象特征对图像中物体的大小、位置和方向等敏感度较低,从而大大提高了物体的识别率,因此卷积神经网络常常用于图像领域。
在图像任务中,卷积神经网络可以用来识别位移、缩放及物体形态扭曲的二维图像。
一方面,由于其网络模型中的特征时通过训练数据集进行图像特征学习,从而避免了显式地特征抽取;
另一方面,由于图像上同一特征映射面上的神经元权值相同,所以卷积神经网络模型可以进行并行训练,极大地缩短了模型的训练时间;
此外,卷积神经网络模型的组织形式也比较特殊,其模型更加易于理解和分析。
全连接网络的层与层之间的神经元全部来连接,会带来庞大的权值和偏置参数。
由于图像像素之间的数据时相互关联的矩阵数据,一个像素代表一个神经元节点,全连接会造成像素间的关系丢失。
通常来说,神经网络的层数加深,提取特征的维度也就越深,但是,当网络的深度超过3层的时候,就会比较容易引发数据的过拟合、梯度消散等一系列的数学问题,所以一般传统神经网络的层数都不会超过3层。
卷积神经网络通过局部感知和权值共享,保留了像素间的关联信息,并大大减少了所需参数的数量,通过Pooling技术,进一步缩减网络的参数数量,提高模型的鲁棒性,让模型可以持续地扩展深度,继续增加隐层。
每个神经元不再与下一层的所有的神经元相连,只和一部分神经元连接,同时这一部分神经元具有相关性(邻近的几个神经元),针对图像的空间关系,一般是局部的像素联系比较紧密,而距离比较远的像素之间的关联性比较弱,也因此没有相连的必要,只需对图像空间中联系比较紧密的局部信息进行感知,然后在更深层网络中继续提取图像的局部特征。
随着网络层次的深入,图像的尺寸逐渐缩小,对图像特征的提取也从片面到整体,综合起来便能够得到图像的全局信息。
一组连接可以共享一个参数,或者多组连接也可以共享同一个卷积核,不再是每条连接都有自己的权重。
比如,一个卷积核在图像的局部区域中抽取了纹理特征,那么在类似图像的类似特征依然可以使用该卷积核,这样就大大的减小了卷积核的数目,也就减小的参数的数目。
通过pooling技术对输入的数据进行下采样压缩操作,减少输出节点。
方式:Max Pooling和Mean Pooling
优点:
1、减少过拟合的可能性,当网络中权重参数过多的时候,很容易在训练阶段造成过拟合;
2、缩减图像的尺寸,减少计算量,提升计算速度;
3、进一步提取图像高维的统计特征。
from keras.datasets import mnist
from keras.utils import to_categorical
from keras.layers import MaxPool2D, Input, Flatten, Conv2D, Dropout, Dense
from keras.models import Model
from tensorflow.examples.tutorials.mnist import input_data
from keras.callbacks import ModelCheckpoint
import os
import keras
num_classes = 10
img_rows, img_cols = (28, 28)
def get_mnist_data():
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
y_train = to_categorical(y_train, num_classes)
y_test = to_categorical(y_test, num_classes)
return x_train, y_train, x_test, y_test
def LeNet5_model(w_path=None):
input_shape = (img_rows, img_cols, 1)
img_input = Input(shape=input_shape)
x = Conv2D(32, (3, 3), activation='relu', padding='same', name='conv1')(img_input)
x = MaxPool2D((2, 2), strides=(2, 2), name='pool1')(x)
x = Conv2D(64, (5, 5), activation='relu', name='conv2')(x)
x = MaxPool2D((2, 2), strides=(2, 2), name='pool2')(x)
x = Dropout(0.25)(x)
x = Flatten(name='Flatten')(x)
x = Dense(120, activation='relu', name='fc1')(x)
x = Dropout(0.5)(x)
x = Dense(84, activation='relu', name='fc2')(x)
x = Dropout(0.5)(x)
x = Dense(10, activation='softmax', name='predictions')(x)
model = Model(img_input, x, name='LeNet5')
if w_path:
model.load_weights(w_path)
model.summary()
model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adadelta(), metrics=['accuracy'])
return model
if __name__ == '__main__':
x_train, y_train, x_test, y_test = get_mnist_data()
print(x_train.shape)
print(x_test.shape)
if not os.path.exists('letnet5_checkpoints'):
os.mkdir('letnet5_checkpoints')
model = LeNet5_model()
checkpoint = ModelCheckpoint(monitor='val_acc', filepath='letnet5_checkpoints/model_{epoch:02d}_{val_acc:.3f}.h5',
save_best_only=True)
model.fit(x_train,
y_train,
batch_size=128,
epochs=30,
verbose=1,
validation_data=(x_test, y_test),
callbacks=[checkpoint])
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
lenet5 = load_model('letnet5_checkpoints/model_21_0.995.h5')
layer1 = lenet5.get_layer("conv1")
w = layer1.get_weights()
print(w[0].shape)
print(np.squeeze(w[0]).shape)
def get_activations(model, model_input, layer_name = None):
activations = []
inp = [model.input]
# 所有层的输出
model_layers = [layer.output for layer in model.layers if
layer.name == layer_name or layer_name is None]
pprint.pprint(model_layers)
newmodel_layers = []
newmodel_layers.append(model_layers[0])
newmodel_layers.append(model_layers[1])
newmodel_layers.append(model_layers[2])
newmodel_layers.append(model_layers[3])
newmodel_layers.append(model_layers[4])
newmodel_layers.append(model_layers[7])
newmodel_layers.append(model_layers[9])
newmodel_layers.append(model_layers[11])
funcs = [K.function(inp + [K.learning_phase()], [layer]) for layer in newmodel_layers]
list_inputs = model_input.reshape(1,28,28,1)
print(list_inputs.shape)
layer_outputs = [func([list_inputs]) for func in funcs]
for activation in layer_outputs:
activations.append(activation)
return activations
activations = get_activations(lenet5, x_test[i])
def display_tensor(tensors):
if tensors.shape == (1, 1, 28, 28):
tt = np.hstack(np.transpose(tensors[0], (0, 1, 2)))
plt.figure(figsize=(15,1))
plt.imshow(tt, interpolation='None', cmap='gray')
plt.show()
else:
tt = np.hstack(np.transpose(tensors[0], (0, 1, 2)))
plt.figure(figsize=(15,1))
plt.imshow(tt, interpolation='None', cmap='hot')
plt.show()
def display_matrix(matrix):
num_activations = len(matrix)
tt = np.repeat(matrix, 10, axis=0)
plt.figure(figsize=(20,2))
plt.imshow(tt, interpolation='None', cmap='hot')
plt.colorbar()
plt.show()
def display_activations(activations_tensor):
img_size = activations_tensor[0][0].shape[0]
assert img_size == 1, 'One image at a time to visualize!'
for i, activation_map in enumerate(activations_tensor):
print('Displaying activation: {} {}'.format(i, activation_map[0].shape))
activation_map = activation_map[0]
shape = activation_map.shape
if len(shape) == 4:
display_tensor(activation_map)
pass
if len(shape) == 2:
display_matrix(activation_map)
display_activations(activations)
参考: