PyTorch - Как отключить отсев в режиме оценки - PullRequest
0 голосов
/ 21 декабря 2018

Это модель, которую я определил, это простая lstm с 2 полностью соединенными слоями.

import copy
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

class mylstm(nn.Module):
    def __init__(self,input_dim, output_dim, hidden_dim,linear_dim):
        super(mylstm, self).__init__()
        self.hidden_dim=hidden_dim
        self.lstm=nn.LSTMCell(input_dim,self.hidden_dim)
        self.linear1=nn.Linear(hidden_dim,linear_dim)
        self.linear2=nn.Linear(linear_dim,output_dim)
    def forward(self, input):
        out,_=self.lstm(input)
        out=nn.Dropout(p=0.3)(out)
        out=self.linear1(out)
        out=nn.Dropout(p=0.3)(out)
        out=self.linear2(out)
        return out

x_train и x_val - это плавающий фрейм данных с формой (4478,30), тогда как y_train иy_val являются float df с формой (4478,10)

    x_train.head()
Out[271]: 
       0       1       2       3    ...        26      27      28      29
0  1.6110  1.6100  1.6293  1.6370   ...    1.6870  1.6925  1.6950  1.6905
1  1.6100  1.6293  1.6370  1.6530   ...    1.6925  1.6950  1.6905  1.6960
2  1.6293  1.6370  1.6530  1.6537   ...    1.6950  1.6905  1.6960  1.6930
3  1.6370  1.6530  1.6537  1.6620   ...    1.6905  1.6960  1.6930  1.6955
4  1.6530  1.6537  1.6620  1.6568   ...    1.6960  1.6930  1.6955  1.7040

[5 rows x 30 columns]

x_train.shape
Out[272]: (4478, 30)

Определите переменную и выполните один раз bp, я могу узнать, что потери vaildation составляют 1.4941

model=mylstm(30,10,200,100).double()
from torch import optim
optimizer=optim.RMSprop(model.parameters(), lr=0.001, alpha=0.9)
criterion=nn.L1Loss()
input_=torch.autograd.Variable(torch.from_numpy(np.array(x_train)))
target=torch.autograd.Variable(torch.from_numpy(np.array(y_train)))
input2_=torch.autograd.Variable(torch.from_numpy(np.array(x_val)))
target2=torch.autograd.Variable(torch.from_numpy(np.array(y_val)))
optimizer.zero_grad()
output=model(input_)
loss=criterion(output,target)
loss.backward()
optimizer.step()
moniter=criterion(model(input2_),target2)

moniter
Out[274]: tensor(1.4941, dtype=torch.float64, grad_fn=<L1LossBackward>)

Но я позвонилФункция переадресации снова Я получаю другое число из-за случайности отсева

moniter=criterion(model(input2_),target2)
moniter
Out[275]: tensor(1.4943, dtype=torch.float64, grad_fn=<L1LossBackward>)

что мне делать, чтобы я мог устранить все пропуски в предсказывающей фразе?

Я пытался eval():

moniter=criterion(model.eval()(input2_),target2)
moniter
Out[282]: tensor(1.4942, dtype=torch.float64, grad_fn=<L1LossBackward>)

moniter=criterion(model.eval()(input2_),target2)
moniter
Out[283]: tensor(1.4945, dtype=torch.float64, grad_fn=<L1LossBackward>)

И передать дополнительный параметр p для управления выпадением:

import copy
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
class mylstm(nn.Module):
    def __init__(self,input_dim, output_dim, hidden_dim,linear_dim,p):
        super(mylstm, self).__init__()
        self.hidden_dim=hidden_dim
        self.lstm=nn.LSTMCell(input_dim,self.hidden_dim)
        self.linear1=nn.Linear(hidden_dim,linear_dim)
        self.linear2=nn.Linear(linear_dim,output_dim)
    def forward(self, input,p):
        out,_=self.lstm(input)
        out=nn.Dropout(p=p)(out)
        out=self.linear1(out)
        out=nn.Dropout(p=p)(out)
        out=self.linear2(out)
        return out

model=mylstm(30,10,200,100,0.3).double()

output=model(input_)
loss=criterion(output,target)
loss.backward()
optimizer.step()
moniter=criterion(model(input2_,0),target2)
Traceback (most recent call last):

  File "<ipython-input-286-e49b6fac918b>", line 1, in <module>
    output=model(input_)

  File "D:\Users\shan xu\Anaconda3\lib\site-packages\torch\nn\modules\module.py", line 489, in __call__
    result = self.forward(*input, **kwargs)

TypeError: forward() missing 1 required positional argument: 'p'

Но ни один из них не сработал.

Ответы [ 3 ]

0 голосов
/ 17 января 2019

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

0 голосов
/ 13 июня 2019

Я добавляю этот ответ только потому, что столкнулся с той же проблемой, пытаясь воспроизвести глубокое байесовское активное обучение через разногласия по поводу отсева.Если вам нужно сохранить активный отсев (например, для начальной загрузки набора различных прогнозов для одних и тех же тестовых экземпляров), вам просто нужно оставить модель в режиме обучения, нет необходимости определять свой собственный выпадающий слой.

Поскольку в pytorch вам нужно определить свою собственную функцию прогнозирования, вы можете просто добавить параметр к ней следующим образом:

def predict_class(model, test_instance, active_dropout=False):
    if active_dropout:
        model.train()
    else:
        model.eval()
0 голосов
/ 21 декабря 2018

Вы должны определить свой слой nn.Dropout в своем __init__ и назначить его своей модели, чтобы она отвечала на вызовы eval().

Поэтому изменение вашей модели должно работать для вас:

class mylstm(nn.Module):
    def __init__(self,input_dim, output_dim, hidden_dim,linear_dim,p):
        super(mylstm, self).__init__()
        self.hidden_dim=hidden_dim
        self.lstm=nn.LSTMCell(input_dim,self.hidden_dim)
        self.linear1=nn.Linear(hidden_dim,linear_dim)
        self.linear2=nn.Linear(linear_dim,output_dim)

        # define dropout layer in __init__
        self.drop_layer = nn.Dropout(p=p)
    def forward(self, input):
        out,_= self.lstm(input)

        # apply model dropout, responsive to eval()
        out= self.drop_layer(out)
        out= self.linear1(out)

        # apply model dropout, responsive to eval()
        out= self.drop_layer(out)
        out= self.linear2(out)
        return out

Если вы измените его так, как этот выпадет будет неактивным, как только вы позвоните eval().

ПРИМЕЧАНИЕ: Если вы хотите продолжить обучение после этого вам нужно позвонить train() в вашей модели, чтобы выйти из режима оценки.


Вы также можете найти небольшой рабочий пример для отсева с eval() для режима оценки здесь: nn.Dropoutпротив F.dropout pyTorch

...