我试图使用 kernlab
R包来做支持向量机(SVM) . 对于我非常简单的例子,我有两条训练数据 . A和B.
(A和B的类型为 matrix
- 它们是图形的邻接矩阵 . )
所以我写了一个函数,它接受A B并生成一个核矩阵 .
> km
[,1] [,2]
[1,] 14.33333 18.47368
[2,] 18.47368 38.96053
现在我使用 kernlab
的 ksvm
函数来生成我的预测模型 . 现在,我不担心训练错误等 .
所以, Question 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
到现在为止还挺好 . 我们创建了自定义内核矩阵,然后使用该矩阵创建了一个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
嗯,哦 . 这没关系 . 有点期待,真的 . “预测”需要某种矢量,而不是矩阵 .
所以让我们尝试一些事情:
> 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
上面的一些测试是荒谬的,但这是我的观点:无论我做什么,我都无法得到预测()来查看我的数据并进行预测 . 标量不起作用,向量不起作用 . 2x2矩阵不起作用,3x3矩阵也不起作用 .
What am I doing wrong here?
(一旦我弄清楚ksvm想要什么,那么我可以确保我的测试数据能够以合理/合理/数学上合理的方式符合该格式 . )
4 回答
如果你考虑支持向量机如何“使用”内核矩阵,你会发现你不能以你正在尝试的方式实现这一点(正如你所看到的那样:-)
当我第一次使用kernlab一个内核矩阵时,我实际上有点挣扎......巧合的是,它也适用于图形内核!
无论如何,让我们首先意识到,由于SVM不知道如何计算内核函数,因此需要在新的(测试)示例之间计算这些值,并在训练步骤中将其作为支持向量选择的示例 .
因此,您需要一起计算所有示例的内核矩阵 . 稍后您将通过在适当时从内核矩阵中删除行列来对其他人进行训练并对其他列进行测试 . 让我告诉你代码 .
我们可以使用
ksvm
文档中的示例代码来加载我们的工作空间中的一些数据:为了让绘图绘制,你需要返回几(2)次返回,并让示例完成,但你现在应该在你的工作空间中有一个名为
K
的内核矩阵 . 我们需要恢复它应该用于其标签的y
向量(因为它已经被示例中的其他代码践踏):现在,选择要用于测试的示例子集
从现在开始,我要:
从原始
K
内核矩阵创建名为trainK
的训练核矩阵 .从我的训练集创建一个SVM模型
trainK
使用从模型中找到的支持向量来创建测试内核矩阵
testK
...这是奇怪的部分 . 如果你看一下kernlab
中的代码来看看它是如何使用支持向量索引的,那么你就是这样做的 . 有可能以另一种方式做到这一点,但我没有看到任何关于使用内核矩阵进行预测的文档/示例,所以我在这里做了"the hard way" .使用SVM预测这些功能并报告准确性
这是代码:
这应该就是这样做的 . 祝好运!
Responses to comment below
想象一下你有一个矢量
x
,你想要从中检索元素1,3和5,你会做:如果你想从
x
中检索除元素1,3和5之外的所有内容,你可以:所以
K[-holdout,-holdout]
返回K
的所有行和列,除了我们想要保留的行 .是的,我将两个命令合并为一个:
既然您已经训练了模型,那么您希望为您的测试示例提供一个新的内核矩阵 .
K[holdout,]
只会为您提供与K
中的训练示例相对应的行,以及K
的所有列 .SVindex(m)
从 original 训练矩阵中为您提供支持向量的索引 - 记住,这些行/列已删除holdout
. 因此,对于那些列索引是正确的(即,引用正确的sv列),我必须先删除holdout
列 .无论如何,也许这更清楚:
现在
testK
只有我们的测试示例行和与支持向量对应的列 .testK[1,1]
将具有在第一个测试示例和第一个支持向量之间计算的内核函数的值 .testK[1,2]
将在第一个测试示例和第二个支持向量之间具有内核函数值等 .Update (2014-01-30) to answer comment from @wrahool
它已经玩了这个,所以
kernlab::ksvm
的细节有点生疏,但原则上这应该是正确的:-) ......这里是:是 . 简短的回答是,如果你想使用内核矩阵,你必须通过
support vectors
提供维度为rows
的矩阵 . 对于矩阵的每一行(您要预测的新示例),列中的值只是在该示例和支持向量之间评估的内核矩阵的值 .对
SVindex(m)
的调用返回原始训练数据维度中给出的支持向量的索引 .所以,首先做
testK <- K[holdout, -holdout]
给我一个testK
矩阵,其中包含我想要预测的示例行,并且这些列来自模型所训练的相同示例(维度) .我进一步通过
SVindex(m)
对testK
的列进行了子集,只给出了(现在)对应于我的支持向量的列 . 如果我没有完成第一个[, -holdout]
选择,SVindex(m)
返回的索引可能与正确的示例不对应(除非您的测试示例的所有N
都是矩阵的最后N
列) .这是一种防御性编码,以确保在执行索引操作后,返回的对象与索引的对象具有相同的类型 .
在R中,如果仅索引2D(或更高(?))对象的一个维度,则返回较低维度的对象 . 我不想将
numeric
向量传递给predict
,因为它想拥有matrix
例如
data.frame
等会发生同样的事情 .首先,我没有多用kernlab . 但只是查看文档,我确实看到了
predict.ksvm()
方法的工作示例 . 复制和粘贴,并省略打印到屏幕:这看起来非常简单:使用随机采样生成训练集
genetrain
及其补码genetest
,然后通过ksvm
拟合,使用拟合调用predict()
方法,以及匹配格式的新数据 . 这是非常标准的 .您可能会发现Max Kuhn的caret包很有用 . 它为各种回归,分类和机器学习方法和包提供了一般评估和测试框架,包括kernlab,并包含几个小插图和一个JSS paper .
Steve Lianoglou是对的 .
在kernlab中,它有点连线,并且在预测时需要每个测试示例和支持向量之间的输入内核矩阵 . 你需要自己找到这个矩阵 .
例如,测试矩阵[n×m],其中n是测试样本的数量,m是学习模型中的支持向量的数量(按照SVindex(模型)的顺序排序) .
示例代码
kernels是输入内核矩阵 . trainidx和testidx是用于训练和测试的ID .
自己根据解决方案的元素构建标签 . 使用此替代预测方法,该方法采用ksvm模型(m)和原始训练格式的数据(d)
K是
kernelMatrix
用于训练 . 为了验证,如果在训练数据上运行predict.alt
,您会注意到备用预测器方法将值与ksvm返回的拟合值一起切换 . 本机预测器以意想不到的方式运行: