帮助对R中的kernlab的SVM使用predict()?

pou*_*def 6 r svm kernlab

我正在尝试使用kernlabR包来做支持向量机(SVM).对于我非常简单的例子,我有两条训练数据.A和B.

(A和B属于类型matrix- 它们是图形的邻接矩阵.)

所以我写了一个函数,它接受A + B并生成一个核矩阵.

> km
         [,1]     [,2]
[1,] 14.33333 18.47368
[2,] 18.47368 38.96053
Run Code Online (Sandbox Code Playgroud)

现在我使用kernlabksvm函数来生成我的预测模型.现在,我只想努力工作 - 我不担心训练错误等.

所以,问题1:我是否正确生成了我的模型?合理?

# y are my classes. In this case, A is in class "1" and B is in class "-1"
> y
[1]  1 -1

> model2 =  ksvm(km, y, type="C-svc", kernel = "matrix");
> model2
Support Vector Machine object of class "ksvm" 

SV type: C-svc  (classification) 
 parameter : cost C = 1 

[1] " Kernel matrix used as input."

Number of Support Vectors : 2 

Objective Function Value : -0.1224 
Training error : 0 
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.我们创建了自定义内核矩阵,然后使用该矩阵创建了一个ksvm模型.我们的训练数据标记为"1"和"-1".

现在预测:

> A
     [,1] [,2] [,3]
[1,]    0    1    1
[2,]    1    0    1
[3,]    0    0    0

> predict(model2, A)
Error in as.matrix(Z) : object 'Z' not found
Run Code Online (Sandbox Code Playgroud)

嗯,哦.这没关系.有点期待,真的."预测"需要某种矢量,而不是矩阵.

所以让我们尝试一些事情:

> predict(model2, c(1))
Error in as.matrix(Z) : object 'Z' not found
> predict(model2, c(1,1))
Error in as.matrix(Z) : object 'Z' not found
> predict(model2, c(1,1,1))
Error in as.matrix(Z) : object 'Z' not found
> predict(model2, c(1,1,1,1))
Error in as.matrix(Z) : object 'Z' not found
> predict(model2, km)
Error in as.matrix(Z) : object 'Z' not found
Run Code Online (Sandbox Code Playgroud)

上面的一些测试是荒谬的,但这是我的观点:无论我做什么,我都无法得到预测()来查看我的数据并进行预测.标量不起作用,向量不起作用.2x2矩阵不起作用,3x3矩阵也不起作用.

我在这做错了什么?

(一旦我弄清楚ksvm 想要什么,那么我可以确保我的测试数据能够以合理/合理/数学上合理的方式符合该格式.)

Ste*_*lou 21

如果你考虑支持向量机如何"使用"内核矩阵,你会发现你不能以你正在尝试的方式实现这一点(正如你所看到的那样:-)

当我第一次使用kernlab +一个内核矩阵时,我实际上有点挣扎......巧合的是,它也适用于图形内核!

无论如何,让我们首先意识到,由于SVM不知道如何计算内核函数,因此需要在新的(测试)示例之间计算这些值,并在训练步骤中将其作为支持向量选择的示例.

因此,您需要一起计算所有示例的内核矩阵.稍后您将通过在适当时从内核矩阵中删除行+列来对其他人进行训练并对其他人进行测试.让我告诉你代码.

我们可以使用ksvm文档中的示例代码来加载我们的工作空间中的一些数据:

library(kernlab)
example(ksvm)
Run Code Online (Sandbox Code Playgroud)

为了让绘图绘制,你需要返回几(2)次返回,并让示例完成,但是你现在应该在你的工作空间中有一个内核矩阵K.我们需要恢复y它应该用于其标签的向量(因为它已经被示例中的其他代码践踏):

y <- matrix(c(rep(1,60),rep(-1,60)))
Run Code Online (Sandbox Code Playgroud)

现在,选择要用于测试的示例子集

holdout <- sample(1:ncol(K), 10)
Run Code Online (Sandbox Code Playgroud)

从现在开始,我要:

  1. 创建一个以trainK原始K内核矩阵命名的训练核矩阵.
  2. 从我的训练集创建一个SVM模型 trainK
  3. 使用从模型中找到的支持向量来创建测试内核矩阵testK......这是奇怪的部分.如果您查看代码kernlab以查看它如何使用支持向量索引,您将看到为什么这样做.有可能以另一种方式做到这一点,但我没有看到任何关于使用内核矩阵进行预测的文档/示例,所以我在这里做"难的".
  4. 使用SVM预测这些功能并报告准确性

这是代码:

trainK <- as.kernelMatrix(K[-holdout,-holdout])  # 1
m <- ksvm(trainK, y[-holdout], kernel='matrix')  # 2
testK <- as.kernelMatrix(K[holdout, -holdout][,SVindex(m), drop=F]) # 3
preds <- predict(m, testK)  # 4
sum(sign(preds) == sign(y[holdout])) / length(holdout) # == 1 (perfect!)
Run Code Online (Sandbox Code Playgroud)

这应该就是这样做的.祝好运!

回复以下评论

K [-holdout,-holdout]是什么意思?(" - "是什么意思?)

想象一下,你有一个向量x,并且你想从中检索元素1,3和5,你可以这样做:

x.sub <- x[c(1,3,5)]
Run Code Online (Sandbox Code Playgroud)

如果要从元素1,3和5 x 之外检索所有内容,您需要执行以下操作:

x.sub <- x[-c(1,3,5)]
Run Code Online (Sandbox Code Playgroud)

因此K[-holdout,-holdout]返回K 除了我们想要保留的行之外的所有行和列.

你的as.kernelMatrix的参数是什么 - 尤其是[,SVindex(m),drop = F]参数(这是特别奇怪的,因为看起来整个括号是K的矩阵索引?)

是的,我将两个命令合并为一个:

testK <- as.kernelMatrix(K[holdout, -holdout][,SVindex(m), drop=F])
Run Code Online (Sandbox Code Playgroud)

既然您已经训练了模型,那么您希望为您的测试示例提供一个新的内核矩阵.K[holdout,]只会给你对应于训练样例的行K,以及所有列的行K.

SVindex(m)原始训练矩阵中为您提供支持向量的索引- 记住,已holdout删除那些行/列.因此,为了使这些列索引正确(即引用正确的sv列),我必须首先删除holdout列.

无论如何,也许这更清楚:

testK <- K[holdout, -holdout]
testK <- testK[,SVindex(m), drop=FALSE]
Run Code Online (Sandbox Code Playgroud)

现在testK只有我们的测试示例行和与支持向量对应的列.testK[1,1]将具有在您的第一个测试示例和第一个支持向量之间计算的内核函数的值.testK[1,2]将在您的第一个测试示例和第二个支持向量之间具有内核函数值等.

更新(2014-01-30)回答来自@wrah的评论

我玩这个已经有一段时间了,所以细节kernlab::ksvm有点生疏,但原则上这应该是正确的:-) ......这里有:

有什么意义testK <- K[holdout, -holdout]- 你不是要删除与测试集对应的列吗?

是.简短的回答是,如果你想predict使用一个内核矩阵,你必须提供一个矩阵,是维的rows通过support vectors.对于矩阵的每一行(您要预测的新示例),列中的值只是在该示例和支持向量之间评估的内核矩阵的值.

调用SVindex(m)返回原始训练数据维度中给出的支持向量的索引.

所以,首先testK <- K[holdout, -holdout]给我一个testK矩阵,其中包含我想要预测的示例行,并且列来自模型训练的相同示例(维度).

我的另一子集列testKSVindex(m)只给我这(现在)对应于我的支持向量列.如果我没有完成第一个[, -holdout]选择,返回的索引SVindex(m)可能与正确的示例不对应(除非N您的所有测试示例都是N矩阵的最后一列).

另外,drop = FALSE条件到底是做什么的?

这是一种防御性编码,以确保在执行索引操作后,返回的对象与索引的对象具有相同的类型.

在R中,如果仅索引2D(或更高(?))对象的一个​​维度,则返回较低维度的对象.我不想传递一个numeric矢量,predict因为它想拥有一个matrix

例如

x <- matrix(rnorm(50), nrow=10)

class(x)
[1] "matrix"

dim(x)
[1] 10  5

y <- x[, 1]

class(y)
[1] "numeric"

dim(y)
NULL
Run Code Online (Sandbox Code Playgroud)

data.frames等会发生同样的情况.