当前位置:   article > 正文

dl----算法常识100例_转置卷积和上采样再卷积的区别

转置卷积和上采样再卷积的区别

1.depthwise卷积&&Pointwise卷积
depthwise与pointwise卷积又被称为Depthwise Separable Convolution,与常规卷积不同的是此卷积极大地减少了参数数量,同时保持了模型地精度,depthwise操作是先进行二维平面上地操作,然后利用pointwise进行维度上的更新。

2. 1*1的卷积核有什么作用
实现不同通道数据之间的计算,降维、升维、跨通道交互、增加非线性,大大减少了参数量,其次,增加的1X1卷积后面也会跟着有非线性激励,这样同时也能够提升网络的表达能力
意义:实现了不同通道同一位置的信息融合,可以实现通道数的降维或升维
在这里插入图片描述

3. 反卷积相比其他上采样层的缺点,棋盘格现象怎么产生的
上采样可以扩大输入图像的尺寸,将一个小分辨率的图像扩展成一个高分辨率的图像。在YOLOv4模型中,上采样被加入卷积网络中,作为中间层使用,扩展特征图尺寸,便于张量拼接,上采样常用的方法有双线性插值法,反卷积(也称转置卷积)法和上池化法。
正向卷积:
在这里插入图片描述
反向卷积
在这里插入图片描述
在上采样使用反卷积的时候,卷积核的大小不能被步长整除导致的。处理方法:多层反卷积;反卷积后面接个步长为1的卷积;调整kernel权重分布;采取可以被stride整除的kernel size;调整图像大小(使用最近邻插值或双线性插值),然后执行卷积操作。

4.3D卷积和2D卷积的区别,主要存在问题,如何加速运算,视频理解的sota方法,还有什么方向可以改进
2D卷积可以分为单通道卷积和多通道卷积
3D卷积由于Convolution Filter只能在高度和宽度方向上移动,因此仍被称为2D卷积,一个Filter和一张图像卷积只能生成一个通道的输出数据。
3D卷积使用的数据和2D卷积最大的不同就在于数据的时序性。3D卷积中的数据通常是视频的多个帧或者是一张医学图像的多个分割图像堆叠在一起,这样每帧图像之间就有时间或者空间上的联系

5.卷积核大小如何选取
卷积就是把卷积核放在输入上进行滑窗,将当前卷积核覆盖范围内的输入与卷积核相乘,值进行累加,得到当前位置的输出,其本质在于融合多个像素值的信息输出一个像素值,本质上是下采样的,所以输出的大小必然小于输入的大小。
卷积核一般都是奇数*奇数 ,奇数尺寸的卷积核便于用中心定位;实现same convolution(n + padding - k + 1 = n) ,若 k 为偶数,那么padding就为奇数,就不能平均分配到卷积张量两边;卷积核越小,所需要的参数和计算量越少;

6.卷积层减少参数的方法,使用13,31代替3*3的原理是什么
非对称卷积通常用于逼近现有的正方形卷积以进行模型压缩和加速,可以将标准的dd卷积分解1d为和d*1卷积,以减少参数量。其背后的理论相当简单:如果二维卷积核的秩为1,则运算可等价地转换为一系列一维卷积。然而,由于深度网络中下学习到的核具有分布特征值,其内在秩比实际中的高,因此直接将变换应用于核会导致显著的信息损失。

7.设计一个在CNN卷积核上做dropout的方式
卷积层一般使用BN,不适用dropout,Dropout一般放在全连接层防止过拟合,提高模型返回能力,由于卷积层参数较少,很少有放在卷积层后面的情况,卷积层一般使用batch norm。

8.反卷积转置卷积的实现原理
反卷积,也叫转置卷积,它并不是正向卷积的完全逆过程。反卷积是一种特殊的正向卷积,先按照一定的比例通过补0来扩大输入图像的尺寸,接着旋转卷积核,再进行正向卷积。

9.Dropout的原理,dropout和BN对比
Dropout说的简单一点就是:我们在前向传播的时候,让某个神经元的激活值以一定的概率p停止工作,这样可以使模型泛化性更强,因为它不会太依赖某些局部的特征。
相同点:都有正则化的效果。二者的机制是有差别的。过拟合的原因,就是使用了对问题而言过于复杂的表述,所以缓解过拟合的基本方法就是降低对问题表述的复杂度。
不同点:BN实现这一点的机制是尽量在一个更平滑的解子空间中寻找问题的解,强调的是处理问题的过程的平滑性,隐含的思路是更平滑的解的泛化能力更好,Dropout是强调的鲁棒性,即要求解对网络配置的扰动不敏感,隐含思路是更鲁棒的解泛化能力更好。从这个机制看,Dropout对过拟合的控制机制实际上更直接更表面化更简单粗暴,而BN则要间接一点,但是更底层更本质。但是二者的机制有差别又有重叠,平滑和鲁棒二者常常是一致的,但又不完全一致,不能简单说哪个效果更好,但从机制上看,BN的思想在统计上似乎应该更好一点,但是由于BN用于约束平滑性的手段本身并不完备,只是选用了一种控制模式,所以并不能完全体现其控制平滑性的思想,所以BN对泛化性能的实际影响也不是非常大。

10.直接转置卷积和先上采样再卷积的区别

  1. 上采样过程(使用插值的方法)。如果后面拼接一个卷积,其感受野大小基本保持不变。如果是多个卷积其感受野还是会增大。 2. 上采样过程中复制的点,也具有和原始特征点相同的感受野。也就是本层中的两个完全相同的特征点的感受野等价于上一层的一个特征点的感受野。直接转置卷积的感受野相同。
  2. 反卷积: 一维-> 多维立方 ->重叠融合;上采样+卷积: 一维变 多维 变一维。

11.maxpooling怎么传递导数
maxpooling的反向传播是把梯度直接传给前一层某一个像素,而其他像素不接受梯度,也就是为0。max pooling的前向传播是把patch中最大的值传递给后一层,而其他像素的值直接被舍弃掉。

12.CNN里面池化的作用
平均池化:倾向于保留突出背景特征;
最大池化:倾向于保留突出纹理特征;
卷积的作用就是为了提取某些指定的特征,而池化就是为了进一步抽取更高阶的特征。通过池化操作忽略一些细节信息,强行让CNN学到的更多我们想要的高阶信息。

13.反向传播的时候怎么传递pooling的导数
max pooling: 下一层的梯度会原封不动地传到上一层最大值所在位置的神经元,其他位置的梯度为0;
average pooling: 下一层的梯度会平均地分配到上一层的对应相连区块的所有神经元。

14.卷积神经网络在maxpooling怎么处理反向传播误差
在卷积神经网络中,无论是max pooling还是mean pooling,都没有需要学习的参数。因此,在卷积神经网络的训练中,Pooling层需要做的仅仅是将误差项传递到上一层,而没有梯度的计算。对于max pooling,下一层的误差项的值会原封不动的传递到上一层对应区块中的最大值所对应的神经元,而其他神经元的误差项的值都是0。

15. shufflenet的结构
第一代模型主要核心为分组卷积和通道打乱,第二代模型主要核心为通道分割和通道打乱。
第二代模型是在四条提速规则下对第一代模型进行调整的结果,论文说在同等复杂度下,shufflenet v2比shufflenet和mobilenetv2更准确。这四条准则如下:(G1)同等通道大小最小化内存访问量 对于轻量级CNN网络,常采用深度可分割卷积(depthwise separable convolutions),其中点卷积( pointwise convolution)即1x1卷积复杂度最大。这里假定输入和输出特征的通道数分别为C1和C2,经证明仅当C1=C2时,内存使用量(MAC)取最小值,这个理论分析也通过实验得到证实。(G2)过量使用组卷积会增加MAC 组卷积(group convolution)是常用的设计组件,因为它可以减少复杂度却不损失模型容量。但是这里发现,分组过多会增加MAC。(G3)网络碎片化会降低并行度 一些网络如Inception,以及Auto ML自动产生的网络NASNET-A,它们倾向于采用“多路”结构,即存在一个lock中很多不同的小卷积或者pooling,这很容易造成网络碎片化,减低模型的并行度,相应速度会慢,这也可以通过实验得到证明。(G4)不能忽略元素级操作 对于元素级(element-wise operators)比如ReLU和Add,虽然它们的FLOPs较小,但是却需要较大的MAC。这里实验发现如果将ResNet中残差单元中的ReLU和shortcut移除的话,速度有20%的提升。

16. 深度网络attention怎么加
通道注意力
![在这里插入图片描述](https://img-blog.csdnimg.cn/7187548b3e8b455d8406645e75dd9a7f.png在这里插入图片描述首先将feature map在spatial维度上进行压缩,得到一个一维矢量,后对输入feature map进行spatial维度压缩,作者同时考虑了average pooling和max pooling,通过两个pooling函数以后总共可以得到两个一维矢量。global average pooling对feature map上的每一个像素点都有反馈,而global max pooling在进行梯度反向传播计算只有feature map中响应最大的地方有梯度的反馈,能作为GAP的一个补充。
空间注意力
在这里插入图片描述首先,还是使用average pooling和max pooling对输入feature map进行压缩操作,只不过这里的压缩变成了通道层面上的压缩,对输入特征分别在通道维度上做了mean和max操作。最后得到了两个二维的feature,将其按通道维度拼接在一起得到一个通道数为2的feature map,之后使用一个包含单个卷积核的隐藏层对其进行卷积操作,要保证最后得到的feature在spatial维度上与输入的feature map一致.
连接方式对比:
在这里插入图片描述mini_xception网络架构:

def mini_XCEPTION(input_shape, num_classes, l2_regularization=0.01):
    regularization = l2(l2_regularization)

    # base
    img_input = Input(input_shape)
    x = Conv2D(8, (3, 3), strides=(1, 1), kernel_regularizer=regularization,
                                            use_bias=False)(img_input)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = Conv2D(8, (3, 3), strides=(1, 1), kernel_regularizer=regularization,
                                            use_bias=False)(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)

    # module 1
    residual = Conv2D(16, (1, 1), strides=(2, 2),
                      padding='same', use_bias=False)(x)
    residual = BatchNormalization()(residual)
    x = SeparableConv2D(16, (3, 3), padding='same',
                        kernel_regularizer=regularization,
                        use_bias=False)(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = SeparableConv2D(16, (3, 3), padding='same',
                        kernel_regularizer=regularization,
                        use_bias=False)(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x)
    x = layers.add([x, residual])

    # module 2
    residual = Conv2D(32, (1, 1), strides=(2, 2),
                      padding='same', use_bias=False)(x)
    residual = BatchNormalization()(residual)
    x = SeparableConv2D(32, (3, 3), padding='same',
                        kernel_regularizer=regularization,
                        use_bias=False)(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = SeparableConv2D(32, (3, 3), padding='same',
                        kernel_regularizer=regularization,
                        use_bias=False)(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x)
    x = layers.add([x, residual])

    # module 3
    residual = Conv2D(64, (1, 1), strides=(2, 2),
                      padding='same', use_bias=False)(x)
    residual = BatchNormalization()(residual)
    x = SeparableConv2D(64, (3, 3), padding='same',
                        kernel_regularizer=regularization,
                        use_bias=False)(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = SeparableConv2D(64, (3, 3), padding='same',
                        kernel_regularizer=regularization,
                        use_bias=False)(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x)
    x = layers.add([x, residual])

    # module 4
    residual = Conv2D(128, (1, 1), strides=(2, 2),
                      padding='same', use_bias=False)(x)
    residual = BatchNormalization()(residual)
    x = SeparableConv2D(128, (3, 3), padding='same',
                        kernel_regularizer=regularization,
                        use_bias=False)(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = SeparableConv2D(128, (3, 3), padding='same',
                        kernel_regularizer=regularization,
                        use_bias=False)(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x)
    x = layers.add([x, residual])

    x = Conv2D(num_classes, (3, 3),
            #kernel_regularizer=regularization,
            padding='same')(x)
    x = GlobalAveragePooling2D()(x)
    output = Activation('softmax',name='predictions')(x)

    model = Model(img_input, output)
    return model

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

cbam模块定义

from tensorflow.keras import backend as K
from tensorflow.keras.layers import GlobalAveragePooling2D, GlobalMaxPooling2D, Reshape, Dense, multiply, Permute, Concatenate, Conv2D, Add, Activation, Lambda

''' 通道注意力机制:
    对输入feature map进行spatial维度压缩时,作者不单单考虑了average pooling,
    额外引入max pooling作为补充,通过两个pooling函数以后总共可以得到两个一维矢量。
    global average pooling对feature map上的每一个像素点都有反馈,而global max pooling
    在进行梯度反向传播计算只有feature map中响应最大的地方有梯度的反馈,能作为GAP的一个补充。
'''
def channel_attention(input_feature, ratio=8):

    channel_axis = 1 if K.image_data_format() == "channels_first" else -1
    channel = input_feature.shape[channel_axis]

    shared_layer_one = Dense(channel // ratio,
                             kernel_initializer='he_normal',
                             activation='relu',
                             use_bias=True,
                             bias_initializer='zeros')

    shared_layer_two = Dense(channel,
                             kernel_initializer='he_normal',
                             use_bias=True,
                             bias_initializer='zeros')

    avg_pool = GlobalAveragePooling2D()(input_feature)
    avg_pool = Reshape((1, 1, channel))(avg_pool)
    assert avg_pool.shape[1:] == (1, 1, channel)
    avg_pool = shared_layer_one(avg_pool)
    assert avg_pool.shape[1:] == (1, 1, channel // ratio)
    avg_pool = shared_layer_two(avg_pool)
    assert avg_pool.shape[1:] == (1, 1, channel)

    max_pool = GlobalMaxPooling2D()(input_feature)
    max_pool = Reshape((1, 1, channel))(max_pool)
    assert max_pool.shape[1:] == (1, 1, channel)
    max_pool = shared_layer_one(max_pool)
    assert max_pool.shape[1:] == (1, 1, channel // ratio)
    max_pool = shared_layer_two(max_pool)
    assert max_pool.shape[1:] == (1, 1, channel)

    cbam_feature = Add()([avg_pool, max_pool])
    cbam_feature = Activation('hard_sigmoid')(cbam_feature)

    if K.image_data_format() == "channels_first":
        cbam_feature = Permute((3, 1, 2))(cbam_feature)

    return multiply([input_feature, cbam_feature])

''' 空间注意力机制:
    还是使用average pooling和max pooling对输入feature map进行压缩操作,
    只不过这里的压缩变成了通道层面上的压缩,对输入特征分别在通道维度上做了
    mean和max操作。最后得到了两个二维的feature,将其按通道维度拼接在一起
    得到一个通道数为2的feature map,之后使用一个包含单个卷积核的隐藏层对
    其进行卷积操作,要保证最后得到的feature在spatial维度上与输入的feature map一致,
'''
def spatial_attention(input_feature):
    kernel_size = 7

    if K.image_data_format() == "channels_first":
        channel = input_feature.shape[1]
        cbam_feature = Permute((2, 3, 1))(input_feature)
    else:
        channel = input_feature.shape[-1]
        cbam_feature = input_feature

    avg_pool = Lambda(lambda x: K.mean(x, axis=3, keepdims=True))(cbam_feature)
    assert avg_pool.shape[-1] == 1
    max_pool = Lambda(lambda x: K.max(x, axis=3, keepdims=True))(cbam_feature)
    assert max_pool.shape[-1] == 1
    concat = Concatenate(axis=3)([avg_pool, max_pool])
    assert concat.shape[-1] == 2
    cbam_feature = Conv2D(filters=1,
                          kernel_size=kernel_size,
                          activation='hard_sigmoid',
                          strides=1,
                          padding='same',
                          kernel_initializer='he_normal',
                          use_bias=False)(concat)
    assert cbam_feature.shape[-1] == 1

    if K.image_data_format() == "channels_first":
        cbam_feature = Permute((3, 1, 2))(cbam_feature)

    return multiply([input_feature, cbam_feature])

def cbam_block(cbam_feature, ratio=8):
    """Contains the implementation of Convolutional Block Attention Module(CBAM) block.
    As described in https://arxiv.org/abs/1807.06521.
    """
    # 实验验证先通道后空间的方式比先空间后通道或者通道空间并行的方式效果更佳
    cbam_feature = channel_attention(cbam_feature, ratio)
    cbam_feature = spatial_attention(cbam_feature, )
    
    return cbam_feature

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96

module 2添加attention

 # module 2
    residual = Conv2D(32, (1, 1), strides=(2, 2),
                      padding='same', use_bias=False)(x)
    residual = BatchNormalization()(residual)
    cbam = cbam_block(residual)  # 接cbam模块
    x = SeparableConv2D(32, (3, 3), padding='same',
                        kernel_regularizer=regularization,
                        use_bias=False)(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = SeparableConv2D(32, (3, 3), padding='same',
                        kernel_regularizer=regularization,
                        use_bias=False)(x)
    x = BatchNormalization()(x)
    x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x)
    x = layers.add([x, residual, cbam]) #模块添加,concatenate()亦可
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

17.resnet的结构特点以及解决地问题是什么
复杂问题,越深的网络往往有更好的性能,然而随着网络的加深,训练集的准确率反而下降;可以确定这不是由于Overfit造成的(过拟合的情况训练集应该准确率很高);所以作者针对这个问题提出了一种全新的网络,叫深度残差网络,它允许网络尽可能的加深。 理论上,对于“随着网络加深,准确率下降”的问题,Resnet提供了两种选择方式,也就是identity mapping和residual mapping,如果网络已经到达最优,继续加深网络,residual mapping将被push为0,只剩下identity mapping,这样理论上网络一直处于最优状态了,网络的性能也就不会随着深度增加而降低了。
在这里插入图片描述
这两种结构分别针对ResNet34(左图)和ResNet50/101/152(右图),一般称整个结构为一个”building block“。其中右图又称为”bottleneck design”,目的一目了然,就是为了降低参数的数目。看右图,输入是一个3×3×256的特征,第一个步骤用64个1x1的卷积把256维channel降到64维,然后在最后通过1x1卷积恢复到256个channel,整体上用的参数数目:1x1x256x64 + 3x3x64x64 + 1x1x64x256 = 69632,而不使用bottleneck的话参考左图,输入假设是3x3x256,第一步经过256个卷积核3×3×256,第二部再经过256个卷积核3×3×256。所以参数数目: 3x3x256x256x2 = 1179648,差了16.94倍。
在这里插入图片描述

18. 图神经网络的理解
图神经网络划分为五大类别,分别是:图注意力网络(Graph Attention Networks)、图自编码器( Graph Autoencoders)、图生成网络( Graph Generative Networks) 和图时空网络(Graph Spatial-temporal Networks)。
GNN是一种连接模型,通过网络中节点之间的信息传递的方式来获取图中的依存关系,GNN通过从节点任意深度的邻居来更新该节点状态,这个状态能够表示状态信息

19.unet结构,为什么要下采样,上采样
U-Net网络结构与FCN网络结构相似,也分为下采样阶段和上采样阶段。网络中较浅的高分辨率层用来解决像素定位的问题,较深的层用来解决像素分类的问题,从而可以实现图像语义级别的分割。U-Net算法利用Concat拼接层来融合两个过程中对应位置上的特征图,使得解码器在进行上采样时能够获取到更多的高分辨率信息,进而更完善地恢复原始图像中的细节信息,提高分割精度。
在这里插入图片描述下采样:
1.降低显存和计算量,图小了占内存也就小了,运算量也少了。2.增大感受野,使同样3*3的卷积能在更大的图像范围上进行特征提取。大感受野对分割任务很重要,小感受野是做不了多类分割的,而且分割出来的掩膜边界很粗糙!3.多出几条不同程度下采样的分支,可以很方便进行多尺度特征的融合。多级语义融合会让分类很准。下采样可以减少数据量,提高计算效率,同时也可以提取更高层次的特征。上采样则可以增加数据量,恢复图像的分辨率,提高图像的质量。
上采样:
使用插值法放大原图像,从而可以显示在更高分辨率的显示设备上。
在图像分割任务中,下采样可以帮助网络提取更高层次的语义信息,而上采样则可以帮助网络恢复图像的细节信息,从而实现精细的分割效果。

20.resnet v1到v2有什么改进,下采样过程是什么样的,跳跃链接怎么实现,shape如何保持
在这里插入图片描述1)反向传播基本符合假设,信息传递无阻碍;2)BN层作为pre-activation,起到了正则化的作用

21.fpn的结构
FPN 的结构较为简单,可以概括为:特征提取,上采样,特征融合,多尺度特征输出。FPN 的输入为任意大小的图片,输出为各尺度的 feature map。与 U-net 类似, FPN 的整个网络结构分为自底向上 (Bottom-Up) 和自顶向下 (Top-Down) 两个部分,Bottom-Up 是特征提取过程,对应 Unet 中的 Encoder 部分,文中以 Resnet 作为 backbone,Top-Down 将最深层的特征通过层层的上采样,采样至与 Bottom-Up 输出对应的分辨率大小,与之融合后输出 feature map,融合方式为对应位置相加,而 Unet 采用的融合方式为对应位置拼接,关于两者的差异我之前在 Unet 这篇文章中提过,这里就不再赘述。在下图中放大的部分中,包含了 3 个步骤:1. 对上层输出进行 2 倍的上采样,2. 对 Bottom-Up 中与之对应的 feature map 的进行 1x1 卷积,以保证特征 channels 相同,3. 将上面两步的结果相加。

22.roi pooling和roi align的区别
RoI Pooling和RoI Align都是用于处理区域感兴趣(RoI)的方法。RoI Pooling是将RoI区域重新缩放到固定大小的过程,通过对RoI内部像素进行最大值池化来实现。然而,这种方法会引入量化误差,因为它会将RoI的坐标和大小量化为整数值。为了解决这个问题,RoI Align被提出。它消除了RoI Pooling中的量化步骤,通过双线性插值来计算每个采样点的精确值。这种方法在像素级目标检测任务中表现更好,因为它能够更精确地保留RoI中的空间信息

23.resnet的理解和全连接相比有什么区别
ResNet是一种深度卷积神经网络,它通过引入残差学习来解决深度网络的退化问题。它的结构参考了VGG19网络,并通过短路机制加入了残差单元。ResNet的一个重要设计原则是:当feature map大小降低一半时,feature map的数量增加一倍,这保持了网络层的复杂度。ResNet相比普通网络每两层间增加了短路机制,这就形成了残差学习。
与全连接层相比,ResNet使用了global average pool层来替换全连接层。全连接层是指每个神经元都与前一层的所有神经元相连,而global average pool层则是对每个feature map进行全局平均池化,将其压缩为一个值。

24.简述alexnet,vgg,resnet,densenet,googlenet
alexnet:
vgg:
resnet:
densenet:
googlenet:

25.mobileNet v1,v2,shuffleNet v2,xception,denseNet

26.感受野的计算,增加
感受野是卷积神经网络(CNN)每一层输出的特征图(feature map)上的像素点在原始输入图像上映射的区域大小。感受野的计算从最深层开始向浅层计算,逐步计算到第一层(即上图的蓝色层开始向红色层传递计算),所以计算前要知道网络的整体结构和参数。
增加方法:1.增加pooling层,但是会降低准确性(pooling过程中造成了信息损失)2.增大卷积核的kernel size,但是会增加参数 3.增加卷积层的个数,但是会面临梯度消失的问题

27.为什么卷积神经网络适用于图像和视频,还能用于其他领域吗
卷积网络的特点主要是卷积核参数共享,池化操作。参数共享的话的话是因为像图片等结构化的数据在不同的区域可能会存在相同的特征,那么就可以把卷积核作为detector,每一层detect不同的特征,但是同层的核是在图片的不同地方找相同的特征。然后把底层的特征组合传给后层,再在后层对特征整合(一般深度网络是说不清楚后面的网络层得到了什么特征的)。而池化主要是因为在某些任务中降采样并不会影响结果。所以可以大大减少参数量,另外,池化后在之前同样大小的区域就可以包含更多的信息了。综上,所有有这种特征的数据都可以用卷积网络来处理。

28.CNN反向传播细节,怎么过全连接层池化层卷积层
卷积神经网络(CNN)的反向传播算法与全连接神经网络的反向传播算法类似,但是由于CNN中包含卷积层、池化层和全连接层,因此需要分别考虑这些层的反向传播过程。
对于全连接层,其反向传播过程与全连接神经网络的反向传播过程相同。对于池化层,其反向传播过程相对简单。以最大池化为例,池化后的某个值对应于池化前的某个区域,实际上只有该区域中的最大值对池化后的结果有影响,权重为1,而其他值对池化后的结果影响都为0。因此,在反向传播时,池化后某个位置的误差将被传递回该区域中最大值对应的位置,而其他位置的误差均为0。
对于卷积层,其反向传播过程相对复杂。在前向传播中,卷积层的输入是通过卷积核与前一层的输出特征图卷积得来的。在反向传播中,我们需要计算每个卷积核和偏置项的梯度,并更新它们的值。具体来说,我们需要计算损失函数关于每个卷积核和偏置项的偏导数,并利用梯度下降法更新它们的值。

29.CNN里能自然起到防止过拟合的办法
正则化是指修改学习算法,使其降低泛化误差而非训练误差。常用的正则化方法根据具体的使用策略不同可分为:(1)直接提供正则化约束的参数正则化方法,如L1/L2正则化;(2)通过工程上的技巧来实现更低泛化误差的方法,如提前终止(Early stopping)和Dropout;(3)不直接提供约束的隐式正则化方法,如数据增强等。

30.CNN中感受野权值共享是什么意思
把局部连接(感受野)中的每一个卷积核中对应的权值进行共享,就可以进一步减少网络中参数的个数,即下一层每一个像素点是由上一层对应位置的N×N的局部区域图片(也就是感受野)与同一卷积核N×N的权值做内积,加 偏置后 再 经过非线性映射 而来的,至此,网络训练参数的数量不再受原始输入图片大小的影响(因为卷积核固定了,里边的权值多少也就固定了)。
把局部连接(感受野)中的每一个卷积核中对应的权值进行共享,就可以进一步减少网络中参数的个数,即下一层每一个像素点是由上一层对应位置的N×N的局部区域图片(也就是感受野)与同一卷积核N×N的权值做内积,加 偏置后 再 经过非线性映射 而来的,至此,网络训练参数的数量不再受原始输入图片大小的影响(因为卷积核固定了,里边的权值多少也就固定了)

31.BN层的作用,为什么有这个作用,训练和测试时有什么不同,在测试时怎么使用
BN作用是收敛速率增加,可以达到更好的精度。
BN层是一种数据归一化方法,往往用在深度神经网络中激活层之前。其作用可以加快模型训练时的收敛速度,使得模型训练过程更加稳定,避免梯度爆炸或者梯度消失。并且起到一定的正则化作用,几乎代替了Dropout。
在这里插入图片描述
归一化的目的:将数据规整到统一区间,减少数据的发散程度,降低网络的学习难度。BN的精髓在于归一之后,使用r,b作为还原参数,在一定程度上保留原数据的分布。
神经网络中传递的张量数据,其维度通常记为[N, H, W, C],其中N是batch_size,H、W是行、列,C是通道数。
训练时,均值、方差分别是该批次内数据相应维度的均值与方差;推理时,均值、方差是基于所有批次的期望计算所得。

import tensorflow as tf
from tensorflow.python.training import moving_averages
def batch_normalization(input, is_training, name="BN", 
                        moving_decay=0.999, eps=1e-5):
    input_shape = input.get_shape()
    params_shape = input_shape[-1]
    axis = list(range(len(input_shape) - 1))
    with tf.variable_scope(name, reuse=tf.AUTO_REUSE) as scope:
        beta = tf.get_variable('beta',
                               params_shape,
                               initializer=tf.zeros_initializer)
        gamma = tf.get_variable('gamma',
                                params_shape,
                                initializer=tf.ones_initializer)
        moving_mean = tf.get_variable('moving_mean',
                                      params_shape,
                                      initializer=tf.zeros_initializer,
                                      trainable=False
                                      )
        moving_var = tf.get_variable('moving_var',
                                     params_shape,
                                     initializer=tf.ones_initializer,
                                     trainable=False
                                     )
        def train():
            # These ops will only be preformed when training.
            mean, var = tf.nn.moments(input, axis)
            update_moving_mean = moving_averages.assign_moving_average(moving_mean,
                                                                       mean, 
                                                                       moving_decay)
            update_moving_var = moving_averages.assign_moving_average(
                moving_var, var, moving_decay)
            return tf.identity(mean), tf.identity(var)

        mean, var = tf.cond(tf.equal(is_training, True), train,
                                 lambda: (moving_mean, moving_var))

        return tf.nn.batch_normalization(input, mean, var, beta, gamma, eps)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

32.BN层做预测的时候,方差均值怎么算,online learning的时候怎么算
BN层(Batch Normalization)在训练和预测时使用的均值和方差的计算方式是不同的。在训练阶段,BN层会计算每个批次数据的均值和方差,并用它们来对数据进行标准化。在预测阶段,BN层则使用训练数据的全局均值和方差来对数据进行标准化。对于在线学习(online learning),由于每次只有一个样本,因此无法直接计算批次均值和方差。一种常用的方法是使用指数加权移动平均(exponential moving average)来估计全局均值和方差。具体来说,每当有一个新样本时,我们可以根据当前样本和之前估计的全局均值和方差来更新全局均值和方差的估计值。
训练时,均值、方差分别是该批次内数据相应维度的均值与方差;推理时,均值、方差是基于所有批次的期望计算所得

33.BN机制,BN怎么训练
BN(Batch Normalization)层的作用(1)加速收敛,防止梯度消失(2)控制过拟合,可以少用或不用Dropout和正则(3)降低网络对初始化权重不敏感(4)允许使用较大的学习率
对于每个隐层神经元,把逐渐向非线性函数映射后向取值区间极限饱和区靠拢的输入分布强制拉回到均值为0方差为1的比较标准的正态分布,使得非线性变换函数的输入值落入对输入比较敏感的区域,以此避免梯度消失问题。因为梯度一直都能保持比较大的状态,所以很明显对神经网络的参数调整效率比较高,就是变动大,就是说向损失函数最优值迈动的步子大,也就是说收敛地快。方法很简单,道理很深刻。就是说经过BN后,目前大部分Activation的值落入非线性函数的线性区内,其对应的导数远离导数饱和区,这样来加速训练收敛过程。

34.发生梯度消失,梯度爆炸的原因,如何解决
梯度消失:RNN的梯度消失主要是由于链式求导法则引起的。 当右边的每一项都很小时,梯度会随着它进一步反向传播而变得越来越小。 这就导致了梯度消失现象的产生。 如果Wh非常小,当不断进行反向传播时,梯度值会越来越小。梯度消失产生的原因有:一是网络过深,二是采用了不合适的损失函数
梯度爆炸:一般出现在深层网络和权值初始化值太大的情况下。在深层神经网络或循环神经网络中,误差的梯度可在更新中累积相乘。如果网络层之间的梯度值大于 1.0,那么重复相乘会导致梯度呈指数级增长,梯度变的非常大,然后导致网络权重的大幅更新,并因此使网络变得不稳定。梯度爆炸会伴随一些细微的信号,如:①模型不稳定,导致更新过程中的损失出现显著变化;②训练过程中,在极端情况下,权重的值变得非常大,以至于溢出,导致模型损失变成 NaN等等。

梯度消失和梯度爆炸问题都是因为网络太深,网络权值更新不稳定造成的,本质上是因为梯度反向传播中的连乘效应。解决梯度消失、爆炸主要有以下几种方法:(1) pre-training+fine-tunning (2) 梯度剪切:对梯度设定阈值 (3) 权重正则化 (4) 选择relu等梯度大部分落在常数上的激活函数 (5) batch normalization (6) 残差网络的捷径(shortcut) (7)LSTM的“门(gate)”结构

35. CNN网络很大,手机上运行效率不高,如何模型压缩
(1)低秩近似 神经网络的基本运算卷积,实则就是矩阵运算,低秩近似的技术是通过一系列小规模矩阵将权重矩阵重构出来,
以此降低运算量和存储开销。目前有两种常用的方法:一是Toeplitz矩阵 【托普利兹】直接重构权重矩阵,简称为T型矩阵,它是由Bryc、Dembo、Jiang于2006年提出的。托普利兹矩阵的主对角线上的元素相等,平行于主对角线的线上的元素也相等;
二是奇异值分解(SVD),将权重矩阵分解为若干个小矩阵。(2)剪枝与稀疏约束 剪枝是模型压缩领域中一种经典的后处理技术,
典型应用如决策树的前剪枝和后剪枝。剪枝技术可以减少模型参数量,防止过拟合,提升模型泛化能力。剪枝被应用于神经网络中,遵循四个步骤:(1)衡量神经元的重要程度 (2)移除掉一部分不重要的神经元 (3)对网络进行微调 (4)返回第一步(1),进行下一轮剪枝(3)参数量化相比于剪枝操作,参数量化则是一种常用的后端压缩技术。量化就是从权重中归纳出若干个有代表性的权重,由这些代表来表示某一类权重的具体数值。这些“代表”被存储在码本(codebook)中,而原权重矩阵只需记录各自“代表”的索引即可,从而极大地降低了存储开销。类似于数据结构与算法中的并查集,有一个代表,当集合的代表。所以可以看出来,参数量化就是换一种存储方式从而降低模型的存储。(4)二值网络 二值网络可以被视为量化方法的一种极端情况:所有参数的取值只能是**+1或-1**。这种极端的设置,使得二值网络能够获得极大的压缩效益。现有神经网络大多基于梯度下降来训练,但二值网络的权重只有+1或-1,无法直接计算梯度信息,也无法更新权重。一个折中的方法是,网络的前向与反向回传是二值的,而权重的更新则是对单精度权重进行。(5)知识蒸馏 老师教学生 知识蒸馏指的是模型压缩的思想,通过一步一步地使用一个较大的已经训练好的网络去教导一个较小的网络确切地去做什么。将从大而笨重中需要的知识转换到一个小但是更合适部署的模型。知识蒸馏的目的是将一个高精度且笨重的teacher转换为一个更加紧凑的student。具体思路是:训练teacher模型softmax层的超参数获得一个合适的soft target集合(“软标签”指的是大网络在每一层卷积后输出的feature map。),然后对要训练的student模型,使用同样的超参数值尽可能地接近teacher模型的soft target集合,作为student模型总目标函数的一部分,以诱导student模型的训练,实现知识的迁移。据说,不管你模型有多大,只要你能解决问题,知识蒸馏的技术,就能将其迁移到手机中,问题不大。(6)紧凑的网络结构 以上的方法都可以理解为后处理。而紧凑的网络结构方法则是另起炉灶,直接设计短小精悍的结构保证网络的速度与精度。如squeezeNet的Fire Module模块和GoogLeNet的Conv-M模块。

36 欠拟合、过拟合及如何防止过拟合
对训练数据集有很好的拟合(训练误差),同时也希望它可以对未知数据集(测试集)有很好的拟合结果(泛化能力),所产生的测试误差被称为泛化误差。度量泛化能力的好坏,最直观的表现就是模型的过拟合(overfitting)和欠拟合(underfitting)
欠拟合:通过增加网络复杂度或者在模型中增加特征
过拟合:原因:训练数据集样本单一,样本不足;训练数据中噪声干扰过大;模型过于复杂;1.增加数据 2.采用合适的模型(控制模型的复杂度)3.降低特征的数量 4.L1 / L2 正则化 5.dropout 6.Early stopping(提前终止)
CNN在图像识别的过程中有强大的“不变性”规则,即待辨识的物体在图像中的形状、姿势、位置、图像整体明暗度都不会影响分类结果。我们就可以通过图像平移、翻转、缩放、切割等手段将数据库成倍扩充

37 如何计算卷积层的复杂度,卷积层的参数量
卷积层的计算复杂度取决于多个因素,包括输入特征图的大小、卷积核的大小、步长、填充方式和输出特征图的数量。假设输入特征图的大小为 W1​×H1​×D1​,卷积核的大小为 K×K,步长为 S,输出特征图的数量为 D2​,则卷积层的计算复杂度大约为 O(W1​×H1​×D1​×K2×D2​/S2)。
卷积层的参数量取决于卷积核的大小和数量。假设卷积核的大小为 K×K,输入特征图的深度为 D1​,输出特征图的数量为 D2​,则卷积层的参数量为 K2×D1​×D2​。此外,每个输出特征图还有一个偏置项,因此总参数量为 (K2×D1​+1)×D2​。
卷积层的复杂度决定了网络需要训练的时间;卷积层的参数量决定了训练需要多大的内存和显存。

38 计算featuremap的size
卷积层输出的特征图(feature map)的大小取决于输入特征图的大小、卷积核的大小、步长和填充方式。假设输入特征图的大小为 W1​×H1​,卷积核的大小为 K×K,步长为 S,填充大小为 P,则输出特征图的大小为 W2​×H2​,其中 W2​=(W1​−K+2P)/S+1,H2​=(H1​−K+2P)/S+1。
对于池化层,其输出特征图的大小也取决于输入特征图的大小、池化核的大小和步长。假设输入特征图的大小为 W1​×H1​,池化核的大小为 K×K,步长为 S,则输出特征图的大小为 W2​×H2​,其中 W2​=(W1​−K)/S+1,H2​=(H1​−K)/S+1。

39 输入为LL,卷积核为kk,步长为s,padding为p,求输出尺寸,求操作的FLOPS
假设输入特征图的大小为 L×L,卷积核的大小为 k×k,步长为 s,填充大小为 p,则输出特征图的大小为 W2​×H2​,其中 W2​=(L−k+2p)/s+1,H2​=(L−k+2p)/s+1。
对于每个输出特征图中的一个元素,都需要进行 k2 次乘法和 k2−1 次加法。因此,对于整个输出特征图,需要进行 (k2+k2−1)×W2​×H2​=2k2W2​H2​−W2​H2​ 次浮点运算。如果输出特征图的深度为 D2​,则总共需要进行 (2k2−1)D2​W2​H2​ 次浮点运算。

40 在同时考虑pooling,stride,padding的情况下,计算depthwise conv和pointwise conv过程中每一步的计算量和feature map的尺寸
Depthwise卷积和Pointwise卷积是深度可分离卷积(Depthwise Separable Convolution)的两个步骤。
对于Depthwise卷积,假设输入特征图的大小为 W1​×H1​×D1​,卷积核的大小为 K×K,步长为 S,填充大小为 P,则输出特征图的大小为 W2​×H2​×D1​,其中 W2​=(W1​−K+2P)/S+1,H2​=(H1​−K+2P)/S+1。由于Depthwise卷积是对每个输入通道单独进行卷积,因此输出特征图的深度与输入特征图相同。对于每个输出特征图中的一个元素,都需要进行 K2 次乘法和 K2−1 次加法。因此,对于整个输出特征图,需要进行 (K2+K2−1)×W2​×H2​×D1​=(2K2−1)W2​H2​D1​ 次浮点运算。
对于Pointwise卷积,假设输入特征图的大小为 W2​×H2​×D1​,输出特征图的深度为 D2​。由于Pointwise卷积使用的是 1×1 的卷积核,因此输出特征图的大小为 W2​×H2​×D2​。对于每个输出特征图中的一个元素,都需要进行 D1​ 次乘法和 D1​−1 次加法。因此,对于整个输出特征图,需要进行 (D1​+D1​−1)×W2​×H2​×D2​=(2D1​−1)W2​H2​D2​ 次浮点运算。
如果在Depthwise卷积和Pointwise卷积之间还有池化操作,则需要根据池化核的大小和步长来计算池化后特征图的大小。假设池化核的大小为 Kp​×Kp​,步长为 Sp​,则池化后特征图的大小为 Wp​×Hp​×Dp​,其中 Wp​=(W2​−Kp​)/Sp​+1,Hp​=(H2​−Kp​)/Sp​+1。

41 CNN中给定数据维度【c, w, h】,卷积核【k, k】,则输出维度,如果padding=p,输出维度是什么
在CNN中,假设输入特征图的维度为 [C,W,H],其中 C 是通道数,W 和 H 分别是宽度和高度。假设卷积核的大小为 [K,K],填充大小为 P,步长为 S,输出特征图的通道数为 D。则输出特征图的维度为 [D,W2​,H2​],其中 W2​=(W−K+2P)/S+1,H2​=(H−K+2P)/S+1。
42 BP神经网络反向传播求导

43 max pooling梯度求导
最大池化(Max Pooling)层的梯度求导相对简单。在前向传播过程中,最大池化层会对输入特征图的每个区域取最大值,作为输出特征图中对应位置的值。在反向传播过程中,输出特征图中每个位置的误差将被传递回输入特征图中对应区域的最大值所在位置,而其他位置的误差均为0。
举个例子,假设输入特征图为 X,输出特征图为 Y,池化核的大小为 K×K。则对于输出特征图中的一个元素 Yi,j​,其对应于输入特征图中的一个区域 Xi:i+K−1,j:j+K−1​。设 Xm,n​ 为该区域中的最大值,则在反向传播过程中,Yi,j​ 处的误差 δYi,j​ 将被传递回 Xm,n​ 处,即 δXm,n​=δYi,j​。而该区域中其他位置的误差均为0。

44 说一些卷积,用代码实现卷积,并再改成有通道的三维卷积
卷积是一种常用的图像处理操作,它通过在输入图像上滑动一个卷积核并计算加权和来提取特征。下面是一个简单的二维卷积的Python实现,它接受一个二维输入图像和一个二维卷积核,并返回卷积后的输出图像。

import numpy as np
def conv2d(image, kernel):
    m, n = kernel.shape
    if (m == n):
        y, x = image.shape
        y = y - m + 1
        x = x - m + 1
        new_image = np.zeros((y,x))
        for i in range(y):
            for j in range(x):
                new_image[i][j] = np.sum(image[i:i+m, j:j+m] * kernel)
    return new_image
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

对于具有多个通道的三维输入图像,我们可以对每个通道分别进行卷积,然后将结果相加。下面是一个简单的三维卷积的Python实现,它接受一个三维输入图像和一个二维卷积核,并返回卷积后的输出图像。

def conv3d(image, kernel):
    m, n = kernel.shape
    if (m == n):
        z, y, x = image.shape
        y = y - m + 1
        x = x - m + 1
        new_image = np.zeros((y,x))
        for c in range(z):
            for i in range(y):
                for j in range(x):
                    new_image[i][j] += np.sum(image[c][i:i+m, j:j+m] * kernel)
    return new_image
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

45 写一个单通道的图像卷积
下面是一个简单的二维卷积的Python实现,它接受一个二维输入图像和一个二维卷积核,并返回卷积后的输出图像。函数首先计算卷积核的大小,并根据输入图像和卷积核的大小计算输出图像的大小。然后,对于输出图像中的每个元素,都在输入图像上取一个与卷积核大小相同的区域,并将该区域与卷积核进行逐元素乘法,然后求和,得到输出图像中对应位置的值。

import numpy as np

def conv2d(image, kernel):
    m, n = kernel.shape
    if (m == n):
        y, x = image.shape
        y = y - m + 1
        x = x - m + 1
        new_image = np.zeros((y,x))
        for i in range(y):
            for j in range(x):
                new_image[i][j] = np.sum(image[i:i+m, j:j+m] * kernel)
    return new_image
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

46 手写前向传播,反向传播代码
前向传播和反向传播是神经网络训练中的两个重要步骤。前向传播是指将输入数据传递到神经网络中,计算每一层的输出,最终得到预测结果。反向传播是指根据预测结果与真实标签之间的误差,计算每一层的梯度,并更新模型参数。

import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    return x * (1 - x)

def forward_propagation(X, W1, b1, W2, b2):
    Z1 = np.dot(X, W1) + b1
    A1 = sigmoid(Z1)
    Z2 = np.dot(A1, W2) + b2
    A2 = sigmoid(Z2)
    return Z1, A1, Z2, A2

def backward_propagation(X, Y, Z1, A1, Z2, A2, W2):
    m = X.shape[0]
    dZ2 = A2 - Y
    dW2 = np.dot(A1.T, dZ2) / m
    db2 = np.sum(dZ2, axis=0) / m
    dA1 = np.dot(dZ2, W2.T)
    dZ1 = dA1 * sigmoid_derivative(A1)
    dW1 = np.dot(X.T, dZ1) / m
    db1 = np.sum(dZ1, axis=0) / m
    return dW1, db1, dW2, db2

def update_parameters(W1, b1, W2, b2, dW1, db1, dW2, db2, learning_rate):
    W1 -= learning_rate * dW1
    b1 -= learning_rate * db1
    W2 -= learning_rate * dW2
    b2 -= learning_rate * db2
    return W1, b1, W2
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

47 写代码实现BN的内部实现,为什么要用GN,GN,BN,LN,IN的区别
Batch Normalization(BN)是一种常用的神经网络层,它通过对每个批次数据进行标准化来加速训练过程。下面是一个简单的BN层的Python实现,它接受一个批次数据,并返回标准化后的数据。

import numpy as np

def batch_norm_forward(X, gamma, beta, eps):
    N, D = X.shape
    mu = np.mean(X, axis=0)
    Xmu = X - mu
    sq = Xmu ** 2
    var = np.mean(sq, axis=0)
    sqrtvar = np.sqrt(var + eps)
    ivar = 1 / sqrtvar
    Xhat = Xmu * ivar
    gammax = gamma * Xhat
    out = gammax + beta
    cache = (Xhat, gamma, ivar, sqrtvar, var, eps)
    return out, cache

def batch_norm_backward(dout, cache):
    Xhat, gamma, ivar, sqrtvar, var, eps = cache
    N, D = dout.shape
    dbeta = np.sum(dout, axis=0)
    dgammax = dout
    dgamma = np.sum(dgammax * Xhat, axis=0)
    dXhat = dgammax * gamma
    divar = np.sum(dXhat * Xmu, axis=0)
    dXmu1 = dXhat * ivar
    dsqrtvar = -1 / (sqrtvar ** 2) * divar
    dvar = 0.5 * 1 / np.sqrt(var + eps) * dsqrtvar
    dsq = 1 / N * np.ones((N,D)) * dvar
    dXmu2 = 2 * Xmu * dsq
    dX1 = dXmu1 + dXmu2
    dmu = -1 * np.sum(dXmu1 + dXmu2, axis=0)
    dX2 = 1 / N * np.ones((N,D)) * dmu
    dX = dX1 + dX2
    return dX, dgamma, dbeta
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

BN层的内部实现包括两个步骤:前向传播和反向传播。在前向传播过程中,BN层会计算输入数据的均值和方差,并用它们来对数据进行标准化。然后,BN层会对标准化后的数据进行缩放和平移,得到最终的输出。在反向传播过程中,BN层会根据输出误差计算每个参数的梯度,并更新参数。

Group Normalization(GN)、Layer Normalization(LN)和Instance Normalization(IN)都是BN的变种,它们与BN的主要区别在于对数据进行标准化时使用的维度不同。BN是对每个批次数据进行标准化,而GN是对每个组内的数据进行标准化,LN是对每个样本内的所有特征进行标准化,IN则是对每个样本内的每个通道进行标准化。

GN、LN和IN都是为了解决BN在某些情况下表现不佳的问题而提出的。例如,在批次大小较小时,BN可能无法很好地工作,此时可以使用GN、LN或IN来代替BN。

48 用代码展示shuffleNET v2的结构

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, Model
 
#(1)标准卷积块
def conv_block(input_tensor, filters, kernel_size, stride=1):
 
    # 卷积+批标准化+relu激活
    x = layers.Conv2D(filters, kernel_size, 
                      strides = stride,  # 步长
                      padding = 'same',  # strides=1卷积过程中特征图size不变,strides=2卷积过程中size减半
                      use_bias = False)(input_tensor)  # 有BN层就不需要偏置
 
    x = layers.BatchNormalization()(x)  # 批标准化
 
    x = layers.ReLU()(x)  # relu激活
 
    return x  # 返回一次标准卷积后的tensor
 
 
#(2)深度可分离卷积块
def depthwise_conv_block(input_tensor, stride=1):
 
    # 深度可分离卷积+批标准化
    # 不需要传入卷积核个数,输入有几个通道,就有几个卷积核,每个卷积核负责一个通道
    x = layers.DepthwiseConv2D(kernel_size = (3,3),  # 深度卷积核size默认3*3
                               strides = stride,  # 步长
                               padding = 'same',  # strides=1卷积过程中特征图size不变,strides=2卷积过程中size减半
                               use_bias = False)(input_tensor)  # 有BN层就不需要偏置
 
    x = layers.BatchNormalization()(x)  # 批标准化
 
    return x  # 返回深度可分离卷积后的tensor
 
 
#(3)通道重排,跨组信息交融
def channel_shuffle(input_tensor, num=2): # 默认时2组特征:shortcut和卷积后的x
 
    # 先得到输入特征图的shape,b:batch size,h,w:一张图的size,c:通道数
    b, h, w, c = input_tensor.shape
 
    # 确定shape = [b, h, w, num, c//num]。通道维度原来是一个长为c的一维tensor,变成2行n列的矩阵
    # 在通道维度上将特征图reshape为2行n列的矩阵。
    x_reshaped = tf.reshape(input_tensor, [-1, h, w, num, c//num])
 
    # 确定转置的矩形的shape = [b, h, w, c//num, num]
    # 矩阵转置,最后两个维度从2行n列变成n行2列
    x_transposed = tf.transpose(x_reshaped, [0,1,2,4,3])
 
    # 重新排列,shotcut和x的通道像素交叉排列,通道维度重新变成一维tensor
    output = tf.reshape(x_transposed, [-1, h, w, c])
 
    return output  # 返回通道维度交叉排序后的tensor
 
 
#(4)步长=1时的卷积块
def shufflent_unit_1(input_tensor, filters):
 
    # 首先将输入特征图在通道维度上平均分成两份:一部分用于残差连接,一部分卷积提取特征
    shortcut, x = tf.split(input_tensor, 2, axis=-1)  # axis指定轴
    # 现在shotcut和x的通道数都只有原来的二分之一
 
    # 1*1卷积+3*3深度卷积+1*1卷积
    x = conv_block(x, filters//2, kernel_size=(1,1), stride=1)  # 1*1卷积,通道数保持不变
    x = depthwise_conv_block(x, stride=1)  # 3*3深度卷积
    x = conv_block(x, filters//2, kernel_size=(1,1), stride=1)  # 1*1卷积跨通道信息融合
 
    # 堆叠shoutcut和x,要求两个tensor的size相同
    x = tf.concat([shortcut, x], axis=-1)  # 在通道维度上堆叠
 
    # 将堆叠后2组特征图,在通道维度上重新排列
    x = channel_shuffle(x)
 
    return x  # 返回步长为1时的卷积块输出的tensor
 
 
#(5)步长=2时(下采样)的卷积块
def shufflenet_unit_2(input_tensor, out_channel):
 
    # 输入特征图的通道数
    in_channel = input_tensor.shape[-1]
 
    # 首先将输入特征图复制一份,分别用于左右两个分支的卷积
    shortcut = input_tensor
 
    # ① 左分支的卷积部分==深度卷积+逐点卷积,输出特征图通道数等于原通道数
    shortcut = depthwise_conv_block(shortcut, stride=2)  # 特征图size减半
    shortcut = conv_block(shortcut, filters=in_channel, kernel_size=(1,1), stride=1)  # 输出特征图个数不变
 
    # ② 右分支==1*1卷积下降通道数+3*3深度卷积+1*1卷积上升通道数
    x = conv_block(input_tensor, in_channel//2, kernel_size=(1,1), stride=1)
    x = depthwise_conv_block(x, stride=2)
    # 右分支的通道数和左分支的通道数叠加==输出特征图的通道数out_channel
    x = conv_block(x, out_channel-in_channel, kernel_size=(1,1), stride=1)
 
    # ③ 左右分支的输出特征图在通道维度上堆叠,并且output.shape[-1]==out_channel
    output = tf.concat([shortcut, x], axis=-1)
 
    # ④ 堆叠后的2组特征在通道维度上重新排列
    output = channel_shuffle(output)
 
    return output  # 返回步长=2时的输出结果
 
 
#(6)构建shufflenet卷积块
# 一个shuffle卷积块是由一个shufflenet_unit_2下采样单元,和若干个shufflenet_unit_1特征传递单元构成
def stage(input_tensor, filters, n):   # filters代表输出通道数
 
    # 下采样单元
    x = shufflenet_unit_2(input_tensor, out_channel=filters)
 
    # 特征传递单元循环n次
    for i in range(n):
        x = shufflent_unit_1(x, filters=filters)
    
    return x  # 返回一个shufflenet卷积结果
 
 
#(7)构建网络模型
def ShuffleNet(input_shape, classes):
 
    # 构建网络输入的tensor
    inputs = keras.Input(shape=input_shape)
 
    # [224,224,3]==>[112,112,24]
    x = layers.Conv2D(filters=24, kernel_size=(3,3), strides=2, padding='same')(inputs)  # 普通卷积
 
    # [112,112,24]==>[56,56,24]
    x = layers.MaxPooling2D(pool_size=(3,3), strides=2, padding='same')(x)  # 最大池化
 
    # [56,56,24]==>[28,28,116]
    x = stage(x, filters=116, n=3)
 
    # [28,28,116]==>[14,14,232]
    x = stage(x, filters=232, n=7)
 
    # [14,14,232]==>[7,7,464]
    x = stage(x, filters=464, n=3)
 
    # [7,7,464]==>[7,7,1024]
    x = layers.Conv2D(filters=1024, kernel_size=(1,1), strides=1, padding='same')(x)  # 1*1普通卷积
 
    # [7,7,1024]==>[None,1024]
    x = layers.GlobalAveragePooling2D()(x)  # 在通道维度上全局平均池化
 
    # 按论文输出层使用全连接层,也可改为卷积层再Reshape
    logits = layers.Dense(classes)(x)  # 为了网络稳定,训练时再使用Softmax函数
 
    # 完成网络架构
    model = Model(inputs, logits)
 
    return model  # 返回网络模型
 
 
#(8)接收网络模型
if __name__ == '__main__':
 
    model = ShuffleNet(input_shape=[224,224,3],  # 输入图像的shape
                       classes=1000)  # 图像分类类别
 
    model.summary()  # 查看网络结构
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161

49 实现一维数组的maxpool

import numpy as np

def maxpool1d(arr, pool_size, stride):
    n = len(arr)
    output_size = (n - pool_size) // stride + 1
    output = np.zeros(output_size)
    for i in range(output_size):
        start = i * stride
        end = start + pool_size
        output[i] = np.max(arr[start:end])
    return output
    
arr = np.array([1, 3, 2, 4, 5, 2, 1])
pool_size = 3
stride = 1
output = maxpool1d(arr, pool_size, stride)
print(output) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

50 说一下softmax多分类器的作用,和二分类相比有什么特点
Softmax 多分类器是一种常用的分类算法,它可以将一组输入数据分配到多个类别中。Softmax 函数将一组实数映射到另一组实数,这些实数的和为 1,因此可以将它们解释为概率。在多分类问题中,Softmax 函数通常用于计算每个类别的概率。与二分类问题相比,多分类问题的一个特点是类别之间可能存在层次关系或相互依赖关系。例如,在手写数字识别问题中,数字 4 和数字 9 可能更容易混淆,因为它们在视觉上更相似。Softmax 多分类器可以捕捉这些关系,并为每个类别分配一个概率值。此外,Softmax 多分类器还可以处理不平衡数据集。在二分类问题中,如果一个类别的样本数量远远大于另一个类别,则分类器可能会倾向于将所有样本都分配到数量较多的类别中。但在多分类问题中,Softmax 分类器可以通过调整每个类别的权重来解决这个问题。总之,Softmax 多分类器是一种强大的分类算法,它可以处理多个类别之间的关系,并能够处理不平衡数据集。
二分类一般用sigmoid函数进行分类,也叫Logistic函数,可以将实数映射到(0,1)之间,函数表达式为g(z) = 1/(1+e(-z));softmax多分类器则是可以预测每个类别的概率,公式为softmax(zi) = exp(zi)/sum(exp(zj),代码实现为:

def softmax(a):
	c = np.max(a)
	exp_a = np.exp(a - c) 
	sum_exp_a = np.sum(exp_a)
	y = exp_a / sum_exp_a
	return y
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

51 为何定义backbone、neck 和 head
Backbone: backbone是模型的主要组成部分,通常是一个卷积神经网络(CNN)或残差神经网络(ResNet)等。backbone 负责提取输入图像的特征,以便后续的处理和分析。backbone 通常具有许多层和许多参数,可以提取出图像的高级特征表示。
Neck: neck是连接 backbone 和 head 的中间层。neck 的主要作用是对来自 backbone 的特征进行降维或调整,以便更好地适应任务要求。neck 可以采用卷积层、池化层或全连接层等。
Head: head是模型的最后一层,通常是一个分类器或回归器。head 通过输入经过 neck 处理过的特征,产生最终的输出。head 的结构根据任务的不同而不同,例如对于图像分类任务,可以使用 softmax 分类器;对于目标检测任务,可以使用边界框回归器和分类器等。
深度学习中常用的Backbone:
AlexNet:AlexNet是在2012年ImageNet挑战赛中首次引入的CNN,具有8层神经网络。
VGG:VGG是由Simonyan和Zisserman于2014年提出的一种卷积神经网络,它采用小尺寸的3×3卷积核来替代传统的5×5或7×7卷积核。
ResNet:ResNet是由Microsoft Research Asia在2015年提出的一种卷积神经网络,通过引入残差连接解决了深度神经网络中的梯度消失问题。
Inception系列网络:Inception系列网络是由Google在2014年提出的一种卷积神经网络,其特点是使用多个不同大小的卷积核来提取不同层次的特征。
MobileNet:MobileNet是一种轻量级的卷积神经网络,可以在移动设备上快速运行,它使用深度可分离卷积来减少参数数量和计算复杂度。
EfficientNet:EfficientNet是由谷歌在2019年提出的一种卷积神经网络,它使用复合系数扩展方法来提高模型的效率和准确性。
ResNeXt:ResNeXt是由Facebook在2017年提出的一种卷积神经网络,通过并行连接多个小型卷积核来提高模型的准确性和效率。
深度学习中常用的Head:
全连接层(Fully Connected Layer):全连接层通常用于分类任务中,将特征图转换成向量形式,并通过多个全连接层实现分类。
池化层(Pooling Layer):池化层通常用于提取特征图的最大值或平均值,以减少特征图的尺寸和参数数量。
Softmax层:Softmax层通常用于分类任务中,将输入向量映射到概率分布,以实现多类别分类。
Sigmoid层:Sigmoid层通常用于二分类任务中,将输入向量映射到0到1的概率范围内,以实现二分类。
RPN(Region Proposal Network)层:RPN层通常用于目标检测中,用于生成候选框,并对其进行分类和回归。
RoI Pooling层(Region of Interest Pooling):RoI Pooling层通常用于目标检测中,用于从特征图中提取感兴趣区域(Region of Interest)的特征。
分支层(Branch Layer):分支层通常用于多任务学习中,用于将特征图分支到不同的任务上,以实现联合训练。
深度学习中常用的Neck:
卷积层:卷积层通常用于增加特征图的通道数和深度,并提高特征表示的丰富程度。这些卷积层可以是普通卷积层、空洞卷积层或分组卷积层等不同类型的卷积。
池化层:池化层通常用于减少特征图的尺寸和参数数量,以减少计算复杂度和内存消耗。这些池化层可以是最大池化或平均池化。
上采样层:上采样层通常用于增加特征图的分辨率,以便更好地进行像素级别的预测。这些上采样层可以是双线性插值、转置卷积或反卷积等不同类型的上采样。
注意力机制:注意力机制通常用于增强特征图的重要性和关联性,以便更好地捕捉物体间的语义关系和上下文信息。这些注意力机制可以是通道注意力机制、空间注意力机制或多头注意力机制等不同类型的注意力。
FPN(Feature Pyramid Network):FPN是一种经典的Neck结构,通过多个不同分辨率的特征图之间的连接,实现多尺度特征融合,以便更好地进行目标检测和分割等任务。

52 softmax的loss function,写一下损失函数
在这里插入图片描述

53 写一下softmax的实现,上下溢出的问题
这个函数接受一个二维数组作为输入,其中每一行表示一个样本,每一列表示一个类别。函数返回一个与输入数组形状相同的数组,其中每个元素表示对应类别的概率。
在实现 Softmax 函数时,需要注意数值溢出的问题。由于 Softmax 函数中包含指数运算,如果输入数据中有很大的数值,则计算结果可能会超出计算机能够表示的范围,导致数值溢出。为了避免这个问题,我们可以在计算指数之前先减去每行的最大值。这样做不会影响最终结果,但可以避免数值溢出。

import numpy as np

def softmax(x):
    # 计算每行的最大值
    row_max = x.max(axis=1).reshape((-1, 1))
    # 减去每行的最大值,避免数值溢出
    x = x - row_max
    # 计算 e 的指数次方
    x_exp = np.exp(x)
    # 计算每行的和
    row_sum = x_exp.sum(axis=1).reshape((-1, 1))
    # 计算 Softmax
    result = x_exp / row_sum
    return result
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

54 隐马,CRF,RNN,LSTM的区别
隐马尔可夫模型(Hidden Markov Model,HMM)、条件随机场(Conditional Random Field,CRF)、循环神经网络(Recurrent Neural Network,RNN)和长短时记忆网络(Long Short-Term Memory,LSTM)都是常用的序列建模方法。它们之间有一些相似之处,但也有一些重要的区别。
隐马尔可夫模型(HMM)是一种概率图模型,它用于建模具有隐含状态的序列数据。HMM 假设序列中的每个观测值都与一个隐含状态相关联,并且隐含状态之间存在转移概率。HMM 可以用来解决序列预测、序列生成和序列标注等问题。
条件随机场(CRF)也是一种概率图模型,它用于建模序列数据中观测值之间的条件依赖关系。与 HMM 不同,CRF 不需要对隐含状态进行建模,而是直接对观测值之间的关系进行建模。CRF 常用于序列标注等问题。
循环神经网络(RNN)是一种神经网络模型,它能够处理任意长度的序列数据。RNN 通过在时间步之间共享权重来实现这一点。RNN 可以用来解决序列预测、序列生成和序列标注等问题。
长短时记忆网络(LSTM)是一种特殊的 RNN,它能够更好地处理长期依赖问题。LSTM 通过引入记忆单元、输入门、遗忘门和输出门来实现这一点。LSTM 可以用来解决与 RNN 相同的问题,但在处理长序列数据时表现更优。
总之,HMM 和 CRF 都是概率图模型,它们通过对隐含状态或观测值之间的关系进行建模来处理序列数据;而 RNN 和 LSTM 则是神经网络模型,它们通过在时间步之间共享权重来处理序列数据。

55 RNN为什么会出现梯度消失
循环神经网络(RNN)在训练过程中可能会出现梯度消失的问题。这是因为 RNN 在处理序列数据时,会在时间步之间反复应用相同的权重矩阵。当这个权重矩阵的特征值小于 1 时,梯度在反向传播过程中会不断衰减,最终导致梯度消失。具体来说,假设 RNN 的权重矩阵为 W,激活函数为 f,则 RNN 的隐藏状态更新公式为 h_t = f(W * h_t-1 + U * x_t + b)。在反向传播过程中,误差关于时间步 t 的隐藏状态 h_t 的梯度会传播到时间步 t-1 的隐藏状态 h_t-1。根据链式法则,我们可以得到:
dE/dh_t-1 = (dE/dh_t) * (dh_t/dh_t-1) = (dE/dh_t) * W * f’(W * h_t-1 + U * x_t + b)
其中,E 表示误差函数,f’ 表示激活函数的导数。可以看出,误差关于时间步 t-1 的隐藏状态 h_t-1 的梯度与误差关于时间步 t 的隐藏状态 h_t 的梯度之间相差一个因子 W * f’(W * h_t-1 + U * x_t + b)。
当这个因子的绝对值小于 1 时,梯度在反向传播过程中会不断衰减。由于 RNN 在处理序列数据时会在时间步之间反复应用相同的权重矩阵 W,因此如果 W 的特征值小于 1,则梯度在经过多个时间步后可能会衰减到接近于零的程度,导致梯度消失。

56 BPTT的推导
BPTT(Backpropagation Through Time)是一种用于训练循环神经网络(RNN)的算法。它通过将 RNN 展开成一个深度神经网络,然后使用反向传播算法来计算梯度。
假设我们有一个序列数据 x = (x_1, x_2, …, x_T),对应的标签为 y = (y_1, y_2, …, y_T)。RNN 的隐藏状态 h_t 和输出 o_t 可以表示为:
h_t = f(U * x_t + W * h_t-1 + b_h) o_t = g(V * h_t + b_o)
其中,f 和 g 分别表示隐藏层和输出层的激活函数,U、V 和 W 分别表示输入权重、输出权重和循环权重,b_h 和 b_o 分别表示隐藏层和输出层的偏置。
假设我们使用平方误差作为损失函数,则总误差 E 可以表示为:
E = sum((y_t - o_t)^2)
我们的目标是计算 E 关于 U、V、W、b_h 和 b_o 的梯度。根据链式法则,我们可以得到:
dE/dU = sum(dE/dh_t * dh_t/dU) dE/dV = sum(dE/do_t * do_t/dV) dE/dW = sum(dE/dh_t * dh_t/dW) dE/db_h = sum(dE/dh_t * dh_t/db_h) dE/db_o = sum(dE/do_t * do_t/db_o)
其中,dE/dh_t 表示 E 关于 h_t 的梯度,dE/do_t 表示 E 关于 o_t 的

57 LSTM 和 GRU和传统RNN的对比
长短时记忆网络(LSTM)和门控循环单元(GRU)都是循环神经网络(RNN)的变种,它们都能够更好地处理长期依赖问题。传统的 RNN 在处理长序列数据时可能会出现梯度消失或梯度爆炸的问题,这使得 RNN 难以捕捉序列中相隔较远的依赖关系。为了解决这个问题,LSTM 和 GRU 引入了门控机制来控制信息的流动。LSTM 通过引入输入门、遗忘门和输出门来实现这一点。输入门控制新信息进入记忆单元的程度,遗忘门控制记忆单元遗忘旧信息的程度,输出门控制记忆单元对隐藏状态的影响程度。这些门控机制使得 LSTM 能够更好地处理长期依赖问题。GRU 是 LSTM 的一种简化版本,它将输入门和遗忘门合并成一个更新门,并且没有输出门。更新门控制新信息进入隐藏状态的程度,重置门控制旧信息对隐藏状态的影响程度。GRU 的结构比 LSTM 简单,但在许多任务中表现与 LSTM 相当。总之,与传统的 RNN 相比,LSTM 和 GRU 都能够更好地处理长期依赖问题。它们通过引入门控机制来控制信息的流动,从而避免梯度消失或梯度爆炸的问题。

58 LSTM减弱梯度消失的原理,三个门的作用,每个门用什么激活函数
LSTM(Long short-term memory)是一种常用的时序模型。它通过引入了三个门来控制信息的传递,分别是遗忘门 f_t ,输入门 i_t 和输出门 o_t 。三个门的作用为:遗忘门 f_t 控制上一时刻的内部状态 c_{t-1} 需要遗忘多少信息;输入门 i_t 控制当前时刻的候选状态 c_t 有多少信息需要保存;输出门 o_t 控制当前时刻的内部状态 c_t 有多少信息需要输出给外部状态 h_t 。
这三个门都是由三个具有sigmoid激活函数的全连接层处理,以计算输入门、遗忘门和输出门的值。因此,这三个门的值都在(0,1)范围内。

59 LSTM的输入输出遗忘门分别是做什么,整个计算流程怎么样

60 RNN梯度弥散和爆炸的原因,lstm为什么不会这样
RNN的梯度弥散和爆炸主要是由于链式求导法则引起的。 当每一项都很小时,梯度会随着它进一步反向传播而变得越来越小。 这就导致了梯度消失现象的产生。 如果Wh非常小,当不断进行反向传播时,梯度值会越来越小。lstm增加了输入门,遗忘门,输出门等干预机制

61 RNN-LSTM解释以及区别,遗忘门的具体体现在哪里,还有哪些时间预测序列
RNN没有细胞状态;LSTM通过细胞状态记忆信息。
RNN激活函数只有tanh;LSTM通过输入门、遗忘门、输出门引入sigmoid函数并结合tanh函数,添加求和操作,减少梯度消失和梯度爆炸的可能性。
RNN只能够处理短期依赖问题;LSTM既能够处理短期依赖问题,又能够处理长期依赖问题。

62 RNN如何防止梯度爆炸
RNN中梯度爆炸的问题可以通过梯度裁剪来解决。梯度裁剪的主要思想是设置一个梯度剪切阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内。这可以防止梯度爆炸.

63 BN和LN的区别,BN一般怎么用,LSTM中有没有用BN
BN和LN的主要区别在于它们做规范化的维度不同。BN是在Batch维度上进行规范化,而LN一般是在最后一维上进行规范化。BN需要在训练过程中,滑动平均累积每个神经元的均值和方差,并保存在模型文件中用于推理过程,而LN不需要。
BN一般用于固定深度的前向神经网络,如CNN,不适用与RNN。LN则主要对RNN效果明显,统计每个样本的所有特征的均值和方差。
已收到消息. BN和LN的主要区别在于它们做规范化的维度不同。BN是在Batch维度上进行规范化,而LN一般是在最后一维上进行规范化。BN需要在训练过程中,滑动平均累积每个神经元的均值和方差,并保存在模型文件中用于推理过程,而LN不需要。 BN一般用于固定深度的前向神经网络,如CNN,不适用与RNN。LN则主要对RNN效果明显,统计每个样本的所有特征的均值和方差。

64 手画gru,并解释门的原理
在这里插入图片描述

65 写一下LSTM的公式
在这里插入图片描述

66 神经网络权重怎么初始化,初始化0有什么问题,为什么不能初始权重为0
神经网络权重的初始化对模型的训练和最终性能有很大的影响。如果权重初始化不当,可能会导致梯度消失或梯度爆炸,使得模型难以训练。通常,神经网络权重是随机初始化的。常用的随机初始化方法有均匀分布和正态分布。例如,可以使用均值为0,标准差为0.01的正态分布来初始化权重。如果将所有权重都初始化为0,那么所有神经元的输出都将是相同的。这意味着每个神经元都将对每个输入产生相同的梯度,并且在反向传播过程中进行相同的参数更新。这样,即使进行多次迭代,每个神经元仍然会保持相同的行为,模型无法学习到有用的信息。因此,不能将神经网络权重全部初始化为0

67 如何解决模型不收敛问题,以及如何加快模型的训练速度
如果模型不收敛,可以尝试以下方法来解决问题:1.调整学习率:学习率过大或过小都可能导致模型不收敛。可以尝试减小或增大学习率,以找到合适的值。2.更换优化器:不同的优化器有不同的优缺点。如果当前使用的优化器不能使模型收敛,可以尝试更换其他优化器。3.调整模型结构:模型结构可能过于复杂或过于简单,导致无法拟合数据。可以尝试增加或减少模型的层数、神经元数量等,以找到合适的模型结构。4.调整正则化系数:正则化可以防止过拟合,但是正则化系数过大可能导致模型无法拟合数据。可以尝试调整正则化系数,以找到合适的值。5.检查数据预处理:数据预处理不当可能导致模型无法拟合数据。可以检查数据预处理流程,确保数据预处理正确。

要加快模型的训练速度,可以尝试以下方法:1.增加批量大小:增加批量大小可以减少模型更新的次数,从而加快训练速度。但是,批量大小过大可能会影响模型的收敛性能。2.使用更快的优化器:一些优化器(如Adam)比其他优化器(如随机梯度下降)更快。可以尝试使用更快的优化器来加快训练速度。3.使用GPU加速:使用GPU可以显著加快模型的训练速度。如果条件允许,可以使用GPU来加速训练。4.减少模型复杂度:减少模型复杂度可以减少计算量,从而加快训练速度。但是,减少模型复杂度可能会影响模型的性能。5.使用预训练模型:使用预训练模型可以减少训练时间。如果有可用的预训练模型,可以使用预训练模型来初始化网络权重,然后再进行微调。

68 normalize方法有哪些,为什么可以加速收敛
常见的normalize方法有以下几种:Batch Normalization (BN):对每个batch的数据进行归一化处理,使得每个batch的数据分布相同。Layer Normalization (LN):对每层神经元的输出进行归一化处理,使得每层神经元的输出分布相同。Instance Normalization (IN):对每个样本的数据进行归一化处理,使得每个样本的数据分布相同。Group Normalization (GN):将通道分组,对每组通道进行归一化处理,使得每组通道的数据分布相同。normalize方法可以加速收敛,主要是因为它能够解决内部协变量偏移(Internal Covariate Shift)问题。内部协变量偏移是指在训练过程中,由于参数更新,导致每层神经元输入数据分布发生变化的现象。这种变化会影响模型的训练速度和最终性能。
normalize方法通过对数据进行归一化处理,使得数据分布保持不变,从而减少内部协变量偏移的影响。这样可以加快模型收敛速度,并提高模型最终性能。

69 attention怎么做,self-attention怎么做,为什么有效,解释softattention与hardattention
Attention机制是一种用于加权不同输入元素以计算表示的方法。它允许模型在处理序列数据时,关注与当前任务相关的部分信息。在基本的attention机制中,我们计算一个查询向量(query vector)和一组键向量(key vectors)之间的相似度得分,然后使用softmax函数将得分归一化为概率分布。接下来,我们将这些概率分布用作权重,对值向量(value vectors)进行加权求和,得到最终的输出。
Self-attention是一种特殊的attention机制,它允许序列中的每个位置都关注序列中的其他位置。在self-attention中,查询、键和值都来自同一个输入序列。Self-attention在自然语言处理任务中非常有效,因为它能够捕捉序列中长距离的依赖关系。Soft attention和hard attention是两种不同的attention方法。Soft attention通过对所有位置进行加权求和来计算输出,而hard attention则只选择一个位置作为输出。Soft attention可以通过梯度下降进行端到端训练,而hard attention则需要使用强化学习或变分推断方法进行训练。Attention机制之所以有效,是因为它能够让模型关注与当前任务相关的信息,忽略不相关的信息。这样可以提高模型的性能,并加快模型收敛速度。

70 encoder-decoder模型里,如果decoder是基于attention做的,该怎么做,是一个什么结构
在encoder-decoder模型中,如果decoder是基于attention做的,那么它的结构是这样的:在decoder中,每个时刻都会将注意力权重输入到Decoder中。此时Decoder中的输入有:经过注意力加权的隐藏层向量,Encoder的输出向量,以及Decoder上一时刻的隐向量。Decoder通过不断迭代,可以输出最终翻译的序列。Attention机制实质上就是一个寻址过程,通过给定一个任务相关的查询Query向量Q,通过计算与Key的注意力分布并附加在Value上,从而计算Attention Value。这个过程实际上是Attention缓解神经网络复杂度的体现,不需要将所有的N个输入都输入到神经网络进行计算,而是选择一些与任务相关的信息输入神经网络,与RNN中的门控机制思想类似。Attention机制计算过程大致可以分成三步:①信息输入:将Q,K,V输入模型用X=[x_1,x_2,…x_n]表示输入权重向量;②计算注意力分布α:通过计算Q和K进行点积计算相关度,并通过softmax计算分数;③信息加权平均:注意力分布α_i来解释在上下文查询q_i时,第i个信息受关注程度

71. RoI Pooling和RoI Align ,RoI Align 相较于RoI Pooling 有什么改进,怎么做插值, 线性插值, spline插值,写插值公式
RoI Pooling使生成的候选框region proposal映射产生固定大小的feature map;ROI Pooling 的作用是根据预选框的位置坐标在特征图中将相应区域池化为固定尺寸的特征图,以便进行后续的分类和包围框回归操作。由于预选框的位置通常是由模型回归得到的,一般来讲是浮点数,而池化后的特征图要求尺寸固定。故ROI Pooling这一操作存在两次量化的过程。1. 将候选框边界量化为整数点坐标值;2.将量化后的边界区域平均分割成 k x k 个单元(bin),对每一个单元的边界进行量化。
RoI Align是一种区域特征聚集方式, 很好地解决了ROI Pooling操作中两次量化造成的区域不匹配(mis-alignment)的问题。实验显示,在检测测任务中将 ROI Pooling 替换为 ROI Align 可以提升检测模型的准确性;RoI Align取消了量化操作,使用双线性内插的方法获得坐标为浮点数的像素点上的图像数值,从而将整个特征聚集过程转化为一个连续的操作。1.遍历每一个候选区域,保持浮点数边界不做量化;2.将候选区域分割成k x k个单元,每个单元的边界也不做量化;3.在每个单元中计算固定四个坐标位置,用双线性内插的方法计算出这四个位置的值,然后进行最大池化操作。
在图像的放大和缩小的过程中,需要计算新图像像素点在原图的位置,如果计算的位置不是整数,就需要用到图像的内插,我们需要寻找在原图中最近得像素点赋值给新的像素点,这种方法很简单是最近邻插法,这种方法好理解、简单,但是不实用,会产生是真现象,产生棋盘格效应,更实用的方法就是双线性内插,

73. detection 的发展,从RCNN到CenterNet
在这里插入图片描述

74. 讲一下faster rcnn,RPN的原理,anchor是怎么来的,为什么这样设计anchor,哪些为正类,哪些为负类,loss怎么设计,tx,ty,tw,th
Faster R-CNN是一种目标检测算法,它由两部分组成:区域生成网络(RPN)和Fast R-CNN检测器。RPN是Faster R-CNN最核心的部分,它的作用是解决候选区域的问题。RPN使用anchor box来解决这个问题,使用满布整张图片尺寸各不相同的anchor作为最初的预选框,再对anchor进行预测与矫正从而选出候选区域。Anchor是通过组合不同的面积与横纵比来实现的。在RPN中,每个特征点都带有k个anchor。对于每个anchor,RPN进行分类和回归。分类是指预测每个anchor是否包含需要检测的物体,回归是指预测物体的大致位置。在RPN中,正类和负类是通过与ground truth box的IoU(交并比)来确定的。如果一个anchor与任意一个ground truth box的IoU大于一个阈值(如0.7),则该anchor被标记为正类;如果一个anchor与所有ground truth box的IoU都小于另一个阈值(如0.3),则该anchor被标记为负类。RPN中使用了多任务损失函数,包括分类损失和边框回归损失。分类损失使用交叉熵损失函数,边框回归损失使用Smooth L1损失函数。tx,ty,tw,th分别表示预测框相对于anchor框中心点x,y坐标以及宽度和高度的偏移量
75. R-FCN与Faster RCNN的区别,Faster RCNN损失函数的构成
R-FCN(Region-based Fully Convolutional Networks)和Faster R-CNN都是目标检测算法。它们的主要区别在于R-FCN使用了位置敏感的得分图来进行目标检测,而Faster R-CNN使用了RoI池化层。这使得R-FCN在计算上更加高效,因为它可以在整个图像上共享计算,而不是对每个RoI单独进行计算。Faster R-CNN的损失函数由两部分组成:RPN损失和Fast R-CNN损失。RPN损失包括分类损失和边框回归损失,Fast R-CNN损失也包括分类损失和边框回归损失。分类损失使用交叉熵损失函数,边框回归损失使用Smooth L1损失函数

76. 怎么理解R-FCN的PS RoiPooling
PS RoiPooling(Position-Sensitive Region of Interest Pooling)是R-FCN中用来解决目标检测问题的一种方法。它通过在池化中强制添加位置信息来实现。例如,将RPN得出的ROI分成3x3的bins,对左上角的bin判断“这是婴儿的左上部分吗”,或“这是婴儿的右上部分吗”,从而得到9个分数的特征图,通过分数的投票来判断这个框是否是一个婴儿。可以预见的是,如果这个框是比较准确的,那么9个格子中的值应该都是比较大的,文中使用了Average Pooling来进行投票

77. RPN中的正负样本的阈值为(0.7,0.3),中间的不选用会有什么后果,为什么要把正负样本的阈值设定在两个相隔较远的值
rpn在神经网络的主要作用是代替selective searchs生成区域建议,输入feature map(特征图),输出一系列ROI(感兴趣区域);RPN的核心思想是使用卷积神经网络直接产生region proposal,使用的方法本质上就是滑动窗口。RPN的设计比较巧妙,RPN只需在最后的卷积层上滑动一遍,因为anchor机制和边框回归可以得到多尺度、多长宽比的region proposal,3*3滑窗对应的每个特征区域同时预测输入图像3种尺度(128,256,512),3种长宽比(1:1,1:2,2:1)的region proposal,这种映射的机制称为anchor

78. ssd的流程,ssd的各种变体
SSD(Single Shot MultiBox Detector)是一种目标检测算法。它的基本流程如下:首先输入一幅图片,让图片经过卷积神经网络(CNN)提取特征,并生成 feature map。然后抽取其中六层的feature map,再在 feature map 的每个点上生成 default box(各层的个数不同,但每个点都有)。最后将生成的所有 default box 都集合起来,全部丢到 NMS(极大值抑制)中,输出筛选后的 default box,并输出。SSD有很多变体,比如FSSD、DSSD、DSOD等等。它们都是在SSD的基础上进行了改进和优化,以提高目标检测的准确性和效率

79. faster RCNN,yolo, ssd的区别
Faster R-CNN,YOLO和SSD都是目标检测算法。它们的主要区别在于它们的检测流程和速度。
Faster R-CNN首先通过CNN得到候选框,然后再进行分类与回归。它的准确率较高,但速度较慢。
YOLO(You Only Look Once)则采用回归的方法直接预测bounding box和分类,没有使用候选区域。它的速度快,但准确率和漏检率较低。SSD(Single Shot MultiBox Detector)平衡了YOLO和Faster R-CNN的优缺点。它采用CNN来直接进行检测,而不是像YOLO那样在全连接层之后做检测。它可以在保持较高准确率的同时,实现较快的检测速度

80. cascade rcnn的流程
Cascade R-CNN是一个多阶段的目标检测算法。它由一个RPN和三个检测阶段组成,每个阶段使用递增的IoU阈值进行训练。前一个阶段的输出被用作下一个阶段的输入,以产生更高质量的bounding box。Cascade R-CNN简单而有效,能直接添加到其它R-CNN型detector中,带来巨大的性能提升

81. YOLOv2,v3的提升,小物体检测上的提升,anchor尺寸如何设置
小目标检测困难原因:1.很多目标检测器试图叠加越来越多的池化和降采样操作,使得在前向传播中逐渐丢失像素数较少的微小目标特征,因此降低了微小目标的检测性能;FPN 通过水平融合低分辨率特征图和高分辨率特征图,在一定程度上缓解了信息扩散问题。但是,直接融合不同密度的信息会引起语义冲突,限制了多尺度特征的表达,使微小目标容易淹没在冲突信息中。2.在目前的经典公共数据集中,微小目标的标注数量远远少于较大目标的标注数量。因此,在训练过程中,网络的收敛方向不断向较大目标倾斜,导致微小目标性能较差。小目标提升的解决方案:CAM融合多尺度扩张卷积特征,获取丰富的上下文信息进行特征增强。FRM在通道和空间维度上引入特征细化机制来抑制冲突信息,防止微小目标淹没在冲突语义信息中。同时,为了保证网络在训练过程中不会向较大目标倾斜,用Copy-Reduction-Paste的方法来增加训练中微小目标丢失的比例,即复制训练集中较大的目标,然后缩小目标,再然后paste回原始图像。在粘贴过程中,必须保证paste的目标不与现有目标重叠。

82. anchor free算法的框架,基本思想,不同网络的具体对比,hourglass结构的好处,损失函数,和sota比性能如何,新的损失函数为什么这么设计
Anchor-free算法是一种目标检测算法,它不依赖于预定义的锚框来检测目标。与之相对的是Anchor-based算法,它依赖于预定义的锚框来检测目标。Anchor-free算法的基本思想是直接在特征图上预测目标的位置和类别,而不需要预先定义锚框。
当前的Anchor-free检测算法主要分为两类:基于关键点的和基于语义地图的。基于关键点的方法,如CornerNet,通过检测一对关键点(左上角和右下角)来确定目标的边界框。基于语义地图的方法,如FSAF、FCOS和FoveaNet,每个像素点表示目标存在概率。
CornerNet网络结构中引入了一种新的池化方法——Corner Pooling。它用于建立角点和目标的位置关系。Corner Pooling模块可以快速实现Corner Pooling操作,提高了效率

83. YOLO全套,ssd,faster rcnn具体细节,代码实现,工程需要考虑的实际问题
R-CNN作为两阶段算法的先驱,利用不同大小的先验框对不同大小的目标进行匹配,然后通过CNN选择候选区域;为了减少训练时间,Fast R-CNN提取整个图像的特征图,然后利用空间金字塔池化和RoI池化生成区域特征并筛选候选区域;为了进一步提高小目标的精度,E-FPN提出了一种超分辨率特征金字塔结构来放大小目标特征。与两阶段网络相比,单阶段网络速度较快,但精度相对较低;SSD在图像上密集放置Anchor以获取Bounding Box,同时充分利用不同尺度的特征来检测更小的目标;利用多尺度特征融合是提高小目标检测精度的有效方法。SSD是首次尝试用多尺度特征来预测目标的位置和类别。YOLOV3基于特征金字塔有3个输出分别选择大、中、微小物体进行检测,大大提高了微小物体的检测性能。在FPN中引入了高分辨率Attention机制,以挖掘微小目标中最有用信息。FPN从上到下融合不同粒度的相邻特征也极大地提高了特征的表达能力。PANet在FPN的基础上增加了额外的自下向上连接,更有效地将信息从底层传输到上层。NAS-FPN通过神经结构搜索技术搜索出一种新的连接方法。Bi-FPN改进了PANet的连接方式,提高了PANet的效率,并在连接点引入了简单的Attention机制。RefineDet引入了新的损失函数,解决了简单样本和困难样本之间的不平衡问题

84. 目标检测框架,TWO-STAGE,ONE-STAGE,两阶段与一阶段的优缺点,focal loss的表达式,与OHEM有什么区别,anchor free方法的优缺点
focal loss从样本难易分类角度出发,解决样本非平衡带来的模型训练问题。
相信很多人会在这里有一个疑问,样本难易分类角度怎么能够解决样本非平衡的问题,直觉上来讲样本非平衡造成的问题就是样本数少的类别分类难度较高。因此从样本难易分类角度出发,使得loss聚焦于难分样本,解决了样本少的类别分类准确率不高的问题,当然难分样本不限于样本少的类别,也就是focal loss不仅仅解决了样本非平衡的问题,同样有助于模型的整体性能提高。要想使模型训练过程中聚焦难分类样本,仅仅使得Loss倾向于难分类样本还不够,因为训练过程中模型参数更新取决于Loss的梯度

84. bn的训练,roipooling和align的细节,FPN网络的细节
BN(Batch Normalization)是一种常用的神经网络训练技术。它通过对每一层的输入进行归一化,使其均值为0,方差为1,来加速训练过程并提高模型的泛化能力。RoI Pooling(Region of Interest Pooling)是一种特征提取方法,用于从特征图中提取感兴趣区域的特征。它将输入的感兴趣区域划分为固定大小的网格,并对每个网格内的特征进行最大池化,以得到固定大小的输出。RoI Align是对RoI Pooling的改进。它通过双线性插值来消除RoI Pooling中由于量化造成的位置偏移。FPN(Feature Pyramid Network)是一种用于目标检测的网络结构。它通过自底向上和自顶向下的路径以及横向连接来构建多尺度的特征金字塔。这样可以在不同尺度上检测不同大小的目标。FPN 通过水平融合低分辨率特征图和高分辨率特征图,在一定程度上缓解了信息扩散问题。但是,直接融合不同密度的信息会引起语义冲突,限制了多尺度特征的表达,使微小目标容易淹没在冲突信息中。

74. 手写nms,实现score排序,iou计算

import numpy as np

def nms(boxes, scores, iou_threshold):
    """
    boxes: 边界框坐标,形状为 (n, 4)
    scores: 边界框得分,形状为 (n,)
    iou_threshold: IoU 阈值
    """
    # 根据得分对边界框进行排序
    indices = np.argsort(scores)[::-1]
    keep = []
    
    while len(indices) > 0:
        # 选择得分最高的边界框并将其添加到保留列表中
        i = indices[0]
        keep.append(i)
        
        # 计算剩余边界框与当前边界框的 IoU
        x1 = np.maximum(boxes[i, 0], boxes[indices[1:], 0])
        y1 = np.maximum(boxes[i, 1], boxes[indices[1:], 1])
        x2 = np.minimum(boxes[i, 2], boxes[indices[1:], 2])
        y2 = np.minimum(boxes[i, 3], boxes[indices[1:], 3])
        
        w = np.maximum(0.0, x2 - x1 + 1)
        h = np.maximum(0.0, y2 - y1 + 1)
        
        inter = w * h
        union = (boxes[i, 2] - boxes[i, 0] + 1) * (boxes[i, 3] - boxes[i, 1] + 1) + \
                (boxes[indices[1:], 2] - boxes[indices[1:], 0] + 1) * (boxes[indices[1:], 3] - boxes[indices[1:], 1] + 1) - inter
        
        iou = inter / union
        
        # 删除与当前边界框 IoU 大于阈值的边界框
        indices = indices[np.where(iou <= iou_threshold)[0] + 1]
    
    return keep
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

75. 能提升速度但不损失性能的操作有哪些
在深度学习模型训练中,有一些方法可以提升速度而不损失性能。例如,可以使用残差连接来解决梯度消失和表示瓶颈问题,这可以帮助梯度传播,因此允许更深的网络;还可以使用批标准化来适应性地将数据标准化,这有助于梯度传播,因此允许更深的网络;此外,还可以使用深度可分离卷积来替代 Conv2D,这可以让模型更加轻量、速度更快,并且可以让任务性能提高几个百分点

76. 介绍retinaface,Centernet
RetinaFace 是一种基于 RetinaNet 的人脸检测网络,它添加了 SSH 网络的三层级联检测模块,以提高检测精度。作者提供了两种网络的复现版本(MobileNet 和 ResNet),基于 MobileNet 的构建版旨在提供更快速的检测,而基于 ResNet 的构建版则更重于精度的指标。CenterNet 是一种目标检测算法,它通过预测目标的中心点和大小来实现目标检测。CenterFace 是基于 CenterNet 的人脸检测算法,它可以实现人脸检测和关键点定位。

77. 单阶段检测方法为什么对负样本需求更大
单阶段检测器速度很快,但是准确度一直被双阶段检测器甩开,作者通过实验发现其主要原因之一是单阶段检测器训练时正负样本不均衡的问题。双阶段检测器在proposal阶段进行了初步检测(极大减少了背景负样本),输入后续检测框的proposals样本不均衡问题不严重。而单阶段检测器没有proposal阶段,直接对整张图进行预测,所以正负样本不均衡问题更加严重。

78. 数据增强的常用方法
深度学习中的数据增强方法有很多,可以分为有监督的数据增强和无监督的数据增强方法。其中有监督的数据增强又可以分为单样本数据增强和多样本数据增强方法,无监督的数据增强分为生成新的数据和学习增强策略两个方向。单样本数据增强包括几何变换类和颜色变换类。几何变换类即对图像进行几何变换,包括翻转,旋转,裁剪,变形,缩放等各类操作。颜色变换类包括噪声、模糊、颜色变换、擦除、填充等等。多样本数据增强方法利用多个样本来产生新的样本。例如 SMOTE 方法是通过人工合成新样本来处理样本不平衡问题,从而提升分类器性能。SamplePairing 方法是从训练集中随机抽取两张图片分别经过基础数据增强操作处理后经像素以取平均值的形式叠加合成一个新的样本,标签为原样本标签中的一种。mixup 是使用线性插值得到新样本数据。无监督的数据增强方法包括通过模型学习数据的分布,随机生成与训练数据集分布一致的图片,代表方法GAN。还有通过模型,学习出适合当前任务的数据增强方法,代表方法AutoAugment。

79. 画出faster rcnn流程以及rpn具体过程
Faster R-CNN 是一个目标检测模型,它包括四个主要部分:特征提取网络(Backbone)、区域建议网络(RPN)、RoI Pooling 以及 R-CNN。它的最大创新点在于提出了 RPN 来替代 R-CNN 中的 Selective Search,应用卷积神经网络提取 RoIs,极大地提升了检测的速度,成为实时目标检测的开山之作。RPN 的流程如下:首先,输入图像经过 Backbone 网络得到特征图。然后,特征图上的每个像素都会生成若干个 Anchor。接着,计算每个 Anchor 的类别真值(前景或背景)和偏移量真值(其相对于对应标注框的偏移量,中心点以及宽和高)。然后,RPN 计算预测值,并结合真值进行反向传播,使 Anchor 更接近于真值框。最后,回归之后对 Anchor 进行初筛,首先去掉超出图像范围的 Anchor,然后按照预测得分取前若干个(例如 12000 个),接下来执行 NMS 进一步筛选并取得分前若干个 Anchor(例如 200 个),使用真值信息对这些 Anchor 进行进一步筛选,并给出目标真值,送入 R-CNN 进行精细分类和回归

80. bbox与坐标轴不平行时如何计算
当 Bounding Box (bbox) 与坐标轴不平行时,通常使用旋转矩形来表示它。旋转矩形由中心点坐标、宽度、高度和旋转角度四个参数定义。旋转角度表示矩形的一个边与水平轴之间的夹角。
要计算旋转矩形的顶点坐标,可以先计算出未旋转矩形的顶点坐标,然后使用旋转矩阵对这些坐标进行旋转。假设旋转矩形的中心点坐标为 (xc​,yc​),宽度为 w,高度为 h,旋转角度为 θ。则未旋转矩形的四个顶点坐标分别为 (xc​−w/2,yc​−h/2),(xc​+w/2,yc​−h/2),(xc​+w/2,yc​+h/2) 和 (xc​−w/2,yc​+h/2)。
接下来,我们可以使用旋转矩阵对这些坐标进行旋转。设点 (x,y) 绕点 (xc​,yc​) 逆时针旋转 θ 度后的新坐标为 (x′,y′),则有:
在这里插入图片描述
通过这种方式,我们就可以计算出旋转矩形的四个顶点坐标。

import numpy as np

def rotated_rectangle_vertices(center, width, height, angle):
    # 将角度转换为弧度
    theta = np.radians(angle)
    
    # 计算旋转矩阵
    R = np.array([[np.cos(theta), -np.sin(theta)],
                  [np.sin(theta),  np.cos(theta)]])
    
    # 计算未旋转矩形的顶点坐标
    x1, y1 = center[0] - width / 2, center[1] - height / 2
    x2, y2 = center[0] + width / 2, center[1] - height / 2
    x3, y3 = center[0] + width / 2, center[1] + height / 2
    x4, y4 = center[0] - width / 2, center[1] + height / 2
    
    # 计算旋转后的顶点坐标
    x1, y1 = R @ ([x1, y1] - center) + center
    x2, y2 = R @ ([x2, y2] - center) + center
    x3, y3 = R @ ([x3, y3] - center) + center
    x4, y4 = R @ ([x4, y4] - center) + center
    
    return (x1, y1), (x2, y2), (x3, y3), (x4, y4)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

81. 匈牙利算法流程
匈牙利算法(也称为 Kuhn-Munkres 算法)是一种用于解决二分图最大权匹配问题的算法。它的基本流程如下:1.从任意一种匹配方案开始,例如空匹配。2.使用标记法找到相等子图中的完美匹配。如果找到了,算法结束。3.如果没有找到完美匹配,则修改标记以扩大相等子图。4.重复步骤 2 和步骤 3,直到找到完美匹配为止。
下面是该算法的详细流程:1.对于矩阵中的每一行,从该行中的每个元素中减去该行的最小元素。2.对于矩阵中的每一列,从该列中的每个元素中减去该列的最小元素。3.使用最少数量的水平线和垂直线覆盖矩阵中所有的零元素。4.如果覆盖线的数量等于矩阵的阶数,则算法结束。否则,继续执行下一步。5.找到矩阵中未被覆盖的最小元素,然后从未被覆盖的每一行中减去该元素,并将其加到被覆盖两次的每一列中。6.转到步骤 3。
该算法保证在有限步骤内结束,并且可以找到二分图的最大权匹配。

from scipy.optimize import linear_sum_assignment
import numpy as np

def hungarian_algorithm(cost_matrix):
    row_ind, col_ind = linear_sum_assignment(cost_matrix)
    return row_ind, col_ind

# 示例
cost = np.array([[4, 1, 3], [2, 0, 5], [3, 2, 2]])
row_ind, col_ind = hungarian_algorithm(cost)
print(f"最小成本:{cost[row_ind, col_ind].sum()}")
print(f"分配方案:{list(zip(row_ind, col_ind))}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

82. unet与deeplab v2流程,v3?
U-Net 和 DeepLab v2/v3 都是用于图像语义分割的深度学习模型。
U-Net 是一种全卷积神经网络,它由一个编码器和一个解码器组成。编码器不断对输入图像进行下采样,以提取高层次的语义信息。解码器则不断对特征图进行上采样,并与编码器中相应层的特征图进行拼接,以恢复空间信息。最终,模型输出一个与输入图像大小相同的特征图,其中每个像素表示该位置处物体的类别。
DeepLab v2 是一种基于空洞卷积和条件随机场(CRF)的语义分割模型。它使用空洞卷积来扩大感受野,以捕获更多的上下文信息。此外,它还使用了空洞空间金字塔池化(ASPP)来捕获多尺度信息。最后,它使用 CRF 来改善物体边界的定位精度。
DeepLab v3 在 DeepLab v2 的基础上进行了改进。它放弃了 CRF,并引入了更强大的 ASPP 模块,该模块包括全局平均池化层和多个并行的空洞卷积层。此外,它还使用了批量归一化层来加速训练过程。
DeepLab v3+ 在 DeepLab v3 的基础上进一步改进。它将模型分为编码器和解码器两部分,并在解码器中引入了深度可分离卷积来减少计算量。此外,它还使用了简单的双线性插值来上采样特征图。

83. 反向传播时unet的直接相加与concat的区别
在 U-Net 模型中,编码器和解码器中的特征图可以通过直接相加或拼接(concatenation)的方式进行融合。这两种方法在反向传播时会有所不同。
当使用直接相加的方式融合特征图时,来自解码器的梯度会直接传递到编码器中对应层的特征图。这意味着,编码器和解码器中对应层的特征图会受到相同的梯度影响。
当使用拼接的方式融合特征图时,来自解码器的梯度会分别传递到编码器和解码器中对应层的特征图。这意味着,编码器和解码器中对应层的特征图会受到不同的梯度影响。
这两种方法在实际应用中都有广泛应用,它们各有优缺点。直接相加的方式更简单,计算量更小,但可能会导致信息损失。拼接的方式能够保留更多信息,但计算量更大。

84. 语义分割中miou计算公式
mIoU(mean Intersection over Union)是语义分割中常用的评估指标之一。它表示所有类别的 IoU 值的平均值。
IoU(Intersection over Union)表示两个集合的交集与并集之比。在语义分割中,IoU 用于衡量预测结果与真实标注之间的重叠程度。对于每个类别,IoU 定义为:
IoU=TP​/(TP+FP+FN)
其中 TP(True Positive)表示预测结果与真实标注都为该类别的像素数量,FP(False Positive)表示预测结果为该类别但真实标注不为该类别的像素数量,FN(False Negative)表示预测结果不为该类别但真实标注为该类别的像素数量。
mIoU 则定义为所有类别的 IoU 值的平均值:
mIoU=(1/N)*∑​IoUi​
其中 N 表示类别总数,IoUi​ 表示第 i 个类别的 IoU 值。

85. 有ocr中文模型如何得到日文的模型
深度学习模型通常是针对特定任务和数据集训练的。因此,要从中文 OCR 模型得到日文 OCR 模型,您需要使用日文数据集重新训练模型。这通常需要大量的标注数据和计算资源。可以考虑使用迁移学习技术,即使用预训练的中文 OCR 模型作为起点,并在日文数据集上进行微调,以加快训练过程并提高模型性能。

86. 超分辨率项目有什么创新点
超分辨率(Super-Resolution,简称 SR)是指利用光学及其相关光学知识,根据已知图像信息恢复图像细节和其他数据信息的过程,简单来说就是增大图像的分辨率,防止其图像质量下降。在过去的二十年中,特别是利用深度学习方法,在超分辨率领域取得了重大进展。一些超分辨率项目的创新点包括:1.引入新型图片退化方法。例如,腾讯的 RealSR 算法采用了自主设计的新型图片退化方法,通过分析真实图片中的模糊和噪声,模拟真实图片的退化过程。2.不需要成对的训练数据。例如,RealSR 算法不需要成对的训练数据,利用无标记的数据即可进行训练。3.引入注意力机制。例如,RCAN 算法是首个将注意力机制应用于 SR 问题的网络。3.引入深度强化学习。例如,有研究人员提出了基于深度强化学习的注意感知人脸超分算法。4.引入 Transformer 网络结构。例如,TTSR 算法是最早将 Transformer 引入图像超分领域的算法,提出了基于 Transformer 网络结构的 TTSR 超分算法,充分利用参考图像的纹理信息,并提出了特征融合机制。这些创新点都有助于提高超分辨率算法的性能和实用性。

87. 超分辨率 的损失函数
超分辨率常用的损失函数包括像素损失(L1,L2,ssim等),直接计算超分辨率预测结果与GT(Ground truth)之间的差异。还有感知损失和风格损失,将预测结果和GT输入到特征提取网络(一般为VGG等backbone),对比特征图之间的差异

88. 检测到的人脸如何对齐,warpaffine参数,转换矩阵M有几维
人脸对齐是人脸识别的第一个步骤,需要把检测到的人脸和人脸关键点统一对齐到一个标准模版。可以使用仿射变换对齐人脸。仿射变换用于旋转、缩放、平移等。我们可以将上述所有三个要求打包到一个cv2.warpAffine调用中;诀窍是创建旋转矩阵M1。转换矩阵M是一个2x3的矩阵。

89. 分类网络的发展进程,有噪声,样本不均衡,分很细的类怎么办
分类网络的发展历程中,有很多经典的网络模型,比如LeNet、AlexNet、VGG、GoogLeNet、SqueezeNet、ResNet、ResNeXt和DenseNet等。这些网络模型在不断地发展和改进,以提高分类准确率和解决各种问题。对于有噪声的数据,可以使用数据清洗和预处理技术来减少噪声的影响。对于样本不均衡的问题,可以使用过采样或欠采样技术来平衡数据集。对于分很细的类别,可以使用更深层次的网络结构来提取更多的特征信息,以提高分类准确率。

90. 分类一般用什么损失函数,交叉熵的形式,20%的噪声数据有什么影响
分类问题中常用的损失函数是交叉熵损失函数。交叉熵损失函数的形式为:
在这里插入图片描述
其中p(x)表示真实标签的概率分布,q(x)表示预测标签的概率分布。如果数据集中有20%的噪声数据,那么这些噪声数据可能会对模型的训练产生负面影响,导致模型的泛化能力下降。可以通过数据清洗和预处理技术来减少噪声数据对模型的影响。

91. 姿态估计openpose实现过程,PAF的原理,除了MSE还能用什么loss
OpenPose是一种实时多人2D姿态估计方法,它使用了一种称为部件关联字段(PAF)的非参数表示来将检测到的身体部位与图像中的每个人相关联。PAF是由一组流场组成的表示,这些流场对可变数量的人的身体部位之间的非结构化成对关系进行编码。除了均方误差(MSE)损失函数,还可以使用其他损失函数,例如交叉熵损失函数、绝对值误差损失函数等。

92. Reid里的MGN网络的设计,为什么有三条支路,加入局部特征会有特征冗余,为什么还要加
MGN(Multiple Granularities Network)是云从科技2018年提出的一种多粒度网络模型,它结合了全局特征和局部特征,具有细粒度多特征融合特性,并且在主流数据集上取得了领先的成果。MGN网络有三条支路,分别是global支路、part-2支路和part-3支路。global支路负责提取整体的宏观上大家共有的特征,而part-2和part-3支路则负责提取不同层次或者不同级别的局部特征。加入局部特征可以帮助模型学习到更详细的细节信息,尽管可能会有一些特征冗余,但总体来说,全局和局部的特征结合在一起能够有丰富的信息和细节去表征输入图片的完整情况.

93. facenet里的triplet loss的公式,反向传播如何更新
Facenet是一种用于人脸识别和聚类的深度神经网络模型,它使用了triplet loss作为损失函数。在triplet loss中,每个样本都包含三个部分:anchor样本、positive样本和negative样本。目标是使得anchor样本与positive样本之间的距离尽可能小,而与negative样本之间的距离尽可能大。
triplet loss的目标函数为:
在这里插入图片描述
其中,a表示anchor样本,p表示positive样本,n表示negative样本,d(x,y)表示x和y之间的距离。目标函数取0或者上式的最大值,当上式有值的时候,表示会产生损失,为0的时候表示没有产生损失。
在反向传播的过程中,梯度按照相应的公式计算。Triplet是指三元组,通常用于机器学习中的一种损失函数——triplet loss。

94. 强化学习DQN,DDQN,AC,DDPG的区别
在强化学习领域,DQN、DDQN、AC和DDPG是常用的算法,它们之间的区别如下:DQN(Deep Q-Network)是一种基于Q-learning的深度强化学习算法,它利用深度神经网络来逼近Q函数,从而实现对动作值的估计。DQN的主要优点是可以处理高维状态空间和动作空间,但是存在过度估计问题。DDQN(Double Deep Q-Network)是在DQN的基础上进行改进的算法,它通过使用两个独立的神经网络来减少目标Q值的过度估计,从而提高学习效率和稳定性。AC(Actor-Critic)算法是一种基于策略梯度的强化学习算法,它同时学习策略和值函数,并使用价值函数的估计来指导策略的更新。AC算法可以处理连续动作空间,但是存在高方差和低效率的问题。DDPG(Deep Deterministic Policy Gradient)算法是一种基于策略梯度和Q-learning的深度强化学习算法,它通过使用Actor-Critic结构来学习连续动作空间下的策略。DDPG算法可以处理高维状态和连续动作空间,但是存在训练不稳定的问题。在实际应用中,需要根据具体问题的特点选择适合的算法,并进行适当的调整和优化,以保证算法的性能和可靠性。同时,需要对算法的开发和部署过程进行全流程记录,以便后续的优化和迭代。

95. 介绍一下什么是GAN,GAN是用来干啥的,是怎么训练的
GAN(Generative Adversarial Networks)是一种生成对抗网络,由Ian Goodfellow于2014年首次提出。GAN是一种生成模型,主要用于生成数据(如图像、语音、文本等),同时也可以用于其他任务,如去噪、超分辨率等。GAN的核心思想是通过训练两个相互对抗的神经网络(一个生成器和一个判别器)来学习真实数据的分布。生成器(Generator):生成器的任务是从一个随机噪声向量生成类似于真实数据的样本生成器试图生成越来越逼真的样本,以便欺骗判别器。判别器(Discriminator):判别器的任务是对输入的数据样本进行判断,判断其是真实数据(来自训练集)还是伪造数据(由生成器生成)。判别器试图提高其区分真伪样本的能力。GAN的训练过程是一个博弈过程,生成器和判别器相互竞争,共同进步。训练过程如下:固定生成器,优化判别器:使用真实数据和生成器生成的数据训练判别器,提高其区分真伪样本的能力。固定判别器,优化生成器:使用判别器的反馈训练生成器,使其生成的样本更加逼真。重复上述两个步骤,直到生成器生成的样本足够逼真,判别器无法区分真伪样本。
通过这种对抗训练过程,生成器逐渐学会生成越来越逼真的数据样本,最终可以生成与真实数据分布非常接近的样本。在实际应用中,GAN已经被成功用于图像生成、文本生成、图像风格迁移、图像去噪等领域。

96. GAN是怎么训练生成器判别器的
GAN训练生成器(Generator)和判别器(Discriminator)的过程是一个迭代和对抗的过程。下面是训练过程的详细步骤:
准备数据集:首先需要一个真实数据集,例如图像、文本或音频等。
初始化生成器和判别器:生成器和判别器通常是使用深度神经网络实现的。在训练开始前,需要对这两个神经网络进行初始化。
训练判别器:
a. 从真实数据集中采样一批数据作为正样本。
b. 使用生成器生成一批伪造数据作为负样本。这通常是从一个随机噪声向量开始,生成器根据这个噪声生成伪造数据。
c. 将正样本和负样本混合在一起,并为每个样本分配一个标签,例如正样本的标签为1,负样本的标签为0。
d. 使用这批带有标签的数据训练判别器,使其能够更好地区分正负样本。这个过程通常是通过最小化一个损失函数进行的,例如交叉熵损失。
训练生成器:
a. 生成一批新的伪造数据,和第3步中的方法类似。
b. 使用判别器对这批伪造数据进行预测,得到每个样本的预测标签。
c. 使用预测标签和实际标签(这里实际标签为1,因为我们希望伪造数据被判别器误判为正样本)计算损失函数,例如交叉熵损失。
d. 使用损失函数对生成器进行更新,使其生成的伪造数据更加逼真,以便欺骗判别器。这个过程通常是通过反向传播和梯度下降进行的。
重复第3步和第4步:在整个训练过程中,不断重复上述步骤,生成器和判别器相互竞争,共同进步。当生成器生成的伪造数据足够逼真以至于判别器无法区分时,训练过程结束。
值得注意的是,GAN训练过程可能会遇到一些问题,如模式崩溃、训练不稳定等。为了解决这些问题,研究人员提出了许多改进的GAN模型,如WGAN、LSGAN、SAGAN等。这些改进模型在损失函数、网络结构或训练策略上进行了调整,以提高生成器和判别器的训练效果和稳定性。

97 如何解决模式崩溃、训练不稳定的问题
模式崩溃(Mode Collapse)和训练不稳定是GAN训练过程中常见的问题。为了解决这些问题,研究人员提出了许多改进的方法和技巧。以下是一些常见的方法:1 使用Wasserstein GAN(WGAN):WGAN通过使用Wasserstein距离作为损失函数,代替原始GAN中的KL散度或JS散度,可以显著提高训练稳定性。此外,WGAN还引入了权重剪裁(Weight Clipping)以确保训练过程的收敛。
2 使用梯度惩罚(Gradient Penalty):WGAN-GP是WGAN的一个改进版本,它通过在损失函数中加入梯度惩罚项来替代权重剪裁,以实现更稳定的训练过程。
3 使用谱归一化(Spectral Normalization):谱归一化通过限制神经网络层的权重矩阵的谱范数(Spectral Norm),可以有效地限制判别器的能力,从而提高训练稳定性。4 使用最小二乘损失(Least Squares Loss):最小二乘生成对抗网络(LSGAN)使用最小二乘损失代替原始GAN中的交叉熵损失,可以减少梯度消失问题,提高训练稳定性。5 添加噪声:在训练过程中给判别器的输入添加噪声,可以增加模型的鲁棒性,有助于解决模式崩溃问题。6 使用经验分布匹配(Feature Matching):通过让生成器生成的数据与真实数据在特征空间上的距离最小化而非在像素空间上,可以提高生成样本的多样性,防止模式崩溃。7 使用多样性损失(Diversity Loss):在损失函数中加入一个多样性损失项,以鼓励生成器生成不同的样本,降低模式崩溃的风险。8 使用条件生成对抗网络(Conditional GAN):在生成器和判别器中引入条件信息(如类别标签),可以提高生成样本的多样性和训练稳定性。9 使用自注意力机制(Self-Attention):引入自注意力机制,如SAGAN,可以帮助生成器捕捉长距离的依赖关系,提高生成样本的质量和多样性。
这些方法可以单独或组合使用,以解决GAN训练中的模式崩溃和训练不稳定问题。需要注意的是,这些方法并非万能,在实际应用中可能需要根据具体问题进行调整和优化。

98 GAN 的损失函数是什么样的,代码实现
生成对抗网络(GAN)的损失函数包括生成器损失和判别器损失。以下是一个简单的原始GAN损失函数的形式:

生成器损失:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/271289
推荐阅读
相关标签