用CNN实现离散数据的分类。
① 全连接网络中的每一个神经元与前后相邻层的每一个神经元都有连接关系,输入是特征,输出为预测的结果。对识别和预测都有非常好的效果。
② 但是参数较多,很容易使得模型过拟合。
每层的参数:前层神经元个数 x 该层神经元个数 + 该层神经元个数
③ 实际应用时,会先对原始图像进行若干层的特征提取,再把提取到的特征送给全连接网络。卷积计算是一种有效的特征提取方法。
一般会用一个正方形的卷积核,按指定步长,在输入特征图上滑动,遍历输入特征图中的每个像素点。每一个步长,卷积核会与输入特征图出现重合区域,重合区域对应元素相乘求和,再加上偏置项,得到输出特征的一个像素点。
输入特征是灰度图,使用深度为1的单通道卷积核;输入特征是3通道彩色图,使用一个nxnx3的卷积核。总之,要使卷积核与输入特征图的通道数一致。
当前层使用了几个卷积核,就有几张输出特征图。若觉得某层模型的特征提取能力不足,可以在这一层多用几个卷积核提高这一层的特征提取能力。
在执行卷积计算的时候,卷积核里的参数是固定的;在每次反向传播时,这些待训练参数会被梯度下降法更新。
三通道计算过程,三个卷积核在三张图的同一位置进行卷积计算,得到3个结果,求和后加上一个偏置b输出。
输出特征图中的1个像素点,在原始输入图片上映射区域的大小。比如,1个像素点对应原始图片上3 x 3大小的区域,则该像素点的感受野为3.
对于一个5 x 5的特征图,两层3 x 3卷积核和一层5 x 5卷积核都能将其变为一个像素点,说明提取能力是一样的。通过比较参数量和计算量进行选择。当输入特征图边长大于10个像素点时,两层3 x 3卷积核要比一层5 x 5卷积核性能要好。
如果想让卷积计算保持输入特征图的尺寸不变,可以使用全零填充,在输入特征图周围填充0。
全零填充:输出特征图边长 = 入长 / 步长(向上取整)
不全零填充:输出特征图边长 = (入长 - 核长 + 1) / 步长 (向上取整)
注意:不能整除,向上取整,2.2 应该取 3。
tf描述全零填充
padding = 'SAME' # 全零填充
padding = 'VALID' # 不全零填充
# 一层卷积层
tf.keras.layers.Conv2D(
filters=卷积核个数,
kernel_size=卷积核尺寸, # 正方形就写一个整数,或(核高h,核宽w)
strides=滑动步长, # 横纵相同写一个整数,或(纵向步长h,横向步长w),默认1
padding="same" / "valid", # 是否全零填充,默认valid
activation="relu" / "sigmoid" / "tanh" / "softmax", # 如果后面有BN则此处不写
input_shape=(高,宽,通道数) # 输入特征维度,可省略
)
tf.keras.layers.BatchNormalization()
池化用于减少特征数据量。分为最大值池化和均值池化。最大值池化可提取图片纹理,均值池化可保留背景特征。
tf描述池化:
# 最大池化
tf.keras.layers.MaxPool2D(
pool_size=池化核尺寸, # 正方形写一个整数,或(核高h,核宽w)
strides=池化步长, # 横纵相同写一个整数,或(纵向步长h,横向步长w),默认pool_size
padding='same' / 'valid' # 默认valid
)
# 平均池化
tf.keras.layers.AveragePooling2D(
pool_size=2,
strides=2,
padding='same'
)
Dropout:为了缓解神经网络过拟合,在训练过程中,常把隐藏层的部分神经元按照一定的比例,从神经网络中临时舍弃。在使用神经网络时,再把所有神经元恢复到神经网络中。
tf描述舍弃:
tf.keras.layers.Dropout(舍弃的概率)
例子:
tf.keras.layers.Dropout(0.2) # 0.2表示随机舍弃掉20%的神经元
卷积神经网络:借助卷积核提取特征后,送入全连接网络。
主要模块:提取特征(卷积、批标准化、激活、池化)、全连接
卷积就是特征提取器,CABPD
tf描述卷积神经网络
model = tf.keras.models.Sequential([
Conv2D(filters=6, kernel_size=(5, 5), padding='same'), # 卷积层
BatchNormalization(), # BN层
Activation('relu'), # 激活函数
MaxPool2D(pool_size=(2, 2), strides=2, padding='same'), # 池化层
Dropout(0.2) # dropout层
])