2013-06-12 47 views
6

我有緯度和經度,所以我需要將RBF內核重新定義爲exp(-1/2 || sophere distrance ||^2),這意味着我需要自己重寫一個內核函數。 我寫我的內核如下:如何在kernlab包的ksvm中定製內核函數?

round.kernel <- function(x,y){ 
    sigma <- 1 
    #R <- 6371 
    R <- 1 
    a <- (sin((x[1]-y[1])/2))^2+cos(x[1])*cos(y[1])*(sin((x[2]-y[2])/2))^2 
    c <- 2*atan2(sqrt(a),sqrt(1-a)) 
    d <- R*c 
    res <- exp(-d^2/(2*sigma)) 
    return (res) 
} 
class(round.kernel) <- "kernel" 

我測試的功能,內核應該是正確的。但具有下列訓練命令我得到的錯誤:

fit <- ksvm(y=train[,2],x=train[,3:4],kernel=round.kernel,type='eps-svr') 

Error in .local(x, ...) : 
    List interface supports only the stringdot kernel. 

更trickly的事情是,我試圖ksvm文檔中的示例代碼:

k <- function(x,y) {(sum(x*y) +1)*exp(-0.001*sum((x-y)^2))} 
class(k) <- "kernel" 

但我得到同樣的錯誤。

任何人都知道如何正確定義內核函數?

+0

這真的很有幫助。你能解釋你如何派生內核函數嗎?我沒有看到exp(-1/2 || sphere distnace ||^2)和你如何完成'res'之間的聯繫。 – momeara

+0

@momeara,我認爲它基本上是基於三角函數,所以可以有多種方法使用arctan,arcsin或atan2這樣做。檢查這個鏈接:http://www.movable-type.co.uk/scripts/latlong.html –

+0

這個例子適合我。 –

回答

6

我的問題解決如下: 內核代碼是正確的,我應該直接定義一個函數(x,y),並將它的類聲明爲「內核」。問題在於,即使在文檔中,ksvm確實支持x,y樣式,但實際上它們不起作用。它更改爲配方數據風格終於可以得到的東西運行:

fit <- ksvm(Freq~lat+lon,data=train[,2:4],kernel=roundrbf,type='eps-svr') 

而且,我也讀rbfdot的源代碼,並在k​​ernlab本身定義的其他內核。注意他們的代碼風格是這樣的:

function(params){ 
    val <- function(x,y){ 
    # True kernel defined here 
    } 
    return (new ("kernel_name",.Data=val,kpar=list(params))) 
} 

但嚴重的是,我試過了,並且使這種風格的內核函數不起作用。工作方式直接像這樣:

k <- function(x,y){ 
    #calculate the result 
} 
class(k) <- "kernel"