训练数据中组大小不等的 SVM

机器算法验证 r 机器学习 支持向量机
2022-03-16 09:55:36

我正在尝试从一组代表多于另一组的训练数据构建一个 SVM。但是,这些组将在最终的测试数据中得到同等的代表。因此,我想使用R包接口的class.weights参数来平衡两组在训练数据中的影响。e1071libsvm

由于我不确定应该如何指定这些权重,所以我设置了一个小测试:

  1. 生成一些空数据(随机特征;组标签之间的比例为 2:1)
  2. class.weights用参数集拟合 svm 。
  3. 预测一堆新的空数据集并查看类比例。
  4. 针对不同的空训练集多次复制整个过程。

这是我正在使用的 R 代码:

nullSVM <- function(n.var, n.obs) {
    # Simulate null training data
    vars   = matrix(rnorm(n.var*n.obs), nrow=n.obs)
    labels = rep(c('a', 'a', 'b'), length.out=n.obs)
    data   = data.frame(group=labels, vars)

    # Fit SVM
    fit = svm(group ~ ., data=data, class.weights=c(a=0.5, b=1))

    # Calculate the average fraction of 'a' we would predict from null test data
    mean(replicate(50, table(predict(fit, data.frame(matrix(rnorm(n.var*n.obs), nrow=n.obs))))[1])) / n.obs
}

library(e1071)
set.seed(12345)
mean(replicate(50, nullSVM(50, 300)))

从这整件事中,我期望输出 ~ 0.5,但是,这不是我得到的:

> mean(replicate(50, nullSVM(50, 300)))
[1] 0.6429987

class.weights参数起作用,有点像,因为 I weighta越低,它在此模拟中表示的越低(如果我省略class.weights它返回接近 1)......但我不明白为什么只使用 1:2 的权重(对于 2:1 的训练数据)并没有让我一路下降到 50%。

如果我误解了 SVM,有人可以解释这一点吗?(或发送一些参考?)

如果我做错了,有人可以告诉我使用class.weights参数的正确方法吗?

它可能是一个错误吗?(我认为不会,因为我理解这个软件和底层的 libsvm 已经相当成熟了)

2个回答

我认为这可能取决于 C 的值和您拥有的模式数量。SVM 试图找到最大边距判别式,所以如果你有稀疏数据,那么 SVM 可能会找到硬边距解决方案,而没有任何拉格朗日乘数达到其上限(在这种情况下,每个惩罚的比率类本质上是不相关的,因为松弛变量很小或为零。尝试增加训练模式的数量,看看是否有效果(因为这样就不太可能在盒子约束中找到硬边距解决方案) .

更重要的是,C 的最佳值是数据相关的,你不能只将它们设置为一些预先确定的值,而是通过最小化留一法误差或一些泛化界限来优化它们。如果您有不平衡的类,您可以固定每个类的值的比率,并优化所有模式的平均惩罚。

在训练 svm 时找到支持向量来形成判别边界,并且当所有类数据都有足够的支持向量来这样做时,就没有问题了。在测试集的结果准确性中,您应该注意现实世界中所有类的数据量相等,并且为了获得真实结果,您应该操纵数据并将其正确考虑到实际情况中。