我正在尝试使用svm
中的e1071
,在使用大量数据时,我打算使用玩具示例。
这就是我在做什么,而且我不明白为什么它显然不起作用。
# 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
我确定我遗失了一些东西,但无法弄清楚是什么!
答案 0 :(得分:2)
我认为这里有两个不同的问题,你的模型和你的情节。该模型很容易解决,但情节更加混乱。
支持向量太多,预测不正确
SVM通常适用于缩放输入(均值= 0,sd = 1)。请参阅this explanation of why SVM takes scaled inputs。
您可以先使用基础R scale
功能缩放输入,也可以在调用scale=TRUE
时设置svm
。我建议手动缩放,以便更好地控制:
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
解决方法就足够了。