2009-11-18 7 views
6

Sto tentando di utilizzare il pacchetto kernlab R per SVM (Support Vector Machines). Per il mio esempio molto semplice, ho due dati di allenamento. A e B.Aiuta ad usare predict() per SVM di kernlab in R?

(A e B sono di tipo matrix - sono matrici di adiacenza per grafi.)

Così ho scritto una funzione che prende A + B e genera una matrice kernel.

> km 
     [,1]  [,2] 
[1,] 14.33333 18.47368 
[2,] 18.47368 38.96053 

ora uso la funzione kernlab s' ksvm per generare il mio modello predittivo. In questo momento, sto solo cercando di far funzionare il maledetto lavoro - non sono preoccupato per errori di allenamento, ecc.

Quindi, Domanda 1: Sto generando il mio modello correttamente? Ragionevolmente?

# 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 

Fin qui tutto bene. Abbiamo creato la nostra matrice del kernel personalizzata, e quindi abbiamo creato un modello ksvm usando quella matrice. Abbiamo i nostri dati di allenamento etichettati come "1" e "-1".

Ora per prevedere:

> 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 

Uh-oh. Questo va bene. Tipo di aspettato, davvero. "Predire" vuole una specie di vettore, non una matrice.

Quindi, consente di provare alcune cose:

> 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 

Alcuni dei test di cui sopra sono senza senso, ma che è il mio punto: non importa quello che faccio, non riesco proprio a get prevedere() per guardare il mio dati e fare una previsione. Gli scalari non funzionano, i vettori non funzionano. Una matrice 2x2 non funziona, né una matrice 3x3.

Cosa sto facendo di sbagliato qui?

(Una volta ho capire cosa ksvm vuole, allora posso fare in modo che i miei dati di test in grado di conformarsi a tale formato in un modo sano/ragionevole/matematicamente suono.)

risposta

21

Se pensi a come la macchina vettoriale di supporto potrebbe "usare" la matrice del kernel, vedrai che non puoi farlo nel modo in cui stai provando (come hai visto :-)

In realtà ho faticato un po 'con questo quando ho usato kernlab + una matrice del kernel ... per coincidenza, era anche per i kernel di grafici!

In ogni caso, rendiamo conto che dal momento che SVM non sa come calcolare la funzione del kernel, è necessario che questi valori siano già stati calcolati tra i nuovi esempi (di prova) e gli esempi selezionati come vettori di supporto durante la fase di addestramento.

Quindi, è necessario calcolare la matrice di kernel per tutte dei tuoi esempi insieme. In seguito ti allenerai su alcuni e testerai gli altri rimuovendo righe + colonne dalla matrice del kernel quando appropriato. Lascia che ti mostri con il codice.

Possiamo utilizzare il codice di esempio nella documentazione ksvm per caricare il nostro spazio di lavoro con alcuni dati:

library(kernlab) 
example(ksvm) 

avrete bisogno di colpire tornare un paio di (2) volte al fine di lasciare le trame disegnare, e lascia che l'esempio finisca, ma ora dovresti avere una matrice del kernel nel tuo spazio di lavoro chiamato K. Abbiamo bisogno di recuperare il vettore y che dovrebbe utilizzare per le sue etichette (come è stato calpestato da altro codice nell'esempio):

y <- matrix(c(rep(1,60),rep(-1,60))) 

Ora, selezionare un sottoinsieme di esempi da utilizzare per i test

holdout <- sample(1:ncol(K), 10) 

da questo punto in poi, ho intenzione di:

  1. Creare una matrice di kernel di formazione chiamato trainK dalla matrice originale K kernel.
  2. Creare un modello SVM dalla mia formazione impostata trainK
  3. Utilizzare i vettori di supporto trovati dal modello per creare una matrice di kernel test testK ... questa è la parte strana. Se osservi il codice in kernlab per vedere come utilizza gli indici vettoriali di supporto, vedrai perché viene eseguito in questo modo. Potrebbe essere possibile farlo in un altro modo, ma non ho visto alcuna documentazione/esempi su che prevedano con una matrice del kernel, quindi lo sto facendo "nel modo più duro" qui.
  4. Utilizzare la SVM di prevedere su queste caratteristiche e segnalare la precisione

Ecco il codice:

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!) 

Questo dovrebbe solo di farlo. In bocca al lupo!

risposte a commentare qui sotto

cosa K [-holdout, -holdout] significa? (cosa significa "-" significa?)

Immaginate di avere un vettore x, e si desidera recuperare gli elementi 1, 3 e 5 da esso, faresti:

x.sub <- x[c(1,3,5)] 

Se si desidera recuperare tutto da xtranne elementi 1, 3, e 5, faresti:

x.sub <- x[-c(1,3,5)] 

Così K[-holdout,-holdout] riporta tutte le righe e colonne di Keccetto per le righe che vogliamo escludere.

Quali sono gli argomenti del tuo as.kernelMatrix - (? Che è particolarmente strano perché sembra che tutta la staffa è un indice di matrice K) in particolare la [, SVindex (m), rilasciare = F] argomento

Sì, ho inline due comandi in una sola:

testK <- as.kernelMatrix(K[holdout, -holdout][,SVindex(m), drop=F]) 

Ora che hai addestrato il modello, si vuole dare una nuova matrice kernel con i tuoi esempi di test. K[holdout,] fornirebbe solo le righe che corrispondono agli esempi di addestramento in K e tutte le colonne di K.

SVindex(m) ti dà gli indici delle tue vettori di supporto dal matrice formazione originale - ricorda, le righe/cols sono holdout rimossi. Pertanto, affinché gli indici delle colonne siano corretti (ad es. Si faccia riferimento alla colonna sv corretta), devo prima rimuovere le colonne holdout.

In ogni caso, forse questo è più chiaro:

testK <- K[holdout, -holdout] 
testK <- testK[,SVindex(m), drop=FALSE] 

Ora testK ha solo le righe dei nostri esempi di test e le colonne che corrispondono ai vettori di supporto. testK[1,1] avrà il valore della funzione del kernel calcolata tra il primo esempio di test e il primo vettore di supporto. testK[1,2] avrà il valore della funzione del kernel tra il 1 ° esempio di prova e il secondo vettore di supporto, ecc

Aggiornamento (2014/01/30) per rispondere commento da @wrahool

E 'stato un po' che ho 've giocato con questo, quindi i particolari di kernlab::ksvm sono un po' arrugginito, ma in linea di principio dovrebbe essere corretto :-) ... ecco qui:

qual è il punto di testK <- K[holdout, -holdout] - non si sono rimozione le colonne che corrispondono al set di test?

Sì. La risposta breve è che se si desidera utilizzare predict utilizzando una matrice del kernel, è necessario fornire una matrice della dimensione rows entro il support vectors. Per ogni riga della matrice (il nuovo esempio che si desidera predire su) i valori nelle colonne sono semplicemente il valore della matrice del kernel valutata tra quell'esempio e il vettore di supporto.

La chiamata a SVindex(m) restituisce l'indice dei vettori di supporto indicati nella dimensione dei dati di allenamento originali.

Quindi, per prima cosa, mi fornisce una matrice testK con le righe degli esempi che voglio prevedere, e le colonne provengono dagli stessi esempi (dimensione) su cui il modello è stato addestrato.

Ho ulteriormente suddiviso le colonne di testK per SVindex(m) solo per darmi le colonne che (ora) corrispondono ai miei vettori di supporto. Se non avessi effettuato la prima selezione [, -holdout], gli indici restituiti da SVindex(m) potrebbero non corrispondere agli esempi corretti (a meno che tutti gli N colonne della matrice non siano tutti gli N colonne della matrice).

Inoltre, cosa fa esattamente la caduta = condizione FALSE?

È un po 'di codifica difensiva per garantire che dopo l'esecuzione dell'operazione di indicizzazione, l'oggetto restituito sia dello stesso tipo dell'oggetto che è stato indicizzato.

In R, se si indice solo una dimensione di un oggetto 2D (o superiore (?)), Viene restituito un oggetto della dimensione inferiore. Non voglio passare un vettore numeric in predict perché vuole avere un matrix

Per esempio

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 

Lo stesso accadrà con data.frame s, ecc

+0

Ok, quindi ho eseguito il codice come scritto, e funziona! Ma ho un po 'di problemi a capire cosa fa. Potresti aiutarmi a capire: cosa significa K [-noldout, -holdout]? (cosa significa "-"?) Quali sono gli argomenti del tuo as.kernelMatrix - in particolare l'argomento [, SVindex (m), drop = F] (che è particolarmente strano perché sembra che l'intera parentesi sia un indice di matrice di K?) – poundifdef

+0

Dato che era lungo, ho risposto al tuo commento nel mio post originale - leggi la metà inferiore. Se hai altre domande, puoi sempre venire nella lista di aiuto per chiedere più domande. Infine, se la mia risposta risponde alla tua domanda, non dimenticare di contrassegnarla come tale ;-) –

+0

Amico. Ti piace tanto. Grazie! – poundifdef

2

Prima di tutto, ho non usato kernlab molto. Ma guardando semplicemente i documenti, vedo esempi di lavoro per il metodo predict.ksvm(). Copia e incolla, e omettendo le stampe di schermo:

## 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") 

Questo sembra abbastanza puritano: utilizzare campionamento casuale per generare un training set genetrain e il suo complemento genetest, poi il montaggio tramite ksvm e una chiamata a un metodo predict() utilizzando la vestibilità e nuovi dati in un formato corrispondente. Questo è molto standard.

È possibile trovare utile il pacchetto caret di Max Kuhn. Fornisce un quadro generale di valutazione e test per una varietà di regressione, classificazione e metodi di apprendimento automatico e pacchetti, tra cui kernlab e contiene diverse vignette più uno JSS paper.

+0

Destra - stavo leggendo predire troppo?. In questo esempio, si passa una funzione del kernel ("rbfdot") e i dati di addestramento ("genetrain") in ksvm().Nel mio caso, il mio input è un kernel matrixm quindi ksvm() non ha mai un parametro "data", quindi non c'è una chiara mappatura tra la struttura dei miei dati di allenamento e la struttura dei miei dati di test. – poundifdef

+1

Se sei curioso, sto cercando di implementare i kernel grafici in R - quindi piuttosto che classificare i dati vettoriali, sto guardando i dati del grafico. Quindi, la mia funzione del kernel esamina il numero di percorsi casuali che sono equivalenti tra due grafici per determinare la loro "distanza" – poundifdef

1

Steve Lianoglou è giusto .

In kernlab è un po 'cablato, e quando si preannuncia richiede la matrice del kernel di input tra ogni esempio di test e i vettori di supporto. Devi trovare questa matrice da solo.

Ad esempio, una matrice di test [n x m], dove n è il numero di campioni di prova e m è il numero di vettori di supporto nel modello appreso (ordinato nella sequenza di SVindex (modello)).

codice Esempio

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") 

kernel è la matrice kernel ingresso. trainidx e testidx sono id per l'addestramento e il test.

0

Costruisci le etichette dagli elementi della soluzione. Utilizzare questo metodo predictor alternativo che tenga modello ksvm (m) e dati in formato formazione originale (d)

predict.alt <- function(m, d){ 
    sign(d[, [email protected]] %*% [email protected][[1]] - [email protected]) 
} 

K è un kernelMatrix per la formazione. Per motivi di validità, se si esegue predict.alt sui dati di allenamento, si noterà che il metodo di predittore alternativo cambia i valori accanto ai valori corretti restituiti da ksvm. Il predittore nativo si comporta in modo inaspettato:

aux <- data.frame([email protected], 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 
Problemi correlati