Dropout的深入理解(基础介绍、模型描述、原理深入、代码实现以及变种)

news2024/11/28 10:59:22

目录

  • 前言
  • 一、DropOut简介
    • 1-1、DropOut论文图解
    • 1-2、DropOut介绍
    • 1-3、DropOut产生动机
    • 1-4、DropOut流程简介
  • 二、模型描述
    • 2-1、公式描述
    • 2-2、神经网络图描述
    • 2-3、一些需要注意的问题!
  • 三、Dropout代码实现以及相关变种(部分有实现)
    • 3-1、Dropout实现(Torch实现)
    • 3-2、Dropout实现(Numpy实现,训练集乘以1/(1-p),测试集不做变化)
    • 3-3、Dropout实现(Numpy实现,测试集变化)
    • 3-4、Dropout实现(复写一个类似于Pytorch中的Dropout)
    • 3-5、高斯Dropout
    • 3-6、DropConnect
    • 3-7、Standout
  • 附录1、nn.Linear()详解
  • 总结


前言

深度神经网络包含多个非线性隐藏层,这使得它们有强大的表现力,可以学习输入和输出之间非常复杂的关系。但是在训练数据有限的情况下,深度神经网络很容易过度学习造成过拟合,过拟合是深度神经网络的一个非常严重的问题,此外,神经网络越大,训练速度越慢,Dropout可以通过在训练神经网络期间随机丢弃单元来防止过拟合,实验证明Dropout有很好的效果。


一、DropOut简介

1-1、DropOut论文图解

左图:拥有两层隐藏层的正常神经网络。
右图:应用Dropout后的神经网络。(来源于官方论文)
在这里插入图片描述

1-2、DropOut介绍

DropOut:正常神经网络需要对每一个节点进行学习,而添加了DropOut的神经网络通过删除部分单元(随机),即暂时将其从网络中移除,以及它的所有传入和传出连接。将DropOut应用于神经网络相当于从神经网络中采样了一个“更薄的”网络,即单元个数较少。(如上图所示,DropOut是从左图采样了一个更薄的网络,如图右)在正反向传播的过程中,采样了多个稀薄网络,即Dropout可以解释为模型平均的一种形式。

1-3、DropOut产生动机

产生DropOut的动机:使用DropOut训练的神经网络中的每个隐藏单元必须学会与随机选择的其他单元样本一起工作,这样会使得每个隐藏单元更加的健壮,并使得他们尽量自己可以创造有用的功能,而不是依赖其他隐藏单元。即按照论文的话来说:减少神经元之间复杂的共适应关系。

官方论文例子: 50个人,分十个组,每五个人完成一个小阴谋,可能比50个人正确扮演各自角色完成一个大的阴谋更容易,当然,在时间足够,各种条件没有改变的情况下,那么完成一个大阴谋是更适合的,但生活总是充满变数,大阴谋往往不太容易实现,这样小的阴谋发挥作用的机会就会更大。同样的,在训练集上,各个隐藏单元可以协同发挥作用,即可以在训练集上可以训练的很好,但是这并不是我们需要的,我们需要他们在新的测试集上可以很好的合作,这时候DropOut体现出了它的价值!

本质上看: DropOut通过使其它隐藏层神经网络单元不可靠从而阻止了共适应的发生。因此,一个隐藏层神经元不能依赖其它特定神经元去纠正其错误。因为dropout程序导致两个神经元不一定每次都在一个dropout网络中出现。这样权值的更新不再依赖于有固定关系的隐含节点的共同作用,阻止了某些特征仅仅在其它特定特征下才有效果的情况 。迫使网络去学习更加鲁棒的特征 ,这些特征在其它的神经元的随机子集中也存在。

1-4、DropOut流程简介

简介: 在神经网络的训练过程中,对于一次迭代中的某一层神经网络,先随机选择其中的一些神经元并将其临时丢弃,然后再进行本次的训练和优化。在下一次迭代中,继续随机隐藏一些神经元,直至训练结束。由于是随机丢弃,故而每一个批次都在训练不同的网络。
详细流程

  • 首先随机(临时)删掉网络中一半的隐藏神经元(以dropout rate为0.5为例),输入输出神经元保持不变。
    在这里插入图片描述
  • 然后把输入x 通过修改后的网络前向传播,然后把得到的损失结果通过修改的网络反向传播。一小批(这里的批次batch_size由自己设定)训练样本执行完这个过程后,在没有被删除的神经元上按照随机梯度下降法更新对应的参数(w,b)
  • 重复以下过程:
    1、恢复被删掉的神经元(此时被删除的神经元保持原样,而没有被删除的神经元已经有所更新),因此每一个mini- batch都在训练不同的网络。
    2、从隐藏层神经元中随机选择一个一半大小的子集临时删除掉(备份被删除神经元的参数)。
    3、对一小批训练样本,先前向传播然后反向传播损失并根据随机梯度下降法更新参数(w,b) (没有被删除的那一部分参数得到更新,删除的神经元参数保持被删除前的结果)。

二、模型描述

2-1、公式描述

前提:带有L层隐藏层的神经网络。

l:第几层。
z: 代表输入向量
y: 代表输出向量
W:代表权重
b:偏差
f: 激活函数

没有DropOut的神经网络前向传播计算公式可以被描述为:l+1层的输入向量是l+1的权重乘以l层的输出向量加l+1层的偏差。l+1层的输出向量为经过激活函数的l+1层的输入向量。
在这里插入图片描述
添加DropOut的神经网络前向传播计算公式可以被描述为:相比于之前输出向量经过了伯努利分布,类似于经过一个门筛选了一下。*代表的是点积。
在这里插入图片描述

2-2、神经网络图描述

神经网络图示如下所示:左图为标准的神经网络,右图为添加了Dropout的神经网络,相比于标准的神经网络,添加了Dropout的神经网络相当于为前一层的输出向量添加了一道概率流程,即是否经过筛选。
在这里插入图片描述

2-3、一些需要注意的问题!

注意

  • 在测试中,权重参数w被缩放 W l = p W l W^l=pW^l Wl=pWl
  • 训练的过程中,会停止训练一些神经元,但是在测试的时候,整个模型是完整的,为了解决这个问题,我们会对没有被dropout的神经元权值做一个rescale,举个栗子:dropout rate为0.5,经过该算式之后rescale rate比例为2,即翻倍,这在一定程度上弥补了删掉一些神经元带来的误差。 r e s c a l e r a t e = 1 / ( 1 − d r o p o u t r a t e ) rescale rate=1 / (1 - dropout rate) rescalerate=1/(1dropoutrate)
  • 拓展延伸:如果不想测试阶段缩放权重,可以选择在训练阶段缩放激活函数,即反向Dropout,这样的话在测试阶段可以保持网络不变。所以我们换一个思路,在训练时候将剩余权重乘以1/(1-p),在测试时,就不需要做什么了。

三、Dropout代码实现以及相关变种(部分有实现)

3-1、Dropout实现(Torch实现)

import torch


# 定义dropout
def dropout_test(x, dropout):
    """
	:param x: input tensor
	:param dropout: probability for dropout
	:return: a tensor with masked by dropout
	"""
    # dropout must be between 0 and 1
    # 判断dropout是不是在01之间,如果不是的话直接抛出异常。
    assert 0 <= dropout <= 1
    # if dropout is equal to 0;just return self_x
    # 如果dropout为0,则返回原式
    if dropout == 0:
        return x
    # if dropout is equal to 1: put all values to zeros in tensor x
    # 如果dropout为1,则返回和输入形状相同的全0矩阵。
    if dropout == 1:
        return torch.zeros_like(x)
    # torch.rand is for return a tensor filled with values from uniform distribution [0,1)
    # we compare the values with dropout,if values is greater than dropout ,return 1,else 0
    # 生成一个mask矩阵,用来使一部分数据为0。
    mask = (torch.rand(x.shape) > dropout).float()
    # mask times x and give the scale(1-dropout) for the same expectation with before
    # 使用mask来遮掉部分数据,并且缩放剩余权重。
    return mask * x / (1.0 - dropout)


if __name__ == '__main__':
    # dropout_test
    input = torch.rand(3, 4)
    dropout = 0.8
    output = dropout_test(input, dropout)

    print(f"input={input}")
    print(f"output={output}")

输出:
input=tensor([[0.9379, 0.6264, 0.2145, 0.8403],
[0.6710, 0.7660, 0.0424, 0.2627],
[0.5760, 0.1775, 0.3744, 0.3073]])
output=tensor([[0.0000, 0.0000, 0.0000, 0.0000],
[0.0000, 0.0000, 0.2121, 0.0000],
[0.0000, 0.8876, 0.0000, 0.0000]])

3-2、Dropout实现(Numpy实现,训练集乘以1/(1-p),测试集不做变化)

在这里插入图片描述

import numpy as np

def another_train(rate, x, w1, b1, w2, b2):
	layer1 = np.maximum(0, (np.dot(x, w1) + b1))
	mask1 = np.random.binomial(1, 1.0 - rate, layer1.shape)
	layer1 = layer1 * mask1
	layer1 = layer1 / (1.0 - rate)
	
	layer2 = np.maximum(0, (np.dot(layer1, w2) + b2))
	mask2 = np.random.binomial(1, 1.0 - rate, layer2.shape)
	layer2 = layer2 * mask2
	layer2 = layer2 / (1.0 - rate)

	return layer2


def another_test(x, w1, b1, w2, b2):
	layer1 = np.maximum(0, np.dot(x, w1) + b1)
	layer2 = np.maximum(0, np.dot(layer1, w2) + b2)
	return layer2

3-3、Dropout实现(Numpy实现,测试集变化)

在这里插入图片描述

import numpy as np

def train(rate, x, w1, b1, w2, b2):
	"""
	description:
	if the train cannot use scale(1/(1-rate)) for output;
	then we need mutiply by (1.0-rate) for keeping the same expectation
	:param rate: probability of dropout
	:param x: input tensor
	:param w1: weight_1 of layer1
	:param b1: bias_1 of layer1
	:param w2: weight_2 of layer2
	:param b2: bias_2 of layer2
	:return: layer2
	"""
	layer1 = np.maximum(0, (np.dot(x, w1) + b1))
	mask1 = np.random.binomial(1, 1.0 - rate, layer1.shape)
	layer1 = layer1 * mask1

	layer2 = np.maximum(0, (np.dot(layer1, w2) + b2))
	mask2 = np.random.binomial(1, 1.0 - rate, layer2.shape)
	layer2 = layer2 * mask2
	return layer2


def test(rate, x, w1, b1, w2, b2):
	layer1 = np.maximum(0, np.dot(x, w1) + b1)
	layer1 = layer1 * (1.0 - rate)

	layer2 = np.maximum(0, np.dot(layer1, w2) + b2)
	layer2 = layer2 * (1.0 - rate)

	return layer2

3-4、Dropout实现(复写一个类似于Pytorch中的Dropout)

# nn.Module,继承自nn.Module。
class Dropout(nn.Module):
    def __init__(self, p=0.5):
        super(Dropout, self).__init__()
        if p <= 0 or p >= 1:
            raise Exception("p value should accomplish 0 < p < 1")
        self.p = p
        self.kp = 1 - p
        
    def forward(self, x):
        if self.training:
        	# 生成mask矩阵。
        	# torch.rand_like:生成和x相同尺寸的张量,取值在[0,1)之间均匀分布。
            mask = (torch.rand_like(x) < self.kp)
            # 先用mask矩阵对x矩阵进行处理,再除以1 - p(保留概率),即上述所说的反向DropOut操作,不需要在测试集上再缩放。
            return x * mask / self.kp
        else:
            return x

3-5、高斯Dropout

高斯Dropout: 在高斯Dropout中,每个节点可以看做乘以了p(1-p) ,所有节点都参与训练。

class GaussianDropout(nn.Module):
    def __init__(self, p=0.5):
        super(GaussianDropout, self).__init__()
        if p <= 0 or p >= 1:
            raise Exception("p value should accomplish 0 < p < 1")
        self.p = p
        
    def forward(self, x):
        if self.training:
        	# 式子算起来有些许区别。
            stddev = (self.p / (1.0 - self.p))**0.5
            epsilon = torch.randn_like(x) * stddev
            return x * epsilon
        else:
            return x

3-6、DropConnect

本质: 不直接在神经元上应用dropout,而是应用在连接这些神经元的权重和偏置上。

在这里插入图片描述

3-7、Standout

本质:神经元被遗漏的概率p在这一层并不是固定的,根据权重的值,它是自适应的。
在这里插入图片描述

附录1、nn.Linear()详解

nn.Linear():用于设置网络中的全连接层。

参数:
in_features:输入的二维张量的大小,即输入的[batch_size, size]中的size。例如Mnist数据集中,输入维度为[batch, 1, 28, 28],则size为12828,即真实输入我们首先需要转化为二维张量[batch, 12828],之后再输入。
out_features:输出二维张量的大小,输出二维张量的形状为[batch_size, output_size]。

总结:相当于一个输入为[batch_size, in_features]的张量变换成了[batch_size, out_features]的输出张量。

import torch as t
from torch import nn

# in_features由输入张量的形状决定,out_features则决定了输出张量的形状 
connected_layer = nn.Linear(in_features = 3*64*64, out_features = 1)

# 假定输入的图像形状为[3,64,64]
input = t.randn(1,3,64,64)

# 将四维张量转换为二维张量之后,才能作为全连接层的输入
input = input.view(1,3*64*64)
print(input.shape)
output = connected_layer(input) # 调用全连接层
print(output.shape)

输出:
torch.Size([1, 12288])
torch.Size([1, 1])

参考文章:
Dropout详解.
一文看尽12种Dropout及其变体.
dropout代码实现 学习笔记.

Dropout、高斯Dropout、均匀分布Dropout(Uout).
15 - Dropout的原理及其在TF/PyTorch/Numpy的源码实现.
伯努利分布——百度百科.
理解dropout.
CNN 入门讲解:什么是dropout?.
Dropout作用原理.
Dropout原理与实现.
PyTorch的nn.Linear()详解.


总结

我从没有见过极光出现的村落,也没有见过有人,在深夜放烟火。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/331498.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Part 4 描述性统计分析(占比 10%)——上

文章目录【后续会持续更新CDA Level I&II备考相关内容&#xff0c;敬请期待】【考试大纲】【考试内容】【备考资料】1、统计基本概念1.1、统计学的含义及应用1.1.1、统计学的含义1.2.1、统计学的应用1.2、统计学的基本概念1.2.1、数据及数据的分类1.2.2、总体和样本1.2.3、…

体系结构原则

构建和设计软件解决方案时应考虑到可维护性。 本部分概述的原则可帮助指导你作出体系结构决策&#xff0c;生成简洁、可维护的应用程序。 一般而言&#xff0c;在这些原则的指导下构建的应用程序各部分间可通过显式接口或消息传送系统进行通信&#xff0c;并非松散耦合的离散组…

WinRAR自解压实现安装程序并开机自启

1、选择要打包的文件&#xff0c;右键添加到压缩文件&#xff0c;勾选“创建自解压格式压缩文件” 2、切换到高级&#xff0c;选择“自解压文件选项” 3、常规 - 指定解压缩路径 4、安装 - 解压缩后运行指定程序 5、模式 - 隐藏全部 全部显示&#xff1a;显示启动对话框&#…

bcript 算法

一、简介 今天要给大家介绍的一种“加密”算法叫做 bcrypt&#xff0c;bcrypt 是由 Niels Provos 和 David Mazires 设计的密码哈希函数&#xff0c;他是基于 Blowfish 密码而来的&#xff0c;并于 1999 年在 USENIX 上提出。 除了加盐来抵御 rainbow table 攻击之外&#xf…

Vue3电商项目实战-首页模块6【22-首页主体-补充-vue动画、23-首页主体-面板骨架效果、4-首页主体-组件数据懒加载、25-首页主体-热门品牌】

文章目录22-首页主体-补充-vue动画23-首页主体-面板骨架效果24-首页主体-组件数据懒加载25-首页主体-热门品牌22-首页主体-补充-vue动画 目标&#xff1a; 知道vue中如何使用动画&#xff0c;知道Transition组件使用。 当vue中&#xff0c;显示隐藏&#xff0c;创建移除&#x…

C语言基础(十)—— 文件操作

1. 概述1.1磁盘文件和设备文件磁盘文件指一组相关数据的有序集合,通常存储在外部介质(如磁盘)上&#xff0c;使用时才调入内存。设备文件在操作系统中把每一个与主机相连的输入、输出设备看作是一个文件&#xff0c;把它们的输入、输出等同于对磁盘文件的读和写。1.2 磁盘文件的…

【C++】nullptr C++中的空指针(C++11)

前言 在平时我们写C/C代码时你可能会看到有人使用NULL表示空指针&#xff0c;也有人用nullptr表示空指针&#xff0c;那么你可能会很好奇它们都是空指针吗&#xff1f;为什么空指针有两种写法&#xff1f;下面就带你了解这背后的原理。 我们都知道NULL是C语言中的空指针&#x…

JDK14 新特性详解,2020-03-17 正式发布

预览版&#xff1a;该功能在当前版本可以使用&#xff0c;如果效果不是很好的话&#xff0c;可能以后的其他版本就会删去该功能。 最终版&#xff1a;该功能在之前版本效果很好&#xff0c;之后的每个版本中都会存在该功能。 1、Switch&#xff08;最终版&#xff09; 和之前…

从线程原理的角度来看C++内存的使用

文章目录线程的内存结构栈帧线程/进程调度线程的进一步使用线程安全和可重入一般的内存使用static变量使用new关键字&#xff0c;访问堆上的内存类中的内存使用从上一篇文章来看&#xff0c;线程的使用是比较简单的。但是在c环境下使用线程&#xff0c;最难也是最麻烦的点在于对…

云原生安全2.X 进化论系列|揭秘云原生安全2.X的五大特征

随着云计算技术的蓬勃发展&#xff0c;传统上云实践中的应用升级缓慢、架构臃肿、无法快速迭代等“痛点”日益明显。能够有效解决这些“痛点”的云原生技术正蓬勃发展&#xff0c;成为赋能业务创新的重要推动力&#xff0c;并已经应用到企业核心业务。然而&#xff0c;云原生技…

Mysql 数据类型

1、数值数据类型 1.1 整数类型(精确值) INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT MySQL支持SQL标准的整数类型INTEGER (或INT)和SMALLINT。作为标准的扩展&#xff0c;MySQL还支持整数类型TINYINT、MEDIUMINT和BIGINT。下表显示了每种整数类型所需的存储和范围。…

13.计算机视觉

13.计算机视觉 目录 图像增广 常用的图像增广方法 翻转和裁剪改变颜色结合多种图像增广方法 使用图像增广进行训练 多GPU训练 总结 微调 步骤 热狗识别获取数据集定义和初始化模型微调模型 总结 目标检测和边界框 边界框总结 目标检测数据集 下载数据集读取数据集演示总结 锚…

【3】深度学习之Pytorch——如何使用张量处理表格数据集(葡萄酒数据集)

张量是PyTorch中数据的基础。神经网络将张量输入并产生张量作为输出&#xff0c;实际上&#xff0c;神经网络内部和优化期间的所有操作都是张量之间的操作&#xff0c;而神经网络中的所有参数&#xff08;例如权重和偏差&#xff09;也都是张量。 怎样获取一条数据、一段视频或…

Java面试知识点

工作也有好些年了&#xff0c;从刚毕业到前几年看过无数的面试题&#xff0c;总想着自己写一个面试总结&#xff0c;随着自我认识的变化&#xff0c;一些知识点的理解也越来越不一样了。写下来温故而知新。很多问题可能别人也总结过&#xff0c;但是答案不尽相同&#xff0c;如…

纯css实现loading加载中(多种展现形式)

前言 现如今网页越来越趋近于动画&#xff0c;相信大家平时浏览网页或多或少都能看到一些动画效果&#xff0c;今天我们来做一个有意思的动画效果&#xff0c;纯 css 实现 loading 加载中&#xff08;多种展现形式&#xff09;&#xff0c;下面一起看看吧。 1. 常规 loading 实…

Linux系统之cuda 11情况下如何配置pytorch 10.2

由于目前pytorch1.8.2只能支持到10.2的版本&#xff0c;但ubuntu最新的系统驱动直接支持了cuda 11.4&#xff0c; 并且cuda tooklit支持的默认下载也是11.0。1、确认NVIDIA驱动安装lspci|grep NVIDIA1. 需要先降低cuda tooklit的版本(卸载新版本)cuda-uninstaller in /usr/loca…

统一附件存储MINIO部署使用

一、基于docker环境部署 1、创建docker-compose配置文件 1&#xff09;创建 docker-compose-minio.yml文件&#xff0c;内容如下&#xff1a; version: 3.7# Settings and configurations that are common for all containers x-minio-common: &minio-commonimage: quay…

结构体+枚举+联合体

目录 一、结构体的声明 &#xff08;一&#xff09;结构的基础知识 &#xff08;二&#xff09;结构的声明 &#xff08;三&#xff09;特殊的声明 &#xff08;四&#xff09;结构的自引用 1. 一个结构体内部包含一个类型为该结构本身的成员&#xff08;不合法&…

Day19 C++STL入门基础知识十一——map、multimap容器 构造赋值、大小交换、插入删除、查找统计、排序【全面深度剖析+例题代码展示】

&#x1f483;&#x1f3fc; 本人简介&#xff1a;男 &#x1f476;&#x1f3fc; 年龄&#xff1a;18 ✍每日一句&#xff1a;【道固远&#xff0c;笃行可至&#xff1b;事虽巨&#xff0c;坚为必成】 文章目录1. 基本概念2. 构造赋值① 函数原型② 代码展示③ 测试结果3. 大小…

基于tensorflow的垃圾分类系统

项目描述 该项目基于PySide2和PyQt5设计界面UI&#xff0c;搭配QT Designer进行界面设计。 基于TensorFlow中的Keras模型&#xff0c;进行垃圾分类模型的训练。 项目包含功能有&#xff1a;使用者注册登录功能、管理员训练模型、用户使用模型进行分类。 功能介绍 一、注册登…