一、卷积神经网络介绍
(一)卷积运算以及编程语言中的卷积运算符
6x6图像经过3x3的过滤器转变为4x4的图像
(二)垂直边缘检测
4x4图像中间有段亮一点的区域,对应检测到6×6图像中间的垂直边缘。
(三)关于边缘检测的更多内容
从亮到暗或从暗到亮的过渡带
垂直边缘检测和水平边缘检测
其他类型的过滤器
(四)padding
1.为何padding
padding的原因:
原本图像经过过滤器放缩(一层一层),变的越来越小,图像变小是一个原因,另一个原因是原本图像边缘信息损失。
n x n图像经过f x f过滤器转化为(n-f+1) x (n-f+1)图像
选择填充的步数p=padding
2.基于padding的两种常用卷积
Valid:不填充,即p=0
Same:填充的步数使得输入大小和输出大小相同
(
n
+
2
p
−
f
+
1
)
(n+2p-f+1)
(n+2p−f+1) X
(
n
+
2
p
−
f
+
1
)
=
n
(n+2p-f+1)=n
(n+2p−f+1)=n X
n
n
n
得到
p
=
f
−
1
2
p=\frac{f-1}{2}
p=2f−1
因此卷积核
f
f
f通常为奇数
(五)步长stride
给定n,f,p,s,计算输出图像大小
数学中的卷积和神经网络中的卷积不一样
数学中的卷积需要对过滤器顺时针旋转90度再镜像
神经网络中不需要这项操作
(六)三维卷积
6 x 6 x 1是指灰色图像
6 x 6 x 3是指彩色图像,3是通道数
三维卷积的计算
输入图像的通道数必须和过滤器的通道数保持一致。
过滤器的参数不同,得到不同的检测器。
如果同时想检测多个特征,比如既想检测垂直边缘特征,又想检测水平边缘特征,则可以使用多个滤波器。最后输出图像的通道数即是使用滤波器的个数。
(七)单层卷积网络
某一层卷积网络的工作原理
(八)简单卷积网络示例
卷积神经网络中常见的层
卷积层、池化层、 全连接层
(九)池化层
池化层的用处:缩减模型的大小,提高计算速度,同时提高提取特征的鲁棒性。
不需要用梯度下降学习参数,因为进行的是固定的运算。
对每个通道进行最大池化
平均池化
在神经网络中,最大池化要比平均池化用的多,但是在深度很深的神经网络中,会用到平均池化。
f=2,s=2表示输出图像的高和宽是输入图像的高和宽的一半,比较常用。
不需要学习参数,只要设置超级参数。
(十)全连接层(fully connected layer)
全连接层和普通神经网络是一样的
(十一)卷积网络示例
池化层不含参数W和b,所以不单独记为一层,而是和卷积层共同看作一层。
激活函数值下降的很快的话,会影响神经网络的性能。
(十一)为什么使用卷积神经网络
相比全连接层,卷积神经网络的两个特点
参数共享
连接稀疏
二、代码实现
这里使用的是keras
(一)导入数据集
import h5py
train_dataset=h5py.File('/Users/renjianmei/Downloads/深度学习/未命名文件夹/第三周/datasets/train_signs.h5', "r")
test_dataset = h5py.File('/Users/renjianmei/Downloads/深度学习/未命名文件夹/第三周/datasets/test_signs.h5', "r")
导入的h5py文件属于字典形式
(二)数据预处理
1.对X进行归一化处理
train_set_x=train_dataset['train_set_x'][:]
train_set_y=train_dataset['train_set_y'][:]
classes1=train_dataset['list_classes'][:]
test_set_x = test_dataset["test_set_x"][:]
test_set_y = test_dataset["test_set_y"][:]
#classes2 = test_dataset["list_classes"][:]
对于图像数据,通常除以255进行归一化处理。
train_x=train_set_x/255
test_x=test_set_x/255
查看数据维度
train_y=train_set_y.reshape(train_set_y.shape[0],-1)
test_y=test_set_y.reshape(test_set_y.shape[0],-1)
(三)one_hot函数
def convert_to_one_hot(Y, C):
"""
Y————标签变量,维度为(m,1)其中m为样本量
C————类别数
返回 Y————维度为(m,C)
"""
Y = np.eye(C)[Y.reshape(-1)]
return Y
1.对y进行ONE-HOT处理
train_y=convert_to_one_hot(train_y, len(classes1))
test_y=convert_to_one_hot(test_y,len(classes1) )
(四)keras构建卷积框架
1.keras.models.Sequential()
是一个容器,描述了神经网络的网络结构,在Sequential()中的输入参数描述了从输入层到输出层的网络结构。输入参数即可直接写在Sequential()中,也可通过add()添加。通常为了便于读懂代码,使用add()来添加参数
import tensorflow as tf
from tensorflow import keras
model = keras.models.Sequential() #描述各层网络
2.model.add()
添加卷积层、池化层、全连接层
(1)卷积层keras.layers.Conv2D
卷积层过滤器的维度(高度,宽度,通道数,过滤器数)
这里指定为(3,3,n_c,32),n_c与输入层的通道数相同
model.add(keras.layers.Conv2D(filters=32,kernel_size=3,padding='same',activation='relu',input_shape=(64,64,3)))
#filters: 卷积核(就是过滤器)的数目
#kernel_size:过滤器的大小,即卷积核(过滤器)的高度和宽度,单个整数或由两个整数构成的list/tuple
#strides: 卷积步长, 默认为 1
#padding: 卷积如何处理边缘。补0策略,选项包括 ‘valid’ 和 ‘same’。默认为 ‘valid’。"valid"不填充
#activation: 激活函数,通常设为 relu
#input_shape: 指定输入层的高度,宽度和深度的元组(高度,宽度,通信数)
(2)最大池化层keras.layers.MaxPool2D()
最大池化层(2,2,n_c),n_c与输入层的通道数相同
model.add(keras.layers.MaxPool2D(pool_size=32,padding='same'))
#pool_size:用于指定池窗口的大小.2个整数的元组/列表:(pool_height,pool_width),可以是单个整数,以指定所有空间维度的值相同.
#strides:用于指定池操作的步幅
#padding:一个字符串,表示填充方法,“valid”或“same”.
#data_format:一个字符串,表示输入维度的顺序.支持channels_last(默认)和channels_first;
#channels_last对应于具有形状(batch, height, width, channels)的输入,而channels_first对应于具有形状(batch, channels, height, width)的输入.
(3)卷积层keras.layers.Conv2D
这里指定为(3,3,n_c,64),n_c与输入层的通道数相同
model.add(keras.layers.Conv2D(filters=64,kernel_size=3,padding='same',activation='relu'))
(4)最大池化层keras.layers.MaxPool2D()
最大池化层(2,2,n_c),n_c与输入层的通道数相同
model.add(keras.layers.MaxPool2D(pool_size=2))
(5)一维化keras.layers.Flatten()
model.add(keras.layers.Flatten())
#用于将输入层的数据压成一维的数据,一般用在卷积层和全连接层之间,因为全连接层只能接收一维数据,卷积层可以处理二维数据
#(m,n_h,n_w,n_c)------( m, n_h*n_w*n_c)
(6)全连接层keras.layers.Dense()
model.add(keras.layers.Dense(6,activation='softmax'))
#输出大小:(batch_size, units)
"""
keras.layers.Dense(units, activation=None, use_bias=True,kernel_initializer='glorot_uniform', bias_initializer='zeros',kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)
#units: 正整数,输出空间维度。
#activation:激活函数.如果不指定该参数,将不会使用任何激活函数(即使用线性激活函数:a(x)=x)
#use_bias: 布尔值,该层是否使用偏置向量
#kernel_initializer: kernel 权值矩阵的初始化器。
#bias_initializer: 偏置向量的初始化器。
"""
output = activation(dot(input, kernel) + bias)
activation 是按逐个元素计算的激活函数
kernel 是由网络层创建的权值矩阵
bias 是其创建的偏置向量 (只在 use_bias 为 True 时才有用)。
3.模型编译model.compile()
model.compile()方法用于在配置训练方法时,告知训练时用的优化器、损失函数和准确率评测标准
model.compile(optimizer='Adam',
loss='mse',
metrics = ['categorical_accuracy'])
4.model.summary()
model.summary()输出模型各层的参数状况
model.summary()
5.model.fit()
history = model.fit(x=X_train,y=Y_train,batch_size=64,epochs=num_epochs)
# validation_split=0.0, #:浮点数0-1之间,用作验证集的训练数据的比例。模型将分出一部分不会被训练的验证数据,并将在每一轮结束时评估这些验证数据的误差和任何其他模型指标。
# validation_data=None, #这个参数会覆盖 validation_split,即两个函数只能存在一个,它的输入为元组 (x_val,y_val),这作为验证数据。
# shuffle=True, #布尔值。是否在每轮迭代之前混洗数据
#batch_size:整数,每次梯度更新的样本数。未指定,默认为32
#epochs:整数,训练模型迭代次数
#verbose:日志展示,整数,0:为不在标准输出流输出日志信息;1:显示进度条;2:每个epoch输出一行记录
6.model.evaluate()
score = model.evaluate(x=X_test,y=Y_test)
model.save('model.h5')
#model.save()保存了模型的图结构和模型的参数,保存模型的后缀是.hdf5
综上代码为
输入数据(m,64,64,3)
→
p
a
d
d
i
n
g
=
′
s
a
m
e
′
卷
积
层
(
3
,
3
,
3
,
32
)
\xrightarrow[padding='same']{卷积层(3,3,3,32)}
卷积层(3,3,3,32)padding=′same′(m,64,64,32)
→
池
化
层
(
2
,
2
,
32
)
\xrightarrow{池化层(2,2,32)}
池化层(2,2,32)(m,32,32,32)
→
p
a
d
d
i
n
g
=
′
s
a
m
e
′
卷
积
层
(
3
,
3
,
32
,
64
)
\xrightarrow[padding='same']{卷积层(3,3,32,64)}
卷积层(3,3,32,64)padding=′same′(m,32,32,64)
→
池
化
层
(
2
,
2
,
32
)
\xrightarrow{池化层(2,2,32)}
池化层(2,2,32)(m,16,16,64)
→
一
维
化
\xrightarrow{一维化}
一维化(m,16*16*64)
→
全
连
接
层
\xrightarrow{全连接层}
全连接层(m,6)$
model = keras.models.Sequential() #描述各层网络
#1.卷积层(3,3,n_c,32),n_c与输入层的通道数相同
model.add(keras.layers.Conv2D(filters=32,kernel_size=3,padding='same',activation='relu',input_shape=(64,64,3)))
#2.最大池化层(2,2,n_c),n_c与输入层的通道数相同
model.add(keras.layers.MaxPool2D(pool_size=2))
#3.卷积层(3,3,n_c,64)
model.add(keras.layers.Conv2D(filters=64,kernel_size=3,padding='same',activation='relu'))
#4.池化层(2,2,n_c)
model.add(keras.layers.MaxPool2D(pool_size=2))
#5.
model.add(keras.layers.Flatten())
#(m,n_h,n_w,n_c)------( m, n_h*n_w*n_c)
#6.全连接层
model.add(keras.layers.Dense(6,activation='softmax'))
#输出大小:(batch_size, units)
model.compile(optimizer='Adam',
loss='mse',
metrics = ['categorical_accuracy'])
model.summary()
history = model.fit(x=train_x,y=train_y,batch_size=64,epochs=100)
score = model.evaluate(x=test_x,y=test_y)
model.save('model.h5')
#model.save()保存了模型的图结构和模型的参数,保存模型的后缀是.hdf5
输出结果为
print('测试集损失值:',str(score[0]*100)[:4]+'%')
print('测试集准确率:',str(score[1]*100)[:4]+'%')
plt.plot(np.squeeze(history.history['loss']))
plt.ylabel('loss')
plt.xlabel('iterations (per tens)')
plt.show()