Spatial Dropout

Spatial DropoutSpatialDropout是Tompson等人在图像领域提出的一种dropout方法。普通的dropout会随机地将部分元素置零,而SpatialDropout会随机地将部分区域置零,该dropout方法在图像识别领域实践证明是有效的。dropoutdropout是怎么操作的?一般来说,对于输入的张量x,dropout就是随机地将部分元素置零,然后对结果做一个尺度变换。比如,我们随机初始化一…

大家好,又见面了,我是你们的朋友全栈君。

SpatialDropout是Tompson等人在图像领域提出的一种dropout方法。普通的dropout会随机地将部分元素置零,而SpatialDropout会随机地将部分区域置零,该dropout方法在图像识别领域实践证明是有效的。

dropout

dropout是怎么操作的?一般来说,对于输入的张量x,dropout就是随机地将部分元素置零,然后对结果做一个尺度变换。比如,我们随机初始化一个5×10的二维矩阵,即;

import numpy as np
x = np.random.random((4,5))
print(x)
def Dropout(x,drop_proba):
    return x * np.random.choice(
        [0,1],
        x.shape,
        p = [drop_proba,1-drop_proba]
    ) / (1. - drop_proba)
print(Dropout(x,0.5))
# x
[[0.56189429 0.03603615 0.97580132 0.36180956 0.55606632]
 [0.81176104 0.47364453 0.97262952 0.04289464 0.42820463]
 [0.26016082 0.61274373 0.10307323 0.84194222 0.48404058]
 [0.37371407 0.88847782 0.37580269 0.97473358 0.7809447 ]]

# dropout(x,0.5)
[[0.         0.07207229 0.         0.         1.11213264]
 [1.62352208 0.         1.94525904 0.08578928 0.        ]
 [0.52032163 1.22548745 0.         0.         0.        ]
 [0.         1.77695563 0.75160539 1.94946716 0.        ]]

可以看到,Dropout操作随机地将部分元素置零,并且对非零部分做了一个尺度变换。尺度变换的幅度跟初始化的drop_rate有关。

作用

一般,我们会将dropout理解为“一种低成本的集成策略”,这是对的,具体过程可以大概这样理解:
经过上述置零操作后,我们可以认为零的部分是被丢弃的,丢失了一部分信息。因而,逼着模型用剩下的信息区拟合目标。然而每次dropout是随机的。我们就不能侧重于某些节点,所以总的来说就是—每次逼着模型用少量的特征学习,每次被学习的特征又不同,那么就是说,每个特征都应该对
模型的预测有所贡献(而不是侧重于部分特征,导致过拟合)。

SpatialDropout

接下来,我们来详细看看keras模块中SpatialDropout具体做了啥,如下图所示:

Spatial Dropout


左:普通的dropout,右:SpatialDropout

首先,让我们看看SpatialDropout1D的输入和输出。SpatialDropout1D的输入是三维张量(samples,timesteps,channels),输出的纬度与输入的纬度相同。

我们以文本为例,一个文本的三维张量可以表示为(samples,sequence_length,embedding_dim),其中:

  • sequence_length表示句子的长度
  • embedding_dim表示词向量的纬度
    如下图所示:
Spatial Dropout

当我们对该张量使用dropout技术时,你会发现普通的dropout会随机独立地将部分元素置零,而SpatialDropout1D会随机地对某个特定的纬度全部置零,如下图所示:

Spatial Dropout


左:普通的dropout,右:SpatialDropout1D

接下来,我们简单的以一个简单的案例说明,首先,我们初始化一个1x7x5的三维张量,如下所示:

#encoding:utf-8
import numpy as np
import keras.backend as K
ary = np.arange(35).reshape((1, 7, 5))
inputs = K.variable(ary)
print(ary)
# result
[[[ 0  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]]]

接下来,我们将分别对该张量使用dropout和SpatialDropout1D技术。

首先,我们先对该张量测试普通的dropout,其中dropout_rate为0.5:

dropout_1 = K.eval(K.dropout(inputs, level=0.5))
print(dropout_1)
# result
[[[ 0.  2.  4.  6.  8.]
  [ 0.  0. 14. 16. 18.]
  [ 0.  0. 24.  0. 28.]
  [ 0. 32. 34.  0.  0.]
  [40.  0.  0.  0. 48.]
  [ 0. 52.  0. 56.  0.]
  [ 0. 62. 64.  0.  0.]]]

从结果中,我们可以看到普通的dropout随机地将部分元素置零,并且是无规律的,也就是说下次可能是另外一部分元素置零。

接下来,然后我们对该张量测试SpatialDropout1D,要达到SpatialDropout1D的效果。我们需要指定dropout的shape,对应dropout函数中的参数noise_shape。

noise_shape是一个一维张量,说白了就是一个一维数组,长度必须跟inputs.shape一样,而且,noise_shape的元素,只能是1或者inputs.shape里面对应的元素。比如inputs.shape= (3,4,5)
,那么noise_shape就只能是以下8种情况:

(3,4,5),(1,4,5),(3,1,5),(3,4,1),(1,1,5),(1,4,1),(3,1,1,),(1,1,1)

实际上,哪个轴为1,哪个轴就会被一致的dropout,比如(3,4,5)是就是普通的dropout,没有任何约束

因此,从上图中,我们想要实现SpatialDropout1D,noise_shape应为(input_shape[0], 1, input_shape[2]),即:

input_shape=K.shape(inputs)
noise_shape=(input_shape[0], 1, input_shape[2])
dropout_2 = K.eval(K.dropout(inputs, 0.5, noise_shape))
print(dropout_2)
# result
[[[ 0.  2.  0.  6.  8.]
  [ 0. 12.  0. 16. 18.]
  [ 0. 22.  0. 26. 28.]
  [ 0. 32.  0. 36. 38.]
  [ 0. 42.  0. 46. 48.]
  [ 0. 52.  0. 56. 58.]
  [ 0. 62.  0. 66. 68.]]]

可以看到,与普通的dropout不同的是,SpatialDropout1D随机地将某块区域全部置零。

实际上,我们也可以横向将部分区域全部置零,只需修改noise_shape即可,即:

noise_shape = (input_shape[0], input_shape[1], 1)
dropout_3 = K.eval(K.dropout(inputs, 0.5, noise_shape))
print(dropout_3)
# result
[[[ 0.  2.  4.  6.  8.]
  [ 0.  0.  0.  0.  0.]
  [20. 22. 24. 26. 28.]
  [ 0.  0.  0.  0.  0.]
  [40. 42. 44. 46. 48.]
  [50. 52. 54. 56. 58.]
  [60. 62. 64. 66. 68.]]]

所以,通过修改noise_shape,本质上我们可以实现任意功能的dropout。

在keras模块中,一般我们实现一个新的dropout,会按照下列模板进行,比如;

class TimestepDropout(Dropout):
    def __init__(self, rate, **kwargs):
        super(TimestepDropout, self).__init__(rate, **kwargs)
        self.input_spec = InputSpec(ndim=3)
    def _get_noise_shape(self, inputs):
        input_shape = K.shape(inputs)
        noise_shape = (input_shape[0], input_shape[1], 1)
        return noise_shape

:本质上是修改noise_shape,新类TimestepDropout继承了Dropout,我们知道当子类中存在与父类相同的函数时,子类的函数会更新父类函数。所以本质上就是修改获取noise_shape的函数。

备注:最近刚开始学习pytorch

pytorch

import torch.nn as nn
from itertools import repeat
class Spatial_Dropout(nn.Module):
    def __init__(self,drop_prob):

        super(Spatial_Dropout,self).__init__()
        self.drop_prob = drop_prob

    def forward(self,inputs):
        output = inputs.clone()
        if not self.training or self.drop_prob == 0:
            return inputs
        else:
            noise = self._make_noise(inputs)
            if self.drop_prob == 1:
                noise.fill_(0)
            else:
                noise.bernoulli_(1 - self.drop_prob).div_(1 - self.drop_prob)
            noise = noise.expand_as(inputs)
            output.mul_(noise)
        return output

    def _make_noise(self,input):
        return input.new().resize_(input.size(0),*repeat(1, input.dim() - 2),input.size(2))
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/131854.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • char (*p)[]和char *p[]的区别[建议收藏]

    理解的关键在于:1.[]的优先级高于*,(*p)[]理解为指向一个数组,*(p[])存放指针的数组2. char(*p)[SIZE]:指向一维数组的指针,一维数组只能有SIZE个元素

    2021年12月18日
    38
  • sql格式化工具-SQL Pretty Printer

    sql格式化工具-SQL Pretty Printersql格式化工具-SQLPrettyPrinter导言使用主要功能:其他功能:RenameTable和RenameColumnToC#(ToVB.NET)C#ToSQL(VB.NETToSQL)SQLFormatterOptions导言写SQL语句或者脚本时,很容易出现凌乱的情况,这里推荐一款很方便的SQLServer插件:SQLPrettyPrinter…

    2025年8月21日
    3
  • zigbee组网的设计_物联网组网技术

    zigbee组网的设计_物联网组网技术目前,针对一定区域内信息和设备进行监测和控制多采用有线方式通信,网络在布线和维护过程中由于线路腐蚀和损坏造成网络中断,给正常生产工作带来影响,同时也增加了人力资源成本比重。基于此,从节省成本和网络稳定性考虑,给出一种基于ZigBee技术的多节点设备无线自组网设计方案。   基于IEEE802.15.4协议的ZigBee技术是一种新兴的短距离无线通信技术,具有功耗低、成本低

    2022年10月8日
    2
  • c# linq用法_文言文中而的用法及例句

    c# linq用法_文言文中而的用法及例句记录C#中Linq的常用用法,方便使用时查找

    2025年8月2日
    3
  • 如何给女朋友做个树莓派复古相机?[通俗易懂]

    如何给女朋友做个树莓派复古相机?[通俗易懂]本文转载自程序员极客实验室手机拍照不够爽,带个单反又太重?试试做个树莓派复古相机,还能自己编写处理算法的那种——成本不到700元。没错,颜值很高,拍出来的照片也能打:你也可以快速上手做一个。如何制作一个树莓派复古相机目前,这部相机的代码、硬件清单、STL文件(用于3D打印)和电路图都已经开源。首先是硬件部分。这部复古相机的硬件清单如下:树莓派ZeroW(搭配microSD卡)、树莓派高清镜头模组、16mm1000万像素长焦镜头、2.2英寸TFT显

    2022年5月27日
    36
  • 3D编程软件(3d动画需要编程吗)

    本篇文章中,我们学习了UnityShader的基本写法框架,以及学习了Shader中Properties(属性)的详细写法,光照、材质与颜色的具体写法。写了6个Shader作为本文Shader讲解的实战内容,最后创建了一个逼真的暴风雪场景进行了Shader的测试。依旧是国际惯例先上本文配套程序的截图。先是一张远眺图:

    2022年4月11日
    37

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号