nn.Dropout против F.dropout pyTorch - PullRequest
0 голосов
/ 21 ноября 2018

Используя pyTorch, есть два способа пропустить torch.nn.Dropout и torch.nn.F.Dropout.

Я изо всех сил пытаюсь увидеть разницу между их использованием
- когда и что использовать?
-Имеет ли это значение?
Я не вижу никакой разницы в производительности, когда переключаю их.

Ответы [ 3 ]

0 голосов
/ 23 ноября 2018

Технические различия уже были показаны в другом ответе.Однако основное отличие состоит в том, что nn.Dropout - это сам модуль горелки, который имеет некоторое удобство:

Краткий пример для иллюстрации некоторых отличий:

import torch
import torch.nn as nn

class Model1(nn.Module):
    # Model 1 using functional dropout
    def __init__(self, p=0.0):
        super().__init__()
        self.p = p

    def forward(self, inputs):
        return nn.functional.dropout(inputs, p=self.p, training=True)

class Model2(nn.Module):
    # Model 2 using dropout module
    def __init__(self, p=0.0):
        super().__init__()
        self.drop_layer = nn.Dropout(p=p)

    def forward(self, inputs):
        return self.drop_layer(inputs)
model1 = Model1(p=0.5) # functional dropout 
model2 = Model2(p=0.5) # dropout module

# creating inputs
inputs = torch.rand(10)
# forwarding inputs in train mode
print('Normal (train) model:')
print('Model 1', model1(inputs))
print('Model 2', model2(inputs))
print()

# switching to eval mode
model1.eval()
model2.eval()

# forwarding inputs in evaluation mode
print('Evaluation mode:')
print('Model 1', model1(inputs))
print('Model 2', model2(inputs))
# show model summary
print('Print summary:')
print(model1)
print(model2)

Вывод:

Normal (train) model:
Model 1 tensor([ 1.5040,  0.0000,  0.0000,  0.8563,  0.0000,  0.0000,  1.5951,
         0.0000,  0.0000,  0.0946])
Model 2 tensor([ 0.0000,  0.3713,  1.9303,  0.0000,  0.0000,  0.3574,  0.0000,
         1.1273,  1.5818,  0.0946])

Evaluation mode:
Model 1 tensor([ 0.0000,  0.3713,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,
         0.0000,  0.0000,  0.0000])
Model 2 tensor([ 0.7520,  0.1857,  0.9651,  0.4281,  0.7883,  0.1787,  0.7975,
         0.5636,  0.7909,  0.0473])
Print summary:
Model1()
Model2(
  (drop_layer): Dropout(p=0.5)
)

Итак, что я должен использовать?

И то, и другое полностью эквивалентно с точки зрения применения отсева, и хотя различия в использовании не так велики, есть некоторые причины, чтобы поддержатьnn.Dropout over nn.functional.dropout:

Выпадение предназначено для применения только во время обучения, поэтому при прогнозировании или оценке модели вы хотите, чтобы отсев был отключен.

Модуль отсеваnn.Dropout удобно обрабатывает это и отключает выпадение, как только ваша модель переходит в режим оценки, в то время как функциональный выпад не заботится о режиме оценки / прогнозирования.

Даже если вы можете установить функциональное отключение на training=False, чтобы отключить его, это все же не такое удобное решение, как с nn.Dropout.

.Частота выпадения хранится в модуле, поэтому вам не нужно сохранять ее в дополнительной переменной.В более крупных сетях вы можете захотеть создать разные выпадающие слои с разной скоростью выпадения - здесь nn.Dropout может повысить удобочитаемость и также может принести некоторое удобство при многократном использовании слоев.

Наконец, все модули, которые назначеныВаша модель зарегистрирована в вашей модели.Таким образом, ваш модельный класс отслеживает их, поэтому вы можете просто отключить выпадающий модуль, вызвав eval().При использовании функционального исключения ваша модель не знает об этом, поэтому она не будет отображаться ни в одной сводке.

0 голосов
/ 20 мая 2019

Проверка torch.nn.functional реализации:

 if p < 0. or p > 1.:
        raise ValueError("dropout probability has to be between 0 and 1, "
                         "but got {}".format(p))
    return (_VF.dropout_(input, p, training)
            if inplace
            else _VF.dropout(input, p, training))

Проверка: torch.nn.dropout реализации:

def forward(self, input):
        return F.dropout(input, self.p, self.training, self.inplace)

Итак: их внутренняя работа одинакова.Интерфейсы разные.Что касается _VF, я предполагаю, что это некоторый код C / C ++.

0 голосов
/ 21 ноября 2018

Если вы посмотрите на исходный код nn.Dropout и Functional.Dropout , вы увидите, что Functional - это интерфейс, а модуль nn реализует функции относительноэтот интерфейс.
Посмотрите на реализации в nn классе:

from .. import functional as F
class Dropout(_DropoutNd):
    def forward(self, input):
        return F.dropout(input, self.p, self.training, self.inplace)

class Dropout2d(_DropoutNd):
    def forward(self, input):
        return F.dropout2d(input, self.p, self.training, self.inplace)

И т. д.

Реализация Functional класса:

def dropout(input, p=0.5, training=False, inplace=False):
    return _functions.dropout.Dropout.apply(input, p, training, inplace)

def dropout2d(input, p=0.5, training=False, inplace=False):
    return _functions.dropout.FeatureDropout.apply(input, p, training, inplace)

посмотрите на пример ниже, чтобы понять:

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
        self.conv2_drop = nn.Dropout2d()
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)

    def forward(self, x):
        x = F.relu(F.max_pool2d(self.conv1(x), 2))
        x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
        x = x.view(-1, 320)
        x = F.relu(self.fc1(x))
        x = F.dropout(x, training=self.training)
        x = self.fc2(x)
        return F.log_softmax(x)

Существует функция F.dropout in forward() и функция nn.Dropout in __init__().Теперь это объяснение:

В PyTorch вы определяете свои Модели как подклассы torch.nn.Module.

В функции init вы должны инициализироватьслои, которые вы хотите использовать.В отличие от keras, Pytorch переходит на более низкий уровень, и вам необходимо указать размеры вашей сети, чтобы все совпадало.

В методе forward вы указываете соединения ваших слоев.Это означает, что вы будете использовать слои, которые вы уже инициализировали, чтобы повторно использовать один и тот же слой для каждого прямого прохода данных, которые вы делаете.

torch.nn.Functional содержит некоторые полезные функции, такие как функции активации сверткаоперации, которые вы можете использовать.Однако это не полные слои, поэтому, если вы хотите указать слой любого типа, вы должны использовать torch.nn.Module.

Вы должны использовать операции torch.nn.Functional conv, чтобы определить пользовательский слой дляпример с операцией свертки, но не для определения стандартного слоя свертки.

...