处理多标签分类中的类不平衡

时间:2013-12-09 00:55:13

标签: machine-learning classification text-classification vowpalwabbit

我在多类设置中看到了关于类不平衡的一些问题。但是,我有一个多标签问题,所以在这种情况下你会怎么处理呢?

我有一组大约300k的文字示例。如标题中所述,每个示例至少有一个标签,并且只有100个可能的唯一标签。我已经通过利用命名空间将这个问题简化为Vowpal Wabbit的二进制分类,例如:

自:

healthy fruit | bananas oranges jack fruit
evil monkey | bipedal organism family guy
...  

要:

1 |healthy bananas oranges jack fruit
1 |fruit bananas oranges jack fruit
0 |evil bananas oranges jack fruit
0 |monkey bananas oranges jack fruit
0 |healthy bipedal organism family guy
0 |fruit bipedal organism family guy
1 |evil bipedal organism family guy
1 |monkey bipedal organism family guy
...  

我正在使用大众提供的默认选项(我认为是在线SGD,具有平方损失功能)。我正在使用平方损失,因为它非常类似汉明损失。

在训练之后,当在同一训练集上进行测试时,我注意到所有的例子都是用'0'标签预测的 ...这是减少损失的一种方法,我想。在这一点上,我不知道该怎么做。我正在考虑使用成本敏感的一对一分类来尝试平衡类,但是由于存在2 ^ 100个标签组合,因此将多标签减少到多类是不可行的。我想知道是否有其他人有任何建议。

编辑:我终于有机会测试了类失衡,特别是vwvw处理不平衡非常严重,至少对于高度维度,人口稀少的文本功能而言。我已经尝试过从1:1到1:25的比率,性能在1:2的比例下突然降低。

3 个答案:

答案 0 :(得分:4)

任何线性模型都会“非常糟糕”地处理类失衡,如果你强制它使用平方损失来解决二进制分类问题。想想损失函数:如果99%的观测值为零,则在所有情况下预测0都会得到0.01的平方误差。 Vowpal Wabbit不能做魔法:如果你要求它最小化平方误差损失,它确实会最小化平方误差损失,就像任何其他回归程序一样。

以下是R中线性回归模型的相同“问题”的演示:

set.seed(42)
rows <- 10000
cols <- 100
x <- matrix(sample(0:1, rows*cols, replace=TRUE), nrow=rows)
y <- x %*% runif(cols) + runif(rows)
y <- ifelse(y<quantile(y, 0.99), 0, 1)
lin_mod <- glm(y~., data.frame(y, x), family='gaussian') #Linear model
log_mod <- glm(factor(y)~., data.frame(y, x), family='binomial') #Logistic model

比较线性模型和逻辑模型的预测表明,线性模型总是预测为0,逻辑模型预测0和1的正确混合:

> table(ifelse(predict(lin_mod, type='response')>0.50, 1, 0))

    0 
10000 
> table(ifelse(predict(log_mod, type='response')>0.50, 1, 0))

   0    1 
9900  100 

在vowpal wabbit中使用--loss_function="logistic"--loss_function="hinge"来解决二进制分类问题。您可以在使用汉明丢失后评估您的预测,但是将您的结果与始终预测为0的汉明损失进行比较可能会提供信息。

答案 1 :(得分:1)

我认为你把问题简化为100,二进制分类问题?这将是在多标签设置中执行操作的标准方法。

如果您的评估指标确实是汉明损失,那么您实际上最好只预测每个二进制问题的多数。对于高度不平衡的问题,很难打败它。但在大多数情况下,您的评估指标本身就不同。例如,您可能希望优化F1度量(微观或宏)。在这种情况下,您可以尝试以某种方式平衡每个二进制问题的+ ve和-ve样本。有几种方法可以做到这一点。

正如Slater所说,你可以尝试针对每个学习问题优化AUC。在这种情况下,您将学习一个以实例作为输入的实值函数。现在不是在默认值(通常为0)下进行阈值处理,而是可以将其阈值设置为不同的值并尝试性能。

事实上,你可以尝试'不同'阈值处理,即使是你已优化的正常最小二乘法。这个阈值虽然至关重要,但你必须通过交叉验证来选择它。

此外,您无法更改阈值,但在不同的学习问题中更改示例的“权重”。例如,如果您发现1k样本中出现“健康”标签而29k样本中没有出现标签,那么对于带有“健康”标签的示例,重量为29,对于没有标签的示例,重量为1。

我不知道你在大众的表现如何。你必须弄明白。

答案 2 :(得分:0)

一般情况下,如果您想要考虑训练数据中的课程不平衡,则意味着您必须更改为更适合的失去函数。特别是对于类不平衡,您希望将损失函数更改为ROC曲线下的区域。专门设计用于解决此问题。

有一个多标签版本,但是如果你已经将它缩减为二进制分类,它应该只是开箱即用。

这是一个wikipedia article更全面地解释这个概念。

这是相关的sklearn documentation,由于我不确定这种情况发生在哪种语言,因此可能不太有用。