dw建设网站视频,惠州建筑信息平台,论坛网页设计,网站建设的报价目录 1.批量归一化
1.1训练神经网络时出现的挑战
1.2核心思想
1.3原理
2.批量规范化层
2.1 全连接层
2.2 卷积层
2.3 总结
3. 代码实现
4. 使用批量规范化层的LeNet
5. 简明实现 1.批量归一化
现在主流的卷积神经网络几乎都使用了批量归一化 批量归一化是一种流行且…目录 1.批量归一化
1.1训练神经网络时出现的挑战
1.2核心思想
1.3原理
2.批量规范化层
2.1 全连接层
2.2 卷积层
2.3 总结
3. 代码实现
4. 使用批量规范化层的LeNet
5. 简明实现 1.批量归一化
现在主流的卷积神经网络几乎都使用了批量归一化 批量归一化是一种流行且有效的技术它可以持续加速深层网络的收敛速度 1.1训练神经网络时出现的挑战
1、数据预处理的方式通常会对最终结果产生巨大影响
使用真实数据时第一步是标准化输入特征使其均值为0方差为1这种标准化可以很好地与优化器配合使用可以将参数的量级进行统一 2、对于典型的多层感知机或卷积神经网络在训练时中间层中的变量可能具有更广的变化范围
不论是沿着从输入到输出的层、跨同一层中的单元、或是随着时间的推移模型参数的随着训练更新变化莫测 归一化假设变量分布中的不规则的偏移可能会阻碍网络的收敛 3、更深层的网络很复杂容易过拟合
这就意味着正则化变得更加重要 作者如果我是泡橘子 当神经网络比较深的时候会发现数据在下面损失函数在上面这样会出现什么问题
正向传递的时候数据是从下往上一步一步往上传递反向传递的时候数据是从上面往下传递这时候就会出现问题梯度在上面的时候比较大越到下面就越容易变小因为是n个很小的数进行相乘越到后面结果就越小也就是说越靠近数据的层的梯度就越小 上面的梯度比较大那么每次更新的时候上面的层就会不断地更新但是下面层因为梯度比较小所以对权重地更新就比较少这样的话就会导致上面的收敛比较快而下面的收敛比较慢这样就会导致底层靠近数据的内容网络所尝试抽取的网络底层的特征简单的局部边缘、纹理等信息变化比较慢上层靠近损失的内容高层语义信息收敛比较快所以每一次底层发生变化所有的层都得跟着变底层的信息发生变化就导致上层的权重全部白学了这样就会导致模型的收敛比较慢。 所以提出了假设能不能在改变底部信息的时候避免顶部不断的重新训练这也是批量归一化所考虑的问题 1.2核心思想
为什么会变因为方差和均值整个分布会在不同层之间变化
所以假设将分布固定假设每一层的输出、梯度都符合某一分布相对来说就是比较稳定的具体分布可以做细微的调整但是整体保持基本一致这样的话在学习细微的变动时也比较容易
批量归一化将不同层的不同位置的小批量mini-batch输出的均值和方差固定均值和方差的计算方法如下图所示 在这个基础上做额外的调整如下图所示 1.3原理 2.批量规范化层
回想一下批量规范化和其他层之间的一个关键区别是由于批量规范化在完整的小批量上运行因此我们不能像以前在引入其他层时那样忽略批量大小。 我们在下面讨论这两种情况全连接层和卷积层他们的批量规范化实现略有不同。
2.1 全连接层 2.2 卷积层 2.3 总结 3. 代码实现
下面我们从头开始实现一个具有张量的批量规范化层
import torch
from torch import nn
from d2l import torch as d2ldef batch_norm(X, gamma, beta, moving_mean, moving_var, eps, momentum):# 通过is_grad_enabled来判断当前模式是训练模式还是预测模式if not torch.is_grad_enabled():# 如果是在预测模式下直接使用传入的移动平均所得的均值和方差X_hat (X - moving_mean) / torch.sqrt(moving_var eps)else:assert len(X.shape) in (2, 4)if len(X.shape) 2:# 使用全连接层的情况计算特征维上的均值和方差mean X.mean(dim0)var ((X - mean) ** 2).mean(dim0)else:# 使用二维卷积层的情况计算通道维上axis1的均值和方差。# 这里我们需要保持X的形状以便后面可以做广播运算mean X.mean(dim(0, 2, 3), keepdimTrue)var ((X - mean) ** 2).mean(dim(0, 2, 3), keepdimTrue)# 训练模式下用当前的均值和方差做标准化X_hat (X - mean) / torch.sqrt(var eps)# 更新移动平均的均值和方差moving_mean momentum * moving_mean (1.0 - momentum) * meanmoving_var momentum * moving_var (1.0 - momentum) * varY gamma * X_hat beta # 缩放和移位return Y, moving_mean.data, moving_var.data
我们现在可以创建一个正确的BatchNorm层。 这个层将保持适当的参数拉伸gamma和偏移beta,这两个参数将在训练过程中更新。 此外我们的层将保存均值和方差的移动平均值以便在模型预测期间随后使用。
撇开算法细节注意我们实现层的基础设计模式。 通常情况下我们用一个单独的函数定义其数学原理比如说batch_norm。 然后我们将此功能集成到一个自定义层中其代码主要处理数据移动到训练设备如GPU、分配和初始化任何必需的变量、跟踪移动平均线此处为均值和方差等问题。 为了方便起见我们并不担心在这里自动推断输入形状因此我们需要指定整个特征的数量。 不用担心深度学习框架中的批量规范化API将为我们解决上述问题我们稍后将展示这一点。
class BatchNorm(nn.Module):# num_features完全连接层的输出数量或卷积层的输出通道数。# num_dims2表示完全连接层4表示卷积层def __init__(self, num_features, num_dims):super().__init__()if num_dims 2:shape (1, num_features)else:shape (1, num_features, 1, 1)# 参与求梯度和迭代的拉伸和偏移参数分别初始化成1和0self.gamma nn.Parameter(torch.ones(shape))self.beta nn.Parameter(torch.zeros(shape))# 非模型参数的变量初始化为0和1self.moving_mean torch.zeros(shape)self.moving_var torch.ones(shape)def forward(self, X):# 如果X不在内存上将moving_mean和moving_var# 复制到X所在显存上if self.moving_mean.device ! X.device:self.moving_mean self.moving_mean.to(X.device)self.moving_var self.moving_var.to(X.device)# 保存更新过的moving_mean和moving_varY, self.moving_mean, self.moving_var batch_norm(X, self.gamma, self.beta, self.moving_mean,self.moving_var, eps1e-5, momentum0.9)return Y
4. 使用批量规范化层的LeNet
为了更好理解如何应用BatchNorm下面我们将其应用于LeNet模型 6.6节。 回想一下批量规范化是在卷积层或全连接层之后、相应的激活函数之前应用的。
net nn.Sequential(nn.Conv2d(1, 6, kernel_size5), BatchNorm(6, num_dims4), nn.Sigmoid(),nn.AvgPool2d(kernel_size2, stride2),nn.Conv2d(6, 16, kernel_size5), BatchNorm(16, num_dims4), nn.Sigmoid(),nn.AvgPool2d(kernel_size2, stride2), nn.Flatten(),nn.Linear(16*4*4, 120), BatchNorm(120, num_dims2), nn.Sigmoid(),nn.Linear(120, 84), BatchNorm(84, num_dims2), nn.Sigmoid(),nn.Linear(84, 10))
和以前一样我们将在Fashion-MNIST数据集上训练网络。 这个代码与我们第一次训练LeNet 6.6节时几乎完全相同主要区别在于学习率大得多。
lr, num_epochs, batch_size 1.0, 10, 256
train_iter, test_iter d2l.load_data_fashion_mnist(batch_size)
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu()) 让我们来看看从第一个批量规范化层中学到的拉伸参数gamma和偏移参数beta。
net[1].gamma.reshape((-1,)), net[1].beta.reshape((-1,)) (tensor([0.4863, 2.8573, 2.3190, 4.3188, 3.8588, 1.7942], devicecuda:0,grad_fnReshapeAliasBackward0),tensor([-0.0124, 1.4839, -1.7753, 2.3564, -3.8801, -2.1589], devicecuda:0,grad_fnReshapeAliasBackward0)) 5. 简明实现
除了使用我们刚刚定义的BatchNorm我们也可以直接使用深度学习框架中定义的BatchNorm。 该代码看起来几乎与我们上面的代码相同。
net nn.Sequential(nn.Conv2d(1, 6, kernel_size5), nn.BatchNorm2d(6), nn.Sigmoid(),nn.AvgPool2d(kernel_size2, stride2),nn.Conv2d(6, 16, kernel_size5), nn.BatchNorm2d(16), nn.Sigmoid(),nn.AvgPool2d(kernel_size2, stride2), nn.Flatten(),nn.Linear(256, 120), nn.BatchNorm1d(120), nn.Sigmoid(),nn.Linear(120, 84), nn.BatchNorm1d(84), nn.Sigmoid(),nn.Linear(84, 10))