PyTorch - Как отключить отсев в режиме оценки
Это модель, которую я определил, это простая 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
плавают 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)
Определите переменную и сделайте один раз б.п., я могу выяснить, потеря 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'
Но ни один из них не работал.
2 ответа
Вы должны определить свой 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
Я добавляю этот ответ только потому, что сейчас сталкиваюсь с той же проблемой, пытаясь воспроизвести глубокое байесовское активное обучение через несогласие с выбыванием. Если вам нужно сохранить активным отключение (например, для начальной загрузки набора различных прогнозов для одних и тех же тестовых экземпляров), вам просто нужно оставить модель в режиме обучения, нет необходимости определять собственный слой исключения.
Поскольку в pytorch вам нужно определить свою собственную функцию прогнозирования, вы можете просто добавить к ней параметр следующим образом:
def predict_class(model, test_instance, active_dropout=False):
if active_dropout:
model.train()
else:
model.eval()
Как и в других ответах, выпадающий слой желательно определить в вашей модели. __init__
метод, так что ваша модель может отслеживать всю информацию каждого предварительно определенного слоя. Когда состояние модели изменяется, она уведомляет все слои и выполняет соответствующую работу. Например, во время звонка model.eval()
Ваша модель будет деактивировать выпадающие слои, но сразу пропустит все активации. В общем, если вы хотите деактивировать свои выпадающие слои, вам лучше определить выпадающие слои в __init__
метод с использованием nn.Dropout
модуль.