基于PyTorch的自编码器多标签分类模型性能不佳的问题排查与优化咨询
基于PyTorch的自编码器多标签分类模型性能不佳的问题排查与优化咨询
我正在用PyTorch构建一个基于自编码器的神经网络,解决多标签分类问题。我的整体思路如下:
- 从CSV文件加载数据集,进行数据清洗(删除缺失值和不必要的列),并选择特征子集
- 将数据拆分为特征(X)和多标签目标(y)——每个目标都是二元值(0或1)
- 使用
GroupShuffleSplit进行基于分组的训练/测试拆分,确保相关样本保持在一起,这是我的问题特性所必需的 - 最后用
StandardScaler对特征进行标准化
我找不到太多这类方法的示例,目前我的实现如下:
class MutationDataset(Dataset): def __init__(self, features, labels): self.features = features self.labels = labels def __len__(self): return len(self.features) def __getitem__(self, idx): return self.features[idx], self.labels[idx] # 模型架构 class AutoencoderClassifier(nn.Module): def __init__(self, input_dim, latent_dim=32, dropout_rate=0.2): super().__init__() self.encoder = nn.Sequential( nn.Linear(input_dim, 128), nn.ReLU(), nn.Dropout(dropout_rate), nn.Linear(128, latent_dim), nn.ReLU() ) self.decoder = nn.Sequential( nn.Linear(latent_dim, 128), nn.ReLU(), nn.Linear(128, input_dim) ) # 分类头输出原始logits self.classifier = nn.Sequential( nn.Linear(latent_dim, 64), nn.ReLU(), nn.Dropout(dropout_rate), nn.Linear(64, 4) ) def forward(self, x): encoded = self.encoder(x) decoded = self.decoder(encoded) logits = self.classifier(encoded) return decoded, logits
我的数据集类别高度不平衡(负类占主导)。为了解决这个问题,我尝试使用带正类权重的Focal Loss:
class FocalLoss(nn.Module): def __init__(self, alpha=1, gamma=3, reduction='mean'): """ Args: alpha (float or Tensor): 稀有类别的权重因子。也可以传入张量实现每类加权。 gamma (float): 聚焦参数。值越高,越关注难分类的样本。 reduction (str): 'mean', 'sum', 或 'none' """ super(FocalLoss, self).__init__() self.alpha = alpha self.gamma = gamma self.reduction = reduction def forward(self, logits, targets): # 逐元素计算标准BCE损失 BCE_loss = F.binary_cross_entropy_with_logits(logits, targets, reduction='none') # 获取概率 pt = torch.exp(-BCE_loss) # 计算Focal Loss的缩放因子 focal_term = (1 - pt) ** self.gamma loss = self.alpha * focal_term * BCE_loss if self.reduction == 'mean': return loss.mean() elif self.reduction == 'sum': return loss.sum() else: return loss
最后是我的模型训练代码:
def train_model(X_train, y_train, X_test, y_test, input_dim, device='cuda', learning_rate=0.001, batch_size=32, epochs=50, dropout_rate=0.2): train_dataset = MutationDataset(X_train, y_train) test_dataset = MutationDataset(X_test, y_test) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False) model = AutoencoderClassifier(input_dim=input_dim, dropout_rate=dropout_rate) model.to(device) # 计算每个标签的正类权重 pos_weights = [] for i in range(y_train.shape[1]): pos_count = np.sum(y_train[:, i]) neg_count = len(y_train) - pos_count weight = neg_count / pos_count if pos_count != 0 else 1.0 pos_weights.append(weight) pos_weights = torch.tensor(pos_weights, dtype=torch.float32, device=device) print("Pos weights:", pos_weights) recon_criterion = nn.MSELoss() class_criterion = FocalLoss(alpha=1, gamma=2, reduction='mean') optimizer = optim.Adam(model.parameters(), lr=learning_rate, weight_decay=1e-4) for epoch in range(epochs): model.train() total_loss = 0 for batch_x, batch_y in train_loader: batch_x = batch_x.to(device) batch_y = batch_y.to(device) optimizer.zero_grad() recon, logits = model(batch_x) loss = 0.7 * recon_criterion(recon, batch_x) + 0.3 * class_criterion(logits, batch_y) loss.backward() optimizer.step() total_loss += loss.item() print(f'Epoch {epoch+1}: Loss {total_loss/len(train_loader):.4f}') return model, test_loader
不用说,模型的表现非常糟糕:
- 训练过程中损失稳步下降——从第1轮的约0.20降到第50轮的约0.03
- 训练集上的准确率相对较高(大多数标签在80%–91%之间),但F1分数差异很大:有些标签能达到中等水平(比如约0.60),其他的则低得多(甚至为0)
- 测试集上部分标签的准确率还算合理(约77%–87%),但F1分数相比训练集骤降
- 其中一个标签,模型完全无法预测任何正例(训练集和测试集上的F1分数都是0)
我可以尝试调整一些参数,但感觉可能在整体方法上存在错误。我到底漏掉了什么?
备注:内容来源于stack exchange,提问作者Marta
相关产品推荐
相关产品推荐

