7

kernlabR パッケージを使用してサポート ベクター マシン (SVM) を実行しようとしています。私の非常に単純な例では、2 つのトレーニング データがあります。AとB。

(A と B はタイプmatrixです。グラフの隣接行列です。)

そこで、A+B を取ってカーネル行列を生成する関数を書きました。

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

ここで、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 

ここまでは順調ですね。カスタム カーネル マトリックスを作成し、そのマトリックスを使用して 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

上記のテストのいくつかは無意味ですが、それが私の言いたいことです。私が何をしようとも、predict() を取得して自分のデータを見て予測を行うことはできません。スカラーは機能しません。ベクトルは機能しません。2x2 マトリックスも 3x3 マトリックスも機能しません。

ここで何が間違っていますか?

(ksvm が何を望んでいるのかを理解したら、テスト データがその形式に正気/合理的/数学的に適切な方法で準拠できることを確認できます。)

4

4 に答える 4

23

サポート ベクター マシンがカーネル マトリックスをどのように「使用」するかを考えると、あなたが試みている方法では実際にはこれを行うことができないことがわかります (これまで見てきたように :-)

私が最初に kernlab + カーネル マトリックスを使用したとき、実際にはこれに少し苦労しました...偶然にも、それはグラフ カーネル用でもありました!

とにかく、SVM はカーネル関数の計算方法を認識していないため、新しい (テスト) サンプルと、トレーニング ステップ中にサポート ベクターとして選択したサンプルの間で、これらの値を既に計算しておく必要があることを最初に認識しましょう。 .

したがって、すべての例のカーネル行列をまとめて計算する必要があります。後で、必要に応じてカーネル マトリックスから行と列を削除して、一部をトレーニングし、他のものをテストします。コードでお見せしましょう。

ドキュメントのサンプル コードを使用してksvm、ワークスペースにデータをロードできます。

library(kernlab)
example(ksvm)

プロットを描画し、例を終了させるために、リターンを数回押す必要がありますが、これで、ワークスペースに と呼ばれるカーネル マトリックスが作成されているはずKです。ラベルに使用するベクトルを復元する必要がありますy(この例では、他のコードによって踏みにじられているため)。

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

ここで、テストに使用する例のサブセットを選択します

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

この時点から、次のことを行います。

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

それはちょうどそれを行う必要があります。幸運を!

以下のコメントへの返信

K[-holdout,-holdout] とはどういう意味ですか? (「~」はどういう意味ですか?)

vectorxがあり、そこから要素 1、3、および 5 を取得したいとします。次のようにします。

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

要素 1、3、および 5x 以外からすべてを取得する場合は、次のようにします。

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

Soは、ホールドアウトしたい行を除くK[-holdout,-holdout]すべての行と列を返します。K

あなたの as.kernelMatrix の引数は何ですか - 特に [,SVindex(m),drop=F] 引数 (ブラケット全体が K のマトリックス インデックスのように見えるため、これは特に奇妙です?)

ええ、2 つのコマンドを 1 つにインライン化しました。

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

モデルのトレーニングが完了したので、テスト例を使用して新しいカーネル マトリックスを与えたいと考えています。K[holdout,]のトレーニング例に対応する行のみKと、 のすべての列が表示されKます。

SVindex(m)は、元のトレーニング マトリックスからのサポート ベクターのインデックスを提供します。これらの行/列はholdout削除されていることを思い出してください。したがって、これらの列インデックスを正しくする (つまり、正しい sv 列を参照する) には、最初にholdout列を削除する必要があります。

とにかく、おそらくこれはより明確です:

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

これで、テスト例testKの行とサポート ベクターに対応する列のみが表示されます。最初のテスト例と最初のサポート ベクターの間で計算されたカーネル関数の値が含まれます。最初のテスト例と 2 番目のサポート ベクターの間にカーネル関数の値が含まれます。testK[1,1]testK[1,2]

@wrahool からのコメントに回答する更新 (2014-01-30)

私がこれで遊んでからしばらく経っているので、詳細はkernlab::ksvm少しさびていますが、原則としてこれは正しいはずです:-) ...ここに行きます:

ポイントは何testK <- K[holdout, -holdout]ですか-テストセットに対応する列を削除していませんか?

はい。簡単に言うとpredict、カーネル行列を使用する場合は、次元が の行列を指定する必要がありrowsますsupport vectors。マトリックスの各行 (予測する新しい例) の列の値は、その例とサポート ベクターの間で評価されたカーネル マトリックスの値です。

の呼び出しは、元のトレーニング データSVindex(m)の次元で指定されたサポート ベクターのインデックスを返します。

したがって、最初に実行すると、予測したい例の行をtestK <- K[holdout, -holdout]含む行列が得られます。列は、モデルがトレーニングされたのと同じ例 (次元) からのものです。testK

testKさらにbyの列をサブセット化しSVindex(m)て、(現在) サポート ベクターに対応する列のみを提供します。最初の[, -holdout]選択を行わなかった場合、返されるインデックスはSVindex(m)正しい例に対応しない場合があります (すべてのテスト例が行列Nの最後の列でない限り)。N

また、drop = FALSE 条件は正確には何をしますか?

インデックス作成操作が実行された後、返されるオブジェクトがインデックス作成されたオブジェクトと同じ型であることを確認するための、少し防御的なコーディングです。

R では、2D (またはそれ以上 (?)) のオブジェクトの 1 つの次元のみにインデックスを付けると、より低い次元のオブジェクトが返されます。ベクトルが必要なので、numericベクトルを渡したくありませんpredictmatrix

例えば

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.frames などでも同じことが起こります。

于 2009-11-18T16:42:50.603 に答える
2

Steve Lianoglou は正しいです。

kernlab では少し配線されており、予測時には、各テスト例とサポート ベクターの間に入力カーネル マトリックスが必要です。このマトリックスを自分で見つける必要があります。

たとえば、テスト マトリックス [nxm] で、n はテスト サンプルの数、m は学習済みモデルのサポート ベクターの数です (SVindex(model) の順序で並べられます)。

サンプルコード

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 です。

于 2014-05-18T16:36:51.757 に答える
2

まず、私は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 によるcaretパッケージが役に立つかもしれません。kernlabを含む、さまざまな回帰、分類、機械学習の方法とパッケージの一般的な評価とテストのフレームワークを提供し、いくつかのビネットとJSS ペーパーが含まれています。

于 2009-11-18T03:17:18.320 に答える
0

ソリューションの要素から自分でラベルを作成します。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
于 2015-03-04T05:52:33.127 に答える