英文:
skorch hyper-parameters grid search fails for classification task with probability vectors as labels (pytorch)
问题
我正在尝试使用skorch库为我的简单神经网络模型找到最佳超参数。
我的标签是概率向量,将一定的概率(高斯分布)分配给10个类别,例如:
y[0] = [0, 0, 0.1, 0.2, 0.5, 0.1, 0.1, 0, 0, 0]
我的模型是一个简单的全连接(FC)模型,输出10个值,这些值代表每个类别的置信度水平:
class Predictor(torch.nn.Module):
def __init__(self, input_size, layer_size, layer_num, dropout=0.2):
super().__init__()
self.hidden = torch.nn.ModuleList()
self.fc_in = torch.nn.Linear(input_size, layer_size)
for i in range(layer_num):
self.hidden.append(torch.nn.Linear(layer_size, layer_size))
self.fc_out = torch.nn.Linear(layer_size, 10)
self.drop = torch.nn.Dropout(p=dropout)
def forward(self, x):
x = F.relu(self.drop(self.fc_in(x)))
for layer in self.hidden:
x = F.relu(self.drop(layer(x)))
x = F.relu(self.fc_out(x))
return x
我正在使用skorch的NeuralNetClassifier
进行网格搜索:
data = CustomDataset("train_data.csv")
dataloader = DataLoader(data, batch_size=len(data), shuffle=True, num_workers=4)
batch, labels = next(iter(dataloader))
val_data = CustomDataset("validation_data.csv")
val_dataloader = DataLoader(val_data, batch_size=len(val_data), shuffle=True, num_workers=4)
batch_validation, labels_validation = next(iter(val_dataloader))
batch = torch.tensor(batch, dtype=torch.float32)
labels = torch.tensor(labels, dtype=torch.float32)
model = NeuralNetClassifier(
Predictor,
criterion=nn.CrossEntropyLoss,
optimizer=optim.Adam,
train_split=predefined_split(val_data),
module__input_size=1148,
module__layer_size=128,
module__layers_num=3,
verbose=True
)
# 定义网格搜索参数
param_grid = {
'batch_size': [10, 20],
'max_epochs': [10, 50]
}
grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=3, cv=3)
grid_result = grid.fit(batch, labels)
问题是我总是收到这个错误:
ValueError: 分类指标无法处理混合的连续多输出和二进制目标
有任何想法吗?
我尝试在模型的输出上应用softmax而不是ReLU,但没有成功。还尝试使用自定义评分函数,但没有任何变化。
英文:
I am trying to use the skorch library to find the best hyper parameters for my simple NN model.
My labels are a probabily vectors, that asing some probabily (gaussian) to 10 classes, for example:
y[0] = [0, 0, 0.1, 0.2, 0.5, 0.1, 0.1, 0, 0, 0]
My model is a simple FC model that outputs 10 values, which are the confidence level for each class:
class Predictor(torch.nn.Module):
def __init__(self, input_size, layer_size, layer_num, dropout=0.2):
super().__init__()
self.hidden = torch.nn.ModuleList()
self.fc_in = torch.nn.Linear(input_size, layer_size)
for i in range(layers_num):
self.hidden.append(torch.nn.Linear(layer_size, layer_size))
self.fc_out = torch.nn.Linear(layer_size, 10)
self.drop = torch.nn.Dropout(p=dropout)
def forward(self, x):
x = F.relu(self.drop(self.fc_in(x)))
for layer in self.hidden:
x = F.relu(self.drop(layer(x)))
x = F.relu(self.fc_out(x))
return x
And I am using the skorch NeuralNetClassifier
for the grid search:
data = CustomDataset("train_data.csv")
dataloader = DataLoader(data, batch_size=len(data), shuffle=True, num_workers=4)
batch, labels = next(iter(dataloader))
val_data = CustomDataset("validation_data.csv")
val_dataloader = DataLoader(val_data, batch_size=len(val_data), shuffle=True, num_workers=4)
batch_validation, labels_validation = next(iter(val_dataloader))
batch = torch.tensor(batch, dtype=torch.float32)
labels = torch.tensor(labels, dtype=torch.float32)
model = NeuralNetClassifier(
Predictor,
criterion=nn.CrossEntropyLoss,
optimizer=optim.Adam,
train_split=predefined_split(val_data),
module__input_size=1148,
module__layer_size=128,
module__layers_num=3,
verbose=True
)
# define the grid search parameters
param_grid = {
'batch_size': [10, 20],
'max_epochs': [10, 50]
}
grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=3, cv=3)
grid_result = grid.fit(batch, labels)
And the problem is that I am always getting this error:
ValueError: Classification metrics can't handle a mix of continuous-multioutput and binary targets
Any ideas?
I did try to apply softmax instead of ReLU in the output of the model and it didn't work. Also tried to use my custom scoring function and nothing changes.
答案1
得分: 0
NeuralNetClassifier
期望二进制目标(即单标签分类),而您的标签是用于多标签分类的概率向量。请使用 softmax
将其转换为概率:
import torch.nn.functional as F
class Predictor(torch.nn.Module):
def __init__(self, input_size, layer_size, layers_num, dropout=0.2):
super().__init__()
self.hidden = torch.nn.ModuleList()
self.fc_in = torch.nn.Linear(input_size, layer_size)
for _ in range(layers_num):
self.hidden.append(torch.nn.Linear(layer_size, layer_size))
self.fc_out = torch.nn.Linear(layer_size, 10)
self.drop = torch.nn.Dropout(p=dropout)
def forward(self, x):
x = F.relu(self.drop(self.fc_in(x)))
for layer in self.hidden:
x = F.relu(self.drop(layer(x)))
x = self.fc_out(x)
return F.softmax(x, dim=1) # 应用 softmax 转换为概率
然后,将您的标签重塑以匹配多标签分类的预期格式,如下所示:
labels = torch.argmax(labels, dim=1)
英文:
NeuralNetClassifier
is expecting binary targets (i.e., single-label classification) while your labels are probability vectors for multi-label classification. Use softmax
to convert to probabilities:
import torch.nn.functional as F
class Predictor(torch.nn.Module):
def __init__(self, input_size, layer_size, layers_num, dropout=0.2):
super().__init__()
self.hidden = torch.nn.ModuleList()
self.fc_in = torch.nn.Linear(input_size, layer_size)
for _ in range(layers_num):
self.hidden.append(torch.nn.Linear(layer_size, layer_size))
self.fc_out = torch.nn.Linear(layer_size, 10)
self.drop = torch.nn.Dropout(p=dropout)
def forward(self, x):
x = F.relu(self.drop(self.fc_in(x)))
for layer in self.hidden:
x = F.relu(self.drop(layer(x)))
x = self.fc_out(x)
return F.softmax(x, dim=1) # Apply softmax to convert to probabilities
Then reshape your labels to match the expected format for multi-label classification like this:
labels = torch.argmax(labels, dim=1)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论