[英]Help using predict() for kernlab's SVM in R?
我正在嘗試使用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
函數來生成我的預測模型。 現在,我只想努力工作 - 我不擔心訓練錯誤等。
所以, 問題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矩陣也不起作用。
我在這做錯了什么?
(一旦我弄清楚ksvm 想要什么,那么我可以確保我的測試數據能夠以合理/合理/數學上合理的方式符合該格式。)
如果你考慮支持向量機如何“使用”內核矩陣,你會發現你不能以你正在嘗試的方式實現這一點(正如你所看到的那樣:-)
當我第一次使用kernlab +一個內核矩陣時,我實際上有點掙扎......巧合的是,它也適用於圖形內核!
無論如何,讓我們首先意識到,由於SVM不知道如何計算內核函數,因此需要在新的(測試)示例之間計算這些值,並在訓練步驟中將其作為支持向量選擇的示例。
因此,您需要一起計算所有示例的內核矩陣。 稍后您將通過在適當時從內核矩陣中刪除行+列來對其他人進行訓練並對其他人進行測試。 讓我告訴你代碼。
我們可以使用ksvm
文檔中的示例代碼來加載我們的工作空間中的一些數據:
library(kernlab)
example(ksvm)
為了讓繪圖繪制,你需要返回幾(2)次返回,並讓示例完成,但是你現在應該在你的工作空間中有一個名為K
的內核矩陣。 我們需要恢復它應該用於其標簽的y
向量(因為它已經被示例中的其他代碼踐踏):
y <- matrix(c(rep(1,60),rep(-1,60)))
現在,選擇要用於測試的示例子集
holdout <- sample(1:ncol(K), 10)
從現在開始,我要:
K
內核矩陣創建名為trainK
的訓練核矩陣。 trainK
創建一個SVM模型 testK
...這是奇怪的部分。 如果你看一下kernlab
中的代碼來看看它是如何使用支持向量索引的,你就會明白為什么它會以這種方式完成。 有可能以另一種方式做到這一點,但我沒有看到任何關於使用內核矩陣進行預測的文檔/示例,所以我在這里做“難的”。 這是代碼:
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!)
這應該就是這樣做的。 祝好運!
回復以下評論
K [-holdout,-holdout]是什么意思? (“ - ”是什么意思?)
想象一下你有一個向量x
,你想要從中檢索元素1,3和5,你會做:
x.sub <- x[c(1,3,5)]
如果你想從x
除了元素1,3和5 之外檢索所有內容,你可以:
x.sub <- x[-c(1,3,5)]
所以K[-holdout,-holdout]
返回所有的行和列的K
除了我們要抵抗的行。
你的as.kernelMatrix的參數是什么 - 尤其是[,SVindex(m),drop = F]參數(這是特別奇怪的,因為看起來整個括號是K的矩陣索引?)
是的,我將兩個命令合並為一個:
testK <- as.kernelMatrix(K[holdout, -holdout][,SVindex(m), drop=F])
既然您已經訓練了模型,那么您希望為您的測試示例提供一個新的內核矩陣。 K[holdout,]
會給你只對應於訓練樣本的行K
,並且所有的列的K
。
SVindex(m)
為您提供您的支持向量的指標從原來的訓練矩陣-記住,這些行/ COLS已holdout
刪除。 因此,對於那些列索引是正確的(即引用正確的SV列),我必須先卸下holdout
列。
無論如何,也許這更清楚:
testK <- K[holdout, -holdout]
testK <- testK[,SVindex(m), drop=FALSE]
現在testK
只有我們的測試示例行和與支持向量對應的列。 testK[1,1]
將具有在第一個測試示例和第一個支持向量之間計算的內核函數的值。 testK[1,2]
將在第一個測試示例和第二個支持向量之間具有內核函數值等。
更新(2014-01-30)回答來自@wrah的評論
我玩這個已經有一段時間了,所以kernlab::ksvm
有點生疏,但原則上這應該是正確的:-) ......這里有:
testK <- K[holdout, -holdout]
是什么testK <- K[holdout, -holdout]
- 你不是要刪除對應於測試集的列嗎?
是。 簡短的回答是,如果要使用內核矩陣進行predict
,則必須通過support vectors
維度rows
的矩陣。 對於矩陣的每一行(您要預測的新示例),列中的值只是在該示例和支持向量之間評估的內核矩陣的值。
對SVindex(m)
的調用返回原始訓練數據維度中給出的支持向量的索引。
所以,首先做testK <- K[holdout, -holdout]
給我一個testK
矩陣,其中包含我想要預測的示例行,並且列來自模型訓練的相同示例(維度)。
我的另一子集列testK
通過SVindex(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
data.frame
s等也會發生同樣的情況。
首先,我還沒有使用過kernlab 。 但只是查看文檔,我確實看到了predict.ksvm()
方法的工作示例。 復制和粘貼,並省略打印到屏幕:
## example using the promotergene data set
data(promotergene)
## create test and training set
ind <- sample(1:dim(promotergene)[1],20)
genetrain <- promotergene[-ind, ]
genetest <- promotergene[ind, ]
## train a support vector machine
gene <- ksvm(Class~.,data=genetrain,kernel="rbfdot",\
kpar=list(sigma=0.015),C=70,cross=4,prob.model=TRUE)
## predict gene type probabilities on the test set
genetype <- predict(gene,genetest,type="probabilities")
這似乎非常簡單:使用隨機抽樣生成訓練集genetrain
及其補充genetest
,然后通過ksvm
擬合,使用擬合調用predict()
方法,並以匹配格式調用新數據。 這是非常標准的。
您可能會發現Max Kuhn的插入包非常有用。 它為各種回歸,分類和機器學習方法和包提供了一般評估和測試框架,包括kernlab ,並包含幾個插圖和JSS論文 。
Steve Lianoglou是對的。
在kernlab中,它有點連線,並且在預測時需要每個測試示例和支持向量之間的輸入內核矩陣。 你需要自己找到這個矩陣。
例如,測試矩陣[nxm],其中n是測試樣本的數量,m是學習模型中的支持向量的數量(按SVindex(模型)的順序排序)。
示例代碼
trmat <- as.kernelMatrix(kernels[trainidx,trainidx])
tsmat <- as.kernelMatrix(kernels[testidx,trainidx])
#training
model = ksvm(x=trmat, y=trlabels, type = "C-svc", C = 1)
#testing
thistsmat = as.kernelMatrix(tsmat[,SVindex(model)])
tsprediction = predict(model, thistsmat, type = "decision")
kernels是輸入內核矩陣。 trainidx和testidx是用於訓練和測試的ID。
自己根據解決方案的元素構建標簽。 使用此替代預測方法,該方法采用ksvm模型(m)和原始訓練格式的數據(d)
predict.alt <- function(m, d){
sign(d[, m@SVindex] %*% m@coef[[1]] - m@b)
}
K是用於培訓的kernelMatrix
。 為了驗證,如果在訓練數據上運行predict.alt
,您會注意到備用預測器方法將值與ksvm返回的擬合值一起切換。 本機預測器以意想不到的方式運行:
aux <- data.frame(fit=kout@fitted, native=predict(kout, K), alt=predict.alt(m=kout, d=as.matrix(K)))
sample_n(aux, 10)
fit native alt
1 0 0 -1
100 1 0 1
218 1 0 1
200 1 0 1
182 1 0 1
87 0 0 -1
183 1 0 1
174 1 0 1
94 1 0 1
165 1 0 1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.