【问题标题】:svm from e1071 produces wrong results来自 e1071 的 svm 产生错误的结果
【发布时间】:2016-09-06 19:02:53
【问题描述】:

我正在尝试使用e1071 中的svm,在使用大量数据之前我打算玩玩具示例。

这就是我正在做的事情,我不明白为什么它显然不起作用。

# generate some silly 2D data
X = data.frame(x1 = runif(10), x2 = runif(10))
# attach a label according to position above/below diagonal x+y=1
X$y <- rep(1, 10)
X$y[(X$x1 + X$x2)<1] = -1
X$y <- factor(X$y)
# train svm model
require(e1071)
meta <- svm(y~., data = X, kernel = "linear", scale = FALSE)
# visualize the result
plot(meta, X)

因此,从这一点开始,图形错误已经可见,因为存在一些错误分类的点,并且分类器不是我所期望的(所有向量都是特别支持的)。

如果我想预测,那也是错的:

predict(meta, newdata = X[,-3])==X$y
[1]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE

如果我想进行手动预测,我也无法正常工作:

omega <- t(meta$coefs)%*%meta$SV
pred <- c(-sign(omega%*%t(X[,-3]) - meta$rho))
pred==X$y
 [1]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE

我确定我缺少某些东西,但不知道是什么!

【问题讨论】:

    标签: r svm


    【解决方案1】:

    我认为这里有两个不同的问题,你的模型和你的情节。模型很容易求解,但情节比较混乱。

    支持向量过多和预测不正确

    SVM 通常适用于缩放输入(mean=0,sd=1)。见this explanation of why SVM takes scaled inputs

    您可以先缩放输入,使用基本 R scale 函数或在调用 svm 时设置 scale=TRUE。我建议手动缩放,以便更好地控制:

    X <- as.data.frame(scale(data.frame(x1 = runif(10), x2 = runif(10))))
    X$y <- rep(1, 10)
    X$y[(X$x1 + X$x2)<0] <- -1
    X$y <- factor(X$y)
    require(e1071)
    meta <- svm(y~., data = X, kernel = "linear")
    

    您现在应该有一个合理数量的支持向量:

    meta
    
      Call:
      svm(formula = y ~ ., data = X, kernel = "linear")
    
    
      Parameters:
         SVM-Type:  C-classification 
       SVM-Kernel:  linear 
             cost:  1 
            gamma:  0.5 
    
      Number of Support Vectors:  4
    

    预测现在也应该是完美的:

    predict(meta, newdata = X[,-3])==X$y
     [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
    

    绘制 SVM

    不过,当我绘制 SVM 时,我仍然遇到与您相同的问题:多个“x”和“o”标签位于决策边界的错误一侧。

    但是,如果我使用 ggplot 手动绘制它,结果看起来是正确的:

    plotgrid <- expand.grid(seq(-2, 2, 0.1), seq(-2, 2, 0.1))
    names(plotgrid) <- c("x1", "x2")
    plotgrid$y <- predict(meta, newdata=plotgrid)
    library(ggplot2)
    ggplot(plotgrid) +
        geom_point(aes(x1, x2, colour=y)) +
        geom_text(data=X, aes(x1, x2, label=ifelse(y==-1, "O", "X"))) +
        ggtitle("Manual SVM Plot")
    

    所以至少我们知道底层的 SVM 模型是正确的。实际上,plot.svm 正确绘制了决策边界(您可以通过在 ggplot 调用中交换 x1 和 x2 轴来确认这一点,以匹配 plot.svm 默认使用的轴标签)。

    问题似乎是plot.svm 错误地标记了这些点。我不确定为什么。如果有人知道,请发表评论,我会更新这个答案。同时,我希望ggplot 解决方法就足够了。

    【讨论】:

    • 感谢您深入研究这个问题。据我对 svm 的了解,即使预测是正确的,svm 也是错误的:根据你的情节应该有 3 个支持向量,并且分离应该有更多或更少相同的斜率但更高的截距
    • 按照 SVM 的严格“最大边距”定义,我认为您是对的。但是请看一下csie.ntu.edu.tw/~cjlin/papers/guide/guide.pdf 的第 6 页(顺便说一下,整篇论文都值得一读)。我认为 LibSVM 计算更复杂,并且涉及“松弛”变量,因此有额外的支持向量。这是为了避免过度拟合并利用更多数据。
    • 我明白你的意思;确实我在想,对于这样一个简单的例子,这些松弛变量不会改变任何东西
    猜你喜欢
    • 1970-01-01
    • 2013-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多