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

DropOut:正常神经网络需要对每一个节点进行学习,而添加了DropOut的神经网络通过删除部分单元(随机),即暂时将其从网络中移除,以及它的所有传入和传出连接。将DropOut应用于神经网络相当于从神经网络中采样了一个“更薄的”网络,即单元个数较少。(如上图所示,DropOut是从左图采样了一个更薄的网络,如图右)在正反向传播的过程中,采样了多个稀薄网络,即Dropout可以解释为模型平均的一种形式。
产生DropOut的动机:使用DropOut训练的神经网络中的每个隐藏单元必须学会与随机选择的其他单元样本一起工作,这样会使得每个隐藏单元更加的健壮,并使得他们尽量自己可以创造有用的功能,而不是依赖其他隐藏单元。即按照论文的话来说:减少神经元之间复杂的共适应关系。
官方论文例子: 50个人,分十个组,每五个人完成一个小阴谋,可能比50个人正确扮演各自角色完成一个大的阴谋更容易,当然,在时间足够,各种条件没有改变的情况下,那么完成一个大阴谋是更适合的,但生活总是充满变数,大阴谋往往不太容易实现,这样小的阴谋发挥作用的机会就会更大。同样的,在训练集上,各个隐藏单元可以协同发挥作用,即可以在训练集上可以训练的很好,但是这并不是我们需要的,我们需要他们在新的测试集上可以很好的合作,这时候DropOut体现出了它的价值!
本质上看: DropOut通过使其它隐藏层神经网络单元不可靠从而阻止了共适应的发生。因此,一个隐藏层神经元不能依赖其它特定神经元去纠正其错误。因为dropout程序导致两个神经元不一定每次都在一个dropout网络中出现。这样权值的更新不再依赖于有固定关系的隐含节点的共同作用,阻止了某些特征仅仅在其它特定特征下才有效果的情况 。迫使网络去学习更加鲁棒的特征 ,这些特征在其它的神经元的随机子集中也存在。
简介: 在神经网络的训练过程中,对于一次迭代中的某一层神经网络,先随机选择其中的一些神经元并将其临时丢弃,然后再进行本次的训练和优化。在下一次迭代中,继续随机隐藏一些神经元,直至训练结束。由于是随机丢弃,故而每一个批次都在训练不同的网络。
详细流程:

前提:带有L层隐藏层的神经网络。
l:第几层。
z: 代表输入向量
y: 代表输出向量
W:代表权重
b:偏差
f: 激活函数
没有DropOut的神经网络前向传播计算公式可以被描述为:l+1层的输入向量是l+1的权重乘以l层的输出向量加l+1层的偏差。l+1层的输出向量为经过激活函数的l+1层的输入向量。

添加DropOut的神经网络前向传播计算公式可以被描述为:相比于之前输出向量经过了伯努利分布,类似于经过一个门筛选了一下。*代表的是点积。

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

注意:
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是不是在0到1之间,如果不是的话直接抛出异常。
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]])

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

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
# 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
高斯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
本质: 不直接在神经元上应用dropout,而是应用在连接这些神经元的权重和偏置上。

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

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()详解.
我从没有见过极光出现的村落,也没有见过有人,在深夜放烟火。
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我有一些非常大的模型,我必须将它们迁移到最新版本的Rails。这些模型有相当多的验证(User有大约50个验证)。是否可以将所有这些验证移动到另一个文件中?说app/models/validations/user_validations.rb。如果可以,有人可以提供示例吗? 最佳答案 您可以为此使用关注点:#app/models/validations/user_validations.rbrequire'active_support/concern'moduleUserValidationsextendActiveSupport:
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs