- Alexnet
(一)创新点:
1.成功使用ReLU作为CNN的激活函数,并验证其效果在较深的网络超过了Sigmoid,成功解决了Sigmoid在网络较深时的梯度弥散问题。2.训练时使用Dropout随机忽略一部分神经元,以避免模型过拟合。3.在CNN中使用重叠的最大池化。此前CNN中普遍使用平均池化,AlexNet全部使用最大池化,避免平均池化的模糊化效果。并且AlexNet中提出让步长比池化核的尺寸小,这样池化层的输出之间会有重叠和覆盖,提升了特征的丰富性。4.提出了LRN层,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。
(二) 一些基本的概念:
1.relu改变梯度弥散:梯度弥散的问题很大程度上是来源于激活函数的“饱和”。因为在后向传播的过程中仍然需要计算激活函数的导数,所以一旦卷积核的输出落入函数的饱和区,它的梯度将变得非常小。使用反向传播算法传播梯度的时候,随着传播深度的增加,梯度的幅度会急剧减小,会导致浅层神经元的权重更新非常缓慢,不能有效学习。这样一来,深层模型也就变成了前几层相对固定,只能改变最后几层的浅层模型。
2.用relu的作用:ReLU在一定程度上能够防止梯度消失,但防止梯度消失不是用它的主要原因,主要原因是求导数简单。一定程度是指,右端的不会趋近于饱和,求导数时,导数不为零,从而梯度不消失,但左端问题依然存在,一样掉进去梯度也会消失。
同时relu的时间会快6倍。
3.最大池化层:一个输入224×224×64的图像,经过最大池化后的尺寸变为112×112×64,可以看到池化操作的降维改变的是图像的宽高,而不改变通道数。用最大池化层是因为平均池化层会有模糊化效果。
4.重叠池化:即相邻池化窗口之间会有重叠区域。如果定义池化窗口的大小为sizeX,定义两个相邻池化窗口的水平位移/竖直位移为stride,此时sizeX>stride。传统的filter是不重合的,但是这篇当中是不断重合的。这样的训练效果更好。
5.LRN:LRN全称为Local Response Normalization,即局部响应归一化层,LRN函数类似DROPOUT和数据增强作为relu激励之后防止数据过拟合而提出的一种处理方法。这个函数很少使用,基本上被类似DROPOUT这样的方法取代
(三)实验过程原理
卷积层:5层,全连接层:3层,深度:8层,参数个数:60M,神经元个数:650k,分类数目:1000类
由于当时的显卡容量问题,AlexNet 的60M个参数无法全部放在一张显卡上操作,所以采用了两张显卡分开操作的形式,其中在C3,R1,R2,R3层上出现交互。
在AlexNet中,卷积层是上图所示的C1……C5,一共5层。而每次卷积后的结果在上图中可以看到,比如经过卷积层C1后,原始的图像变成了55X55的尺寸,一共有96个通道,分布在2张3G的显卡上,所以上图中一个立方体的尺寸是55×55×48,48是通道数目(后面会详细的说明),而在这个立方体里面还有一个5×5×48的小立方体,这个就是C2卷积层的核尺寸,48是核的厚度(后面会详细说明)。就能看到它每一层的卷积核尺寸以及每一层卷积之后的尺寸。
(四) 自己理解的难点:
1.C2的卷积核个数即为C3的厚度,这个不符合用双显卡得出的结论:
因为在这里做了通道的合并,也就是一种串接操作,所以一个卷积核卷积的不再是单张显卡上的图像,而是两张显卡的图像串在一起之后的图像,串在一起之后的通道数就是256,所以卷积核的厚度为256。两个GPU相互的交换数据,其他的是不交换的。
2.为什么一开始就是256:因为在一开始的时候要对模型进行统一,将他们的大小统一成同一的256X256。
- VGG16
(一)总体结构:
都有含有5组卷积,每组卷积都使用3X3的卷积核,每组卷积后进行一个2X2最大池化,接下来是三个全连接层.在训练高级别的网络时,可以先训练低级别的网络,用前者获得的权重初始化高级别的网络,可以加速网络的收敛。
虽然从A到E每一级网络逐渐变深,但是网络的参数量并没有增长很多,这是因为参数量主要都消耗在最后3个全连接层。
前面的卷积部分虽然很深,但是消耗的参数量不大,不过训练比较耗时的部分依然是卷积,因其计算量比较大。
其中的D、E也就是我们常说的VGGNet-16和VGGNet-19。
训练时,输入是大小为224*224的RGB图像,预处理只有在训练集中的每个像素上减去RGB的均值。
C很有意思,相比B多了几个11的卷积层,11卷积的意义主要在于线性变换,而输入通道数和输出通道数不变,没有发生降维。
在预测时,VGG采用Multi-Scale的方法,将图像scale到一个尺寸Q,并将图片输入卷积网络计算。然后在最后一个卷积层使用滑窗的方式进行分类预测,将不同窗口的分类结果平均,再将不同尺寸Q的结果平均得到最后结果,这样可提高图片数据的利用率并提升预测准确率。在训练中,VGGNet还使用了Multi-Scale的方法做数据增强,将原始图像缩放到不同尺寸S,然后再随机裁切224´224的图片,这样能增加很多数据量,对于防止模型过拟合有很不错的效果。
(二)实际运用:
主要是完成了对于VGG16的实际运用,实际使用数据量很小,所以使用的参数进行自己的调试:
model.add(Conv2D(45,(3,3),activation = ‘relu’,padding = ‘same’,input_shape=(1,1,8),kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
#进行一次归一化
model.add(BatchNormalization())
model.add(Dropout(0.05))
#layer2 323264
model.add(Conv2D(45, (3, 3), padding=‘same’,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
#下面两行代码是等价的,#keras Pool层有个奇怪的地方,stride,默认是(22),
#padding默认是valid,在写代码是这些参数还是最好都加上,这一步之后,输出的shape是161664
#model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(MaxPooling2D(pool_size=2,strides=(2,2),padding=‘same’))
#layer3 161664
model.add(Conv2D(30, (3, 3), padding=‘same’,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
model.add(Dropout(0.05))
#layer4 1616128
model.add(Conv2D(30, (3, 3), padding=‘same’,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=1))
#layer5 88128
model.add(Conv2D(15, (3, 3), padding=‘same’,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
model.add(Dropout(0.05))
#layer6 88256
model.add(Conv2D(15, (3, 3), padding=‘same’,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
model.add(Dropout(0.05))
#layer7 88256
model.add(Conv2D(15, (3, 3), padding=‘same’,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=1))
#layer8 44256
model.add(Conv2D(15, (3, 3), padding=‘same’,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
model.add(Dropout(0.05))
#layer9 44512
model.add(Conv2D(15, (3, 3), padding=‘same’,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
model.add(Dropout(0.05))
#layer10 44512
model.add(Conv2D(15, (3, 3), padding=‘same’,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=1))
#layer11 22512
model.add(Conv2D(15, (3, 3), padding=‘same’,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
model.add(Dropout(0.05))
#layer12 22512
model.add(Conv2D(15, (3, 3), padding=‘same’,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
model.add(Dropout(0.05))
#layer13 22512
model.add(Conv2D(15, (3, 3), padding=‘same’,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=1))
model.add(Dropout(0.05))
#layer14 11*512
model.add(Flatten())
model.add(Dense(15,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
#layer15 512
model.add(Dense(15,kernel_regularizer=regularizers.l2(weight_decay)))
model.add(Activation(‘relu’))
model.add(BatchNormalization())
#layer16 512
model.add(Dropout(0.05))
model.add(Dense(1))
model.add(Activation(‘sigmoid’))
model.summary()
model.compile(optimizer=‘adam’,
loss=‘binary_crossentropy’,
metrics=[‘accuracy’])
model.fit(X_train,y_train,epochs=10, batch_size=5, verbose=1)