BN层(Batch Normalization)+LN层(Layer Normalization)高频面试题集合

BN层高频面试题

    • BN的作用,为什么要用BN;
    • 为什么BN层一般用在线性层和卷积层后面,而不是放在非线性单元后
    • BN 计算过程,训练和测试的区别,训练是线性的吗?
    • BN训练时为什么不用整个训练集的均值和方差?
    • BN层的参数量
    • 手写BN
    • BN为什么能和卷积融合
    • BN在什么情况下能和卷积融合,可以放卷积前面吗
    • BN和LN区别
    • LN的作用,为什么Transformer用LN
    • 如何对BN层进行剪枝
    • 优点缺点
    • 代码实现
    • 如果只有一个样本BN层怎么求均值和方差呢?
    • Batch Normalization应该放在ReLU非线性激活层的前面还是后面?
    • GN层是什么

BN的作用,为什么要用BN;

BN层是深度学习中的一种常用层,全称为Batch Normalization(批量归一化)层,主要用于提高深度神经网络的训练速度和性能。
BN层的主要作用是对每一层的输入进行归一化,即将每个特征值减去其均值并除以其方差,使得网络中每一层的输入分布更加稳定,从而加速网络的收敛过程,避免梯度消失和梯度爆炸等问题。另外,BN层还能够减少模型对初始化的依赖,提高模型的泛化性能。
BN层的作用主要有三个:
1.加快网络的训练和收敛的速度;
2.控制梯度爆炸防止梯度消失;
3.防止过拟合。
加快网络的训练和收敛的速度
在深度神经网络中,如果每层的数据分布都不一样的话,将会导致网络非常难收敛和训练,而如果把每层的数据都在转换在均值为零,方差为1的状态下,这样每层数据的分布都是一样的训练会比较容易收敛。

控制梯度爆炸防止梯度消失
梯度消失:在深度神经网络中,如果网络的激活输出很大,其对应的梯度就会很小,导致网络的学习速率就会很慢,假设网络中每层的学习梯度都小于最大值0.25,网络中有n层,因为链式求导的原因,第一层的梯度将会小于0.25的n次方,所以学习速率相对来说会变的很慢,而对于网络的最后一层只需要对自身求导一次,梯度就大,学习速率就会比较快,这就会造成在一个很深的网络中,浅层基本不学习,权值变化小,而后面几层网络一直学习,后面的网络基本可以表征整个网络,这样失去了深度的意义。(使用BN层归一化后,网络的输出就不会很大,梯度就不会很小)

梯度爆炸:第一层偏移量的梯度=层斜率1x权值1x层斜率2x…层斜率(n-1)x权值(n-1)x层斜率n,假如**层斜率均为最大值0.25,所有层的权值为100,这样梯度就会指数增加。使用bn层后权值的更新也不会很大

防止过拟合
在网络的训练中,BN的使用使得一个minibatch中所有样本都被关联在了一起,因此网络不会从某一个训练样本中生成确定的结果,即同样一个样本的输出不再仅仅取决于样本的本身,也取决于跟这个样本同属一个batch的其他样本而每次网络都是随机取batch,这样就会使得整个网络不会朝这一个方向使劲学习。一定程度上避免了过拟合。

为什么BN层一般用在线性层和卷积层后面,而不是放在非线性单元后

原文中是这样解释的,因为非线性单元的输出分布形状会在训练过程中变化,归一化无法消除他的方差偏移,相反的,==全连接和卷积层的输出一般是一个对称,非稀疏的一个分布,更加类似高斯分布,对他们进行归一化会产生更加稳定的分布。==其实想想也是的,像relu这样的激活函数,如果你输入的数据是一个高斯分布,经过他变换出来的数据能是一个什么形状?小于0的被抑制了,也就是分布小于0的部分直接变成0了.

BN层的主要目的是加速模型的训练过程,减少模型的过拟合。在深度神经网络中,非线性单元(如ReLU、tanh等)会导致输入数据的分布发生变化,使得模型的学习过程变得更加困难。因此,BN层一般放在线性层和卷积层后面,以使得输入数据的分布更加稳定,从而加速模型的训练过程。而放在非线性单元后面,则可能会破坏输入数据的分布稳定性,影响模型的训练效果。因此,BN层一般不会放在非线性单元后面。

BN 计算过程,训练和测试的区别,训练是线性的吗?

BN层在网络的训练和测试过程中的区别在于,训练过程中需要计算每个batch的均值和方差,并且使用这个batch的均值和方差来归一化输入,而测试过程中则需要使用整个训练集的均值和方差来归一化输入。BN层(Batch Normalization)+LN层(Layer Normalization)高频面试题集合_第1张图片
训练时,BN层除了计算当前mini-batch的方差与均值并对该mini-batch进行逐channel归一化,还会存储这些mini-batch的方差与均值的方差无偏估计与滑动均值估计,并且逐mini-batch更新。当所有的mini-batch都训练过一遍之后,滑动均值就约等于整个训练集的均值,方差的无偏估计就约等于整个训练集的方法。又根据IID假设,它们就约等于测试时整个测试集的均值与方差。参数则直接使用学习到的γ、β。在实际实现时通常方差与均值都使用滑动平均估计。测试时BN层存储的实际前向传播参数量为channel数*(2+2)(每个channel都会存一个滑动平均的均值和方差)。
————————————————
版权声明:本文为CSDN博主「qq184861643」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq184861643/article/details/83539190
不是线性的。BN层的训练包括两个步骤:第一步是对训练数据进行标准化,第二步是对标准化后的数据进行缩放和平移,这些都是非线性的操作。此外,BN层还使用指数加权移动平均法来更新均值和方差,这也是非线性的。因此,BN层的训练是非线性的。

BN训练时为什么不用整个训练集的均值和方差?

因为用整个训练集的均值和方差容易过拟合,对于BN,其实就是对每一批数据进行归一化到一个相同的分布,而每一批数据的均值和方差会有一定的差别,而不是固定的值,这个差别能够增加模型的鲁棒性,也会在一定程度上减少过拟合。

BN层的参数量

我们知道γ和β是需要学习的参数,所以其实BN的本质就是利用优化改变方差大小和均值的位置。在CNN中,因为网络的特征是对应到一整张特征图上的,所以做BN的时候也是以特征图为单位而不是按照各个维度。比如在某一层,Batch大小为n,那么做BN的参数量为n×2。
BN层是对于每个神经元做归一化处理,甚至只需要对某一个神经元进行归一化,而不是对一整层网络的神经元进行归一化。既然BN是对单个神经元的运算,那么在CNN中卷积层上要怎么搞?假如某一层卷积层有6个特征图,每个特征图的大小是100×100,这样就相当于这一层网络有6×100×100个神经元,如果采用BN,就会有6×100×100个参数γ、β,这样岂不是太恐怖了。因此卷积层上的BN使用,其实也是使用了类似权值共享的策略,把一整张特征图(即一个channel)当做一个神经元进行处理。

卷积神经网络经过卷积后得到的是一系列的特征图,如果min-batch sizes为m,那么网络某一层输入数据可以表示为四维矩阵(m,f,p,q),m为min-batch sizes,f为特征图个数,p、q分别为特征图的宽高。在cnn中我们可以把每个特征图看成是一个特征处理(一个神经元),因此在使用Batch Normalization,mini-batch size 的大小就是:m×p×q,于是对于每个特征图都只有一对可学习参数:γ、β。其实这就是相当于求取所有样本所对应的一个特征图的所有神经元的平均值、方差,然后对这个特征图神经元做归一化。

即在CNN中BN层的前向传播参数量(理论参数量)为channel数*2.

手写BN

BN层(Batch Normalization)+LN层(Layer Normalization)高频面试题集合_第2张图片
1.计算样本均值。
2.计算样本方差。
3.样本数据标准化处理。
4.进行平移和缩放处理。引入了γ和β两个参数。来训练γ和β两个参数。引入了这个可学习重构参数γ、β,让我们的网络可以学习恢复出原始网络所要学习的特征分布。
BN就是对不同样本的同一特征做归一化。

BN为什么能和卷积融合

BN层和卷积层能够融合的原因是因为它们都是在卷积神经网络中进行前向传播的基本组件。BN层可以对每个输入的特征图进行均值和方差的归一化操作,从而使得网络更加稳定和可靠,减少了梯度消失和梯度爆炸的问题。而卷积层则是主要进行特征提取的组件,通过卷积操作可以将输入的特征图提取出更加高级的特征表示。

将BN层和卷积层进行融合可以进一步提高网络的性能和效率。融合后的组件可以同时进行归一化和特征提取操作,避免了在前向传播中多次进行BN操作和卷积操作的计算开销。此外,融合后的组件可以更好地利用GPU的并行计算能力,加速网络的训练和推理过程。因此,BN层和卷积层的融合是卷积神经网络中常用的优化技巧。

BN在什么情况下能和卷积融合,可以放卷积前面吗

BN在卷积层后面使用最为常见,因为它可以规范化卷积层输出的特征图,防止过拟合并加速模型收敛。但是在某些情况下,BN也可以和卷积层融合,这主要是为了优化模型的计算效率。具体可以采用以下几种方式:

将BN层的缩放和偏移参数合并到卷积层的权重和偏置中,从而避免了BN层的额外计算。

将BN层的均值和方差参数作为卷积层的权重的一部分,这样就可以在卷积操作中直接进行规范化。

需要注意的是,在使用这些方法时,需要小心调整参数,以确保模型的性能不会受到影响。另外,在某些情况下,将BN层放在卷积层之前也是可行的,但需要根据具体情况进行决策。

BN和LN区别

BN层和LN层都是常用的归一化方法,但是它们有一些区别。

BN层是针对batch维度进行归一化的,而LN层是针对feature维度进行归一化的。

BN层在训练过程中计算每个batch的均值和方差,然后在测试时使用训练集的总体均值和方差进行归一化,而LN层在训练和测试时都使用每个样本的均值和方差进行归一化。

BN层可以加速模型的收敛,在深层网络中使用效果更好,而LN层可以更好地处理不同样本之间的差异,对于较小的网络效果更好。

BN层的参数较多,需要学习每个特征的均值和方差,而LN层的参数较少,只需要学习每个特征的比例因子和偏差。

BN层对于batch size较小时效果不佳,而LN层对batch size的大小不敏感。

综上所述,BN层和LN层的适用场景不同,需要根据具体情况选择合适的归一化方法。

LN的作用,为什么Transformer用LN

LN代表Layer Normalization(层归一化),它是一种用于深度学习神经网络的正则化技术。它的作用是在神经网络中对每个层进行归一化,以便更好地控制梯度流和提高训练效率。

Transformer使用LN的主要原因是因为它可以解决训练过程中的梯度消失和梯度爆炸问题。通过对每个层进行归一化,LN可以使每个层输出的值具有相似的分布,从而减少梯度变化,并使训练更稳定。此外,它还可以提高模型的泛化能力,使得模型对于新的数据更具有鲁棒性。

如何对BN层进行剪枝

对BN层进行剪枝可以通过以下步骤:

计算每个BN层的标准差,选取阈值:通常情况下,保留在阈值以上的通道,忽略在阈值以下的通道。

针对每个BN层,计算每个通道的标准差(std)和均值(mean)。

根据阈值减少每个通道的尺寸。

重新建立网络:在剪枝后,需要重新构建网络,并将剪枝后的层添加到新网络中。

重新训练网络:在新网络上进行训练,以保证网络的准确性。训练时可以使用Dropout等技术来防止过拟合。

测试新网络:在新网络上进行测试,以评估网络的性能。

需要注意的是,对BN层进行剪枝可能会对网络的性能产生一定的影响。因此,在进行剪枝之前,需要在测试集上评估网络的性能,以确定阈值和剪枝后的通道数。

优点缺点

优点:

可以选择较大的初始学习率。因为这个算法收敛很快。
可以不用dropout,L2正则化。
不需要使用局部响应归一化。
可以把数据集彻底打乱。
模型更加健壮。
缺点:
Batch Normalization非常依赖Batch的大小,当Batch值很小时,计算的均值和方差不稳定。
所以BN不适用于以下几个场景:

小Batch
RNN

代码实现

def Batchmorm(x, gamma, beta, bn_param):

    #x_shape:[B,C,H,W]
    running_mean = bn_param['running_mean']
    running_var = bn_param['running_var']
    results = 0
    eps = 1e-5

    x_mean = np.mean(x, axis=(0, 2 ,3), keepdims=True)
    x_var = np.var(x, axis=(0, 2, 3), keepdims=True)
    x_normalized = (x - x_mean) / np.sqrt(x_var + eps)
    results = gamma * x_normalized + beta

    #因为在测试时是单个图片测试,这里保留训练时的均值和方差,用在后面测试时用
    runnng_mean = momentum * running_mean + (1 - momentum) * x_mean
    running_var = momentum * running_var + (1 - momentum) * x_var

    bn_param['running_mean'] = running_mean
    bn_param['running_var'] = running_var

    return results, bn_param

这段代码实现了Batch Normalization的前向传播过程。具体来说,它输入了一个batch的数据x,以及BN的参数gamma、beta和bn_param,输出了经过BN处理后的结果results和更新后的bn_param。

在具体实现中,首先从输入数据x中计算出均值x_mean和方差x_var,并利用它们对输入数据进行标准化处理,得到x_normalized。然后,使用参数gamma和beta将标准化后的数据进行线性变换,并输出最终结果results。

同时,为了在测试时能够使用之前训练得到的均值和方差,这段代码还会更新bn_param中的running_mean和running_var参数。具体来说,这里使用了一个指数加权平均的方法,利用之前的running_mean和running_var,以及当前batch的均值和方差,计算出更新后的running_mean和running_var,并将它们保存在bn_param中。

总的来说,这段代码实现了BN的前向传播过程,能够对输入数据进行标准化处理,并输出最终结果。同时,它还会更新BN的参数,以便在测试时能够使用之前训练得到的均值和方差。

如果只有一个样本BN层怎么求均值和方差呢?

其实就是问测试的时候,要用训练阶段整个数据集的均值方差

Batch Normalization应该放在ReLU非线性激活层的前面还是后面?

Batch Normalization可以放在ReLU非线性激活函数的前面或者后面,但通常建议将Batch Normalization置于ReLU之前。

原因如下:

非线性激活函数的前置:如果我们将Batch Normalization放在ReLU之前,它会规范化输入数据,并将其缩放成平均值为0、方差为1.这使得输入数据更易于通过ReLU,从而提高模型的效率和准确性。此外,将BN层放在激活函数的前面还可以帮助防止病态梯度(vanishing or exploding gradient)问题。

非线性激活函数的后置:我们也可以将Batch Normalization放在ReLU之后,在这种情况下,我们使用的是幅度而不是方向信息来“规范化”输出。在这种情况下,由于ReLU对负值产生截断作用,只有正值得到了该处理。然而,对于Batch Normalization来说,所有值都参与规范化过程,这可以有效地降低训练数据中的批量方差偏移(batch variance shift)。

总的来说,根据实际情况,Batch Normalization既可以放在ReLU之前,也可以放在ReLU之后。通常情况下,将其放在ReLU之前的效果更好一些。

GN层是什么

Group Normalization
GN层不在依赖 batch_size大小了,其将Channel分为多个组,在每一个组中求均值方差。这里附上代码

import torch
import torch.nn as nn
def group_norm(x:torch.Tensor,
               num_groups: int,
               num_channels: int,
               eps: float = 1e-5,
               gamma: float = 1.0,
               beta: float = 0):
    channels_per_group = num_channels//num_groups
    new_tensor = []
    for t in x.split(channels_per_group, dim=1):
        var_mean = torch.var_mean(t, dim=[1, 2, 3], unbiased=False)
        var = var_mean[0]
        mean = var_mean[1]
        mean = mean.unsqueeze(1).unsqueeze(2).unsqueeze(3).expand_as(t)
        #t = (t-mean[:, None, None, None])/torch.sqrt(var[:, None, None, None]+eps)
        t = (t - mean) / torch.sqrt(var[:, None, None, None] + eps)
        t = t*gamma+beta
        new_tensor.append(t)

    new_tensor = torch.cat(new_tensor, axis=1)
    return new_tensor

num_groups = 2
num_channels = 4
eps = 1e-5
img = torch.randn(2, num_channels, 2, 2)

gn = nn.GroupNorm(num_groups=num_groups, num_channels=num_channels, eps=eps)

r1 = gn(img)
print(r1)
r2 = group_norm(img, num_groups=num_groups, num_channels=num_channels, eps=eps)
print(r2)

其跟BN有点类似,但是求均值方差的方法跟以前不一样了。这里针对每一个mini_batch执行同样的处理,先将Channel分组,代码中是2,即分为两组,每一组求得该mini_batch上该Group的图像均值方差
然后在进行减均值除方差操作。同BN一样,网络也需要去学习一个gamma,beta参数。最后在进行加权。这里相比于BN,少了一个running_mean和running_std参数。言外之意网络只需要去学习gamma和beta参数。同时训练和测试都采用同样的模式,而不用model.eval().
BN层(Batch Normalization)+LN层(Layer Normalization)高频面试题集合_第3张图片
针对每一个 γ 和 β,GN 是对每一个 channel 进行学习的

其中两维 C 和 N 分别表示 channel 和 batch size,第三维表示 H,W,可以理解为该维度大小是 H ∗ W ,也就是拉长成一维,这样总体就可以用三维图形来表示。可以看出 BN 的计算和 batch size 相关(蓝色区域为计算均值和方差的单元),而 LN、BN 和 GN 的计算和 batch size 无关。同时 LN 和 IN 都可以看作是 GN 的特殊情况(LN 是 group=1 时候的 GN,IN 是 group=C 时候的GN)。

你可能感兴趣的:(python)