从零开始深度学习0521——keras基本知识+GAP理解

时间:2024-03-18 12:06:49

Keras 中经常可以看到

K.image_data_format() == 'channels_first' 

从零开始深度学习0521——keras基本知识+GAP理解

 

 

 

 

深度学习中 Flatten层 的作用 <  GAP

 

Flatten层的实现在Keras.layers.core.Flatten()类中。

作用:

Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。Flatten不影响batch的大小。

 

from keras.models import Sequential

from keras.layers.core import Flatten

from keras.layers.convolutional import Convolution2D

from keras.utils.vis_utils import plot_model

 

model = Sequential()

model.add(Convolution2D(64,3,3,border_mode="same",input_shape=(3,32,32)))

model.add(Flatten())

plot_model(model, to_file='Flatten.png', show_shapes=True)

 

为了更好的理解Flatten层作用,我把这个神经网络进行可视化如下图:

从零开始深度学习0521——keras基本知识+GAP理解

 

 flatten层用来扁平参数用,一般用在卷积层与全链接层之间,可以从vgg16网络中可以看出,但是在后来的网络中用GlobalAveragePooling2D代替了flatten层,可以从vgg16与inceptionV3网络对比看出。从参数的对比可以看出,显然这种改进大大的减少了参数的使用量,避免了过拟合现象。

 

 

GlobalAveragePooling2D 层 全局池化层 还可以不在乎输入图像的大小

 

一般在全连接后会有**函数来做分类,假设这个**函数是一个多分类softmax,那么全连接网络的作用就是将最后一层卷积得到的feature map stretch成向量,对这个向量做乘法,最终降低其维度,然后输入到softmax层中得到对应的每个类别的得分。全连接层如此的重要,以至于全连接层过多的参数重要到会造成过拟合

从零开始深度学习0521——keras基本知识+GAP理解

 

在最后一个卷积层后,加上GAP 不管前面输出是多少  通过GAP后都变成了1*1*chinnal

所以就可以不在乎原始图像输入是多少,然后继续接下往下做

 

去掉fc层 换成GAP 我们叫全卷积神经网络  fully convlation network

 

在卷积层之后,用GAP替代FC全连接层。有两个有点:一是GAP在特征图与最终的分类间转换更加简单自然;二是不像FC层需要大量训练调优的参数,降低了空间参数会使模型更加健壮,抗过拟合效果更佳。

从零开始深度学习0521——keras基本知识+GAP理解

 

假设卷积层的最后输出是h × w × d 的三维特征图,具体大小为6 × 6 × 3,经过GAP转换后,变成了大小为 1 × 1 × 3 的输出值,也就是每一层 h × w 会被平均化成一个值。

 

GAP的使用一般在卷积层之后,输出层之前:

从零开始深度学习0521——keras基本知识+GAP理解

 

GAP GMP Flatten 对比

https://www.cnblogs.com/hutao722/p/10008581.html

 

对GAP的解释

https://www.jianshu.com/p/510072fc9c62

结论:

从本实验看出,在数据集有限的情况下,采用经典模型进行迁移学习时,GMP表现不太稳定,FC层由于训练参数过多,更易导致过拟合现象的发生,而GAP则表现稳定,优于FC层。当然具体情况具体分析,我们拿到数据集后,可以在几种方式中多训练测试,以寻求最优解决方案。

 

 

 

Tensorflow 写法

 

# detach original VGG fc layers and
# reconstruct your own fc layers serve for your own purpose

self.flatten = tf.reshape(pool5, [-1, 7*7*512])
self.fc6 = tf.layers.dense(self.flatten, 256, tf.nn.relu, name='fc6'#tf.layers.dense 可以一步建立最普通的隐藏层
self.out = tf.layers.dense(self.fc6, 1, name='out')

 

 

 

 

 

Dense层 == Fc

Dense即全连接层,逻辑上等价于这样一个函数:

权重W为m*n的矩阵.

输入x为n维向量.

**函数Activation.

偏置bias.

输出向量out为m维向量.

out=Activation(Wx+bias).

即一个线性变化加一个非线性变化产生输出.

 

 

为什么卷积层池化层玩需要将向量进行压缩,扁平

把分布式特征 representation 映射到样本标记空间

就是它把特征representation整合到一起,输出为一个值。

这样做,有一个什么好处?

就是大大减少特征位置对分类带来的影响。

 

举个简单的例子

从零开始深度学习0521——keras基本知识+GAP理解

 

从上图我们可以看出,猫在不同的位置,输出的 feature 值相同,但是位置不同。对于电脑来说,特征值相同,但是特征值位置不同,那分类结果也可能不一样,而这时全连接层 filter 的作用就相当于

喵在哪我不管    我只要喵

于是我让filter去把这个喵找到,实际就是把 feature map 整合成一个值:这个值大,哦,有喵;这个值小,那就可能没喵,和这个喵在哪关系不大了有没有,鲁棒性有大大增强了

因为空间结构特性被忽略了,所以全连接层不适合用于在方位上找 Pattern 的任务,比如 segmentation。

 

 

一些CNN网络最后为什么要有2个全连接层

 

写的太好了,生动,容易理解

https://blog.csdn.net/weixin_40903337/article/details/100074878

泰勒公式都知道吧,意思就是用多项式函数去拟合光滑函数。我们这里的全连接层中一层的一个神经元就可以看成一个多项式,我们用许多神经元去拟合数据分布,但是只用一层 fully-connected layer 有时候没法解决非线性问题,而如果有两层或以上 fully-connected layer 就可以很好地解决非线性问题了。

 

我们都知道,全连接层之前的作用是提取特征,全连接层的作用是分类

从零开始深度学习0521——keras基本知识+GAP理解

 

 

 

random.seed()

seed()方法改变随机数生成器的种子

从零开始深度学习0521——keras基本知识+GAP理解

 

seed()没有参数时,每次生成的随机数是不一样的,而当seed()有参数时,每次生成的随机数是一样的,同时选择不同的参数生成的随机数也不一样

 

做图片分类任务时使用img_to_array

 

image = cv2.imread(imagePath)

image = cv2.resize(image, (norm_size, norm_size))

image = img_to_array(image)

data.append(image)

 

img_to_array是keras下的一个方法,主要作用就是把numpy矩阵中的整数转换成浮点数。

训练和预测时Keras对图片读取处理方式不同,加入img_to_array会降低差距

网络性能影响挺大的,使用了以后val_acc与val_loss更加接近训练acc与loss

 

 

 

 

to_categorical()

 

# convert the labels from integers to vectors

labels = to_categorical(labels, num_classes=CLASS_NUM) 
 

to_categorical就是将类别向量转换为二进制(只有0和1)的矩阵类型表示。其表现为将原有的类别向量转换为独热编码的形式

从零开始深度学习0521——keras基本知识+GAP理解

 

to_categorical最为keras中提供的一个工具方法,从以上代码运行可以看出,将原来类别向量中的每个值都转换为矩阵里的一个行向量,从左到右依次是0,1,2,...8个类别。2表示为[0. 0. 1. 0. 0. 0. 0. 0. 0.],只有第3个为1,作为有效位,其余全部为0。

 

 

 

为什么要用one-hot编码

将离散型特征使用one-hot编码,确实会让特征之间的距离计算更加合理

one-hot编码,是为了更合理地计算欧式距离

 

比如,有一个离散型特征,代表工作类型,该离散型特征,共有三个取值,不使用one-hot编码,其表示分别是x_1 = (1), x_2 = (2), x_3 = (3)。两个工作之间的距离是,(x_1, x_2) = 1, d(x_2, x_3) = 1, d(x_1, x_3) = 2。那么x_1和x_3工作之间就越不相似吗?显然这样的表示,计算出来的特征的距离是不合理。那如果使用one-hot编码,则得到x_1 = (1, 0, 0), x_2 = (0, 1, 0), x_3 = (0, 0, 1),那么两个工作之间的距离就都是sqrt(2).即每两个工作之间的距离是一样的,显得更合理

 

使用onehot的直接原因是现在多分类cnn网络的输出通常是softmax层,而它的输出是一个概率分布,从而要求输入的标签也以概率分布的形式出现,进而算交叉熵之类。

 

对于离散型特征,基于树的方法是不需要使用one-hot编码的,例如随机森林等。基于距离的模型,都是要使用one-hot编码,例如神经网络等。

 

 

在keras中model.fit_generator()和model.fit()有什么区别

 

https://blog.csdn.net/Hodors/article/details/97500808

首先Keras中的fit()函数传入的x_train和y_train是被完整的加载进内存的,当然用起来很方便,但是如果我们数据量很大,那么是不可能将所有数据载入内存的,必将导致内存泄漏,这时候我们可以用fit_generator函数来进行训练。

 

 

 

详细理解全连接层

 

  从零开始深度学习0521——keras基本知识+GAP理解

从零开始深度学习0521——keras基本知识+GAP理解

从零开始深度学习0521——keras基本知识+GAP理解

从零开始深度学习0521——keras基本知识+GAP理解

这一步卷积一个非常重要的作用

就是把分布式特征representation映射到样本标记空间

就是它把特征representation整合到一起,输出为一个值

这样做,有一个什么好处?

就是大大减少特征位置对分类带来的影响

 

为什么全连接层可以实现分类

https://www.cnblogs.com/inception6-lxc/p/9939691.html

 

从零开始深度学习0521——keras基本知识+GAP理解

 

 

运行python3程序 出现如下错误

ModuleNotFoundError: No module named '__main__.model'; '__main__' is not a p

 

不知道原因

直接使用相对路径会出现问题

解决办法是不使用当前路径的  .

from automationtest_frame.output.logger import Logger

同时

1、把automationtest_frame 的上级路径放到系统path里

2、把autimation_frame的上级目录作为工程目录打开