Dropout的rescale

部署运行你感兴趣的模型镜像

dropout 有两种实现方式,Vanilla Dropout 和inverted Dropout。前者是 原始论文 中的朴素版后者在 Andrew Ng 的 cs231 课程中(https://cs231n.github.io/neural-networks-2/#init)有介绍。其实就两个要点:

  1. rescale。输入序列为X=[x0,x1,x2,x3]X=[x_0,x_1,x_2,x_3]X=[x0,x1,x2,x3] ,正常的梯度序列为D=[d0,d1,d2,d3]D=[d_0,d_1,d_2,d_3]D=[d0,d1,d2,d3] ,假设以丢弃概率 p=0.2 进行伯努利采样Q得到的 mask 序列M =1011 。如果是 vanilla 版本,在 forward 时直接对输入进行遮罩X′=[x0,0,x2,x3]X^{'}=[x_0,0,x_2,x_3]X=[x0,0,x2,x3] ,在 backward 时梯度和输入保持一致D′=[d0,0,d2,d3]D^{'}=[d_0,0,d_2,d_3]D=[d0,0,d2,d3];在infer 时进行 1-p 倍的缩小I = 0.8X 。你看,训练时候因为随机扔掉了一些节点Q,总期望变小,那么预测时候就全体缩小一点来保持一致。这样处理的一个最大问题,就是预测过程需要跟着 dropout 策略做调整,哪些层取消了、加重了或者减轻了,都需要改。一不小心就会出错,inverted 版本顺势而生,把所有的修改都放在训练阶段,保持预测阶段不变。在 forward 时先遮罩再进行 1/(1-p) 的放大X′=1.25∗[x0,0,x2,x3]X^{'}=1.25*[x_0,0,x_2,x_3]X=1.25[x0,0,x2,x3],在 backward 时需要同步修改梯度D′=[d0,0,d2,d3]D^{'}=[d_0,0,d_2,d_3]D=[d0,0,d2,d3],在 infer 时不做额外的处理I = X。训练时虽然也随机扔掉了一些节点,但是做了 rescale 之后总期望被拉回了原来的水平,训练过程和预测过程仍然是一致的。
  2. forward和backward的时候扩大1-p倍,Infer的时候啥也不用干了

Pytorch对dropout的实现早就被放到cpp和cuda里去了,在古早版本里还有python版本的dropout,在https://github.com/colesbury/pytorch-old/blob/master/torch/nn/functions/dropout.py 这里可以看到源代码,input.new()就是随机了一个矩阵,下面摘录一些要点:

import torch
import torch.nn as nn
import torch.autograd.functional as Function

class MyDropoutFunc(Function):
    def __init__(self, p, train):
        self.p = p
        self.train = train
    def forward(self, input):
        if self.p > 0 and self.train:
            self.noise = self.rand(input.size()).bernoulli_(1 - self.p).div_(1 - self.p)
            input.mul_(self.noise)
            return input
        return input
    def backward(self, grad_output):
        if self.p > 0 and self.train:
            return grad_output.mul(self.noise)
        else:
            return grad_output

补充一个写成nn.Module的版本:

import torch
import torch.nn as nn
class MyDropout(nn.Module):
    def __init__(self,p):
        super(MyDropout, self).__init__()
        self.p = p
    def forward(self, input):
        self.noise = torch.rand(input.size()).bernoulli_(1-self.p).div_(1-self.p)
        if self.training and self.p > 0:
            input.mul_(self.noise)
            return input
        return input
    def backward(self, grad_output):
        if self.train and self.p > 0:
            grad_output.mul_(self.noise)
        return grad_output

if __name__ == '__main__':
    input = torch.randn(4,3)
    input2 = input.clone()
    my_dropout = MyDropout(0.2)
    my_dropout.train()
    print(my_dropout(input))
    dropout = nn.Dropout(0.2)
    print(dropout(input2))
'''
tensor([[-0.5323,  0.6883, -1.2510],
        [ 0.0000,  0.3083,  0.0000],
        [ 0.9472,  0.0000,  0.8548],
        [ 0.4423, -0.0776,  1.0469]])
tensor([[-0.5323,  0.6883, -0.0000],
        [ 0.4311,  0.3083,  0.0000],
        [ 0.9472,  0.3472,  0.8548],
        [ 0.4423, -0.0776,  1.0469]])
'''

部分转述自: https://www.zhihu.com/question/60874090/answer/181672076?from=groupmessage

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

import tensorflow as tf from tensorflow import keras from tensorflow.keras.applications.vgg16 import VGG16 from tensorflow.keras.layers import Dense, Flatten, Dropout from tensorflow.keras.models import Model from tensorflow.keras.preprocessing.image import ImageDataGenerator import os # 加载VGG16模型,不包含顶部的全连接层 base_model = VGG16(weights=None, include_top=False, input_shape=(224, 224, 3)) # 加载预训练的权重文件 weights_path = 'vgg16_weights_tf_dim_ordering_tf_kernels.h5' base_model.load_weights(weights_path) # 冻结预训练模型的所有层 for layer in base_model.layers: layer.trainable = False # 添加自定义的全连接层 x = Flatten()(base_model.output) x = Dense(1024, activation='relu', name='fc1')(x) x = Dense(1024, activation='relu', name='fc2')(x) x = Dropout(0.5, name='dropout_1')(x) predictions = Dense(8, activation='softmax', name='dense_1')(x) # 创建新的模型 model = Model(inputs=base_model.input, outputs=predictions) # 编译模型 model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) # 数据预处理和增强 train_datagen = ImageDataGenerator( rescale=1./255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True ) test_datagen = ImageDataGenerator(rescale=1./255) # 加载训练数据和预测数据 train_generator = train_datagen.flow_from_directory( 'coco-animals/train', target_size=(224, 224), batch_size=32, class_mode='categorical' ) test_generator = test_datagen.flow_from_directory( 'testImages', target_size=(224, 224), batch_size=32, class_mode='categorical' ) # 训练模型 model.fit( train_generator, steps_per_epoch=train_generator.samples // train_generator.batch_size, epochs=10, validation_data=test_generator, validation_steps=test_generator.samples // test_generator.batch_size ) # 进行预测 predictions = model.predict(test_generator)
最新发布
10-15
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值