0.Attention
上一章用的 mnist 数据集是二值数据集。
本章用的 cifar10 数据集是彩色数据集。
1.知识点
1.1卷积神经网络
卷积神经网络
卷积就是特征提取,就是CBAPD。
from tensorflow.keras.layers import Conv2D, BatchNormalization, Activation, MaxPool2D, Dropout
为何使用卷积神经网络:为了减少待训练参数,先对原始图像进行特征提取,再把提取到的特征送入全连接网络。
1.1.1卷积核
1.1.1.1 感受野(receptive field)
定义:卷积神经网络各输出层每个像素点在原始图像上的映射区域大小。
使用:当我们采用尺寸不同的卷积核时,最大的区别就是感受野的大小不同,所以经常会采用多层小卷积核来替换一层大卷积核,在保持感受野相同的情况下减少参数量和计算量。
例如:十分常见的用 2 层 3
×
\times
× 3 卷积核来替换 1 层 5
×
\times
× 5 卷积核的方法。
1.1.1.2 Dropout
定义:在神经网络训练时,将一部分神经元按照一定概率从神经网络中暂时舍弃,从而减小对W权重的依赖,以达到减小过拟合的效果。神经网络使用时,被舍弃的神经元恢复链接。
注意:dropout只能用在训练中,测试的时候不能dropout,要用完整的网络测试。
大佬链接
1.1.1.3 全零填充(padding)
作用:为了保持输出图像尺寸与输入图像一致,经常会在输入图像周围进行全零填充,在 5 × \times × 5 的输入图像周围填 0,则输出特征尺寸同为 5 × \times × 5。
1.1.1.4 池化(Pooling)
作用:减少特征数据量(降维),减少计算量。
- 最大值池化可提取图片纹理。
- 均值池化可保留背景特征。
1.1.1.5 批标准化(BatchNormalization)
作用:
- 标准化:使数据符合0均值,1为标准差的分布。
- 批标准化:对一小批数据(batch),做标准化处理 。
使用位置:在卷积操作和激活操作之间。
1.1.1.6 激活(Activation)
作用:激活函数给神经元引入了非线性因素,使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以应用到众多的非线性模型中。
如果不用激活函数,每一层输出都是上层输入的线性函数,无论神经网络有多少层,输出都是输入的线性组合,这种情况就是最原始的感知机(Perceptron)。
1.1.2 卷积核计算量
设:输入特征图的宽、高均为 x,卷积计算的步长为 1。
Kernel | 图像经卷积核后输出尺寸 | 输出特征图像计算量 | 卷积核参数计算量 |
---|---|---|---|
2 个 3 × \times × 3 | 第一个 3 × \times × 3 卷积核输出特征图共有 ( x − 3 + 1 ) 2 (x-3+1)^2 (x−3+1)2 个像素点,每个像素点需要进行 3 × \times × 3 = 9 次乘加运算,第二个 3 × \times × 3卷积核输出特征图共有 ( x − 3 + 1 − 3 + 1 ) 2 (x-3+1-3+1)^2 (x−3+1−3+1)2 个像素点,每个像素点同样需要进行 9 次乘加运算。 | 则总计算量为 9 × ( x – 3 + 1 ) 2 + 9 × ( x – 3 + 1 – 3 + 1 ) 2 9\times(x – 3 + 1)^2 + 9 \times(x – 3 + 1 – 3 + 1)^2 9×(x–3+1)2+9×(x–3+1–3+1)2 = 18 x 2 – 108 x + 180 18 x^2 – 108x + 180 18x2–108x+180 | 9 + 9 = 18 |
5 × \times × 5 | 输出特征图共有 ( x − 5 + 1 ) 2 (x-5+1)^2 (x−5+1)2 个像素点 | 每个像素点需要进行 5 × \times × 5 = 25 次乘加运算,则总计算量为:25 × ( x − 5 + 1 ) 2 \times(x-5+1)^2 ×(x−5+1)2 = 25 x 2 – 200 x + 400 25x^2 – 200x + 400 25x2–200x+400 | 25,上面的参数量更少。 |
1.2卷积核的理解
1 × \times × 1卷积操作可通过步长改变特征图尺寸,通过卷积核个数改特征图深度。
2.其他知识点
2.1 python类的使用
2.2 python len()
返回对象(字符, 列表, 元组)长度和项目个数。
2.3 ∗ * ∗arg和 ∗ ∗ ** ∗∗kwarg
∗
*
∗arg和
∗
∗
**
∗∗kwarg的用法
∗
∗
**
∗∗kwarg的用法
这只是编程人员约定的变量名字,args 是 arguments 的缩写,表示位置参数;kwargs 是 keyword arguments 的缩写,表示关键字参数。这其实就是 Python 中可变参数的两种形式,并且
∗
*
∗args 必须放在
∗
∗
**
∗∗kwargs 的前面,因为位置参数在关键字参数的前面。
2.4 python 括号作用
2.5 sigmoid和softmax
sigmoid和softmax的差别:
softmax函数:Normalized exponential function 归一化指数函数(归一化用),对于多分类任务时,只有一个正确答案。
sigmoid函数:sigmoid function s型函数(激活用),对于多分类任务时,有多个正确答案。
差别1
差别2
2.6 tensorflow使用GPU
首先确保已安装 TensorFlow GPU 版本。
tensorflow使用
控制gpu代码:
gpus = tf.config.experimental.list_physical_devices('GPU')
tf.config.experimental.set_virtual_device_configuration(
gpus[0],
[tf.config.experimental.VirtualDeviceConfiguration(memory_limit=1024)])
2.7 经验
2.7.1
https://blog.csdn.net/weixin_43584807/article/details/103093874
# 控制输出的值的个数,np.inf只是为了保证这个阈值足够大,以至于所有长度的数组都能完整打印
np.set_printoptions(threshold=np.inf)
2.7.2
有时batch设置的过大(1024)可能会导致数据收敛的不好,相对batch=32就会大大改善情况,缺点是训练时间长一些。
3.顶会 Paper
neuron network | feature |
---|---|
LeNet | 开篇之作,共享卷积核,减少网路参数。 |
AlexNet | 1.用 relu 激活函数,提升训练速度; 2.使用 Dropout 缓解过拟合。 |
VGGNet | 小尺寸卷积核减少参数,网络结构规整,适合并行加速。 |
Inception 10 | 一层内使用不同尺寸卷积核,提升感知力使用批标准化防止梯度消失 |
ResNet | 层间残差跳连,引入前方信息,缓解模型退化,使模型网络层数加深成为可能 |
3.1 LeNet
CAP -> CAP -> FDDD
3.2 AlexNet
CBAP -> CBAP -> CA -> CA -> CAP -> FDDD
3.3 VGGNet
CBA -> CBAPD -> CBA -> CBAPD -> CBA -> CBA -> CBAPD -> CBA -> CBA -> CBAPD -> CBA -> CBA -> CBAPD -> FDDD
3.4 Inception 10:
3个class:
1.将C、B、 A 这3个操作在Sequential中合并简化后续步骤。
2.每个Inception Block组成一个class
3.将其合并成为真正的Inception10 class
class employee:
perc_raise =1.05
def __init__(self, first, last, sal):
##############################################################
#注意:外部变量传入内部时,在内部创建相应的变量,方便后边相关函数调用
##############################################################
self.fname=first
self.lname=last
self.sal=sal
self.email=first + '.' + last + '@company.com'
def fullname(self):
return '{}{}'.format(self.fname,self.lname)
def apply_raise(self):
self.sal=int(self.sal*1.05)
3.5 ResNet
neuron network | Value |
---|---|
Inception struct block | “+”是沿深度方向叠加(千层蛋糕层数叠加),四个并行子块的叠加。 |
ResNet struct block | “+”是特征图对应元素值相加(矩阵值相加),卷积块和原始块对应数字相加。 |
双方加法位置及函数:
# 在倒数第二行
class InceptionBlk(Model):
def __init__(self, ch, strides=1):
super(InceptionBlk, self).__init__()
self.ch = ch
self.strides = strides
self.c1 = ConvBNRelu(ch, kernelsz=1, strides=strides)
self.c2_1 = ConvBNRelu(ch, kernelsz=1, strides=strides)
self.c2_2 = ConvBNRelu(ch, kernelsz=3, strides=1)
self.c3_1 = ConvBNRelu(ch, kernelsz=1, strides=strides)
self.c3_2 = ConvBNRelu(ch, kernelsz=5, strides=1)
self.p4_1 = MaxPool2D(3, strides=1, padding='same')
self.c4_2 = ConvBNRelu(ch, kernelsz=1, strides=strides)
def call(self, x):
x1 = self.c1(x)
x2_1 = self.c2_1(x)
x2_2 = self.c2_2(x2_1)
x3_1 = self.c3_1(x)
x3_2 = self.c3_2(x3_1)
x4_1 = self.p4_1(x)
x4_2 = self.c4_2(x4_1)
# concat along axis=channel
x = tf.concat([x1, x2_2, x3_2, x4_2], axis=3)
return x
# 在倒数第2行
class ResnetBlock(Model):
def __init__(self, filters, strides=1, residual_path=False):
super(ResnetBlock, self).__init__()
self.filters = filters
self.strides = strides
self.residual_path = residual_path
self.c1 = Conv2D(filters, (3, 3), strides=strides, padding='same', use_bias=False)
self.b1 = BatchNormalization()
self.a1 = Activation('relu')
self.c2 = Conv2D(filters, (3, 3), strides=1, padding='same', use_bias=False)
self.b2 = BatchNormalization()
# residual_path为True时,对输入进行下采样,即用1x1的卷积核做卷积操作,保证x能和F(x)维度相同,顺利相加
if residual_path:
self.down_c1 = Conv2D(filters, (1, 1), strides=strides, padding='same', use_bias=False)
self.down_b1 = BatchNormalization()
self.a2 = Activation('relu')
def call(self, inputs):
residual = inputs # residual等于输入值本身,即residual=x
# 将输入通过卷积、BN层、激活层,计算F(x)
x = self.c1(inputs)
x = self.b1(x)
x = self.a1(x)
x = self.c2(x)
y = self.b2(x)
if self.residual_path:
residual = self.down_c1(inputs)
residual = self.down_b1(residual)
out = self.a2(y + residual) # 最后输出的是两部分的和,即F(x)+x或F(x)+Wx,再过激活函数
return out