web-dev-qa-db-ja.com

カスタムSVMカーネルを使用する方法は?

演習のために、Pythonで独自のGaussianカーネルを実装したいと思います。私は使用しています:sklearn.svm.SVC(kernel=my_kernel)ですが、何が起こっているのか本当にわかりません。

関数my_kernelは、X行列の列をパラメーターとして呼び出されることを期待していますが、代わりにXXを引数として呼び出されました。例を見ると、物事は明確ではありません。

何が足りないのですか?

これは私のコードです:

'''
Created on 15 Nov 2014

@author: Luigi
'''
import scipy.io
import numpy as np
from sklearn import svm
import matplotlib.pyplot as plt

def svm_class(fileName):

    data = scipy.io.loadmat(fileName)
    X = data['X']
    y = data['y']

    f = svm.SVC(kernel = 'rbf', gamma=50, C=1.0)
    f.fit(X,y.flatten())
    plotData(np.hstack((X,y)), X, f)

    return

def plotData(arr, X, f):

    ax = plt.subplot(111)

    ax.scatter(arr[arr[:,2]==0][:,0], arr[arr[:,2]==0][:,1], c='r', marker='o', label='Zero')
    ax.scatter(arr[arr[:,2]==1][:,0], arr[arr[:,2]==1][:,1], c='g', marker='+', label='One')

    h = .02  # step size in the mesh
    # create a mesh to plot in
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))


    # Plot the decision boundary. For that, we will assign a color to each
    # point in the mesh [x_min, m_max]x[y_min, y_max].
    Z = f.predict(np.c_[xx.ravel(), yy.ravel()])

    # Put the result into a color plot
    Z = Z.reshape(xx.shape)
    plt.contour(xx, yy, Z)



    plt.xlim(np.min(arr[:,0]), np.max(arr[:,0]))
    plt.ylim(np.min(arr[:,1]), np.max(arr[:,1]))
    plt.show()
    return


def gaussian_kernel(x1,x2):
    sigma = 0.5
    return np.exp(-np.sum((x1-x2)**2)/(2*sigma**2))

if __name__ == '__main__':

    fileName = 'ex6data2.mat'
    svm_class(fileName)
15
Luigi Tiburzi

上記の回答、およびその他のいくつかの質問とサイトを読んだ後( 12 、、 4 、- 5 )、これをガウスカーネル用にまとめました svm.SVC()

_kernel=precomputed_を使用してsvm.SVC()を呼び出します。

次に、 グラム行列 a.k.a.カーネル行列(多くの場合、Kと省略されます)を計算します。

次に、このグラム行列を最初の引数(、つまりX)として svm.SVC().fit() に使用します。

次のコード から始めます:

_C=0.1
model = svmTrain(X, y, C, "gaussian")
_

sklearn.svm.SVC()svmTrain()を呼び出し、次にsklearn.svm.SVC().fit()

_from sklearn import svm

if kernelFunction == "gaussian":
    clf = svm.SVC(C = C, kernel="precomputed")
    return clf.fit(gaussianKernelGramMatrix(X,X), y)
_

グラム行列の計算-sklearn.svm.SVC().fit()のパラメーターとして使用-は gaussianKernelGramMatrix() で行われます:

_import numpy as np

def gaussianKernelGramMatrix(X1, X2, K_function=gaussianKernel):
    """(Pre)calculates Gram Matrix K"""

    gram_matrix = np.zeros((X1.shape[0], X2.shape[0]))
    for i, x1 in enumerate(X1):
        for j, x2 in enumerate(X2):
            gram_matrix[i, j] = K_function(x1, x2)
    return gram_matrix
_

gaussianKernel() を使用して、x1とx2の間の動径基底関数カーネルを取得します( sigma = 0.1のx1を中心とするガウス分布に基づく類似性の尺度 =):

_def gaussianKernel(x1, x2, sigma=0.1):

    # Ensure that x1 and x2 are column vectors
    x1 = x1.flatten()
    x2 = x2.flatten()

    sim = np.exp(- np.sum( np.power((x1 - x2),2) ) / float( 2*(sigma**2) ) )

    return sim
_

次に、モデルがこのカスタムカーネルでトレーニングされると、 "テストデータとトレーニングデータの間の[カスタム]カーネル" で予測します。

_predictions = model.predict( gaussianKernelGramMatrix(Xval, X) )
_

つまり、カスタムSVMガウスカーネルを使用するには、次のスニペットを使用できます。

_import numpy as np
from sklearn import svm

def gaussianKernelGramMatrixFull(X1, X2, sigma=0.1):
    """(Pre)calculates Gram Matrix K"""

    gram_matrix = np.zeros((X1.shape[0], X2.shape[0]))
    for i, x1 in enumerate(X1):
        for j, x2 in enumerate(X2):
            x1 = x1.flatten()
            x2 = x2.flatten()
            gram_matrix[i, j] = np.exp(- np.sum( np.power((x1 - x2),2) ) / float( 2*(sigma**2) ) )
    return gram_matrix

X=...
y=...
Xval=...

C=0.1
clf = svm.SVC(C = C, kernel="precomputed")
model = clf.fit( gaussianKernelGramMatrixFull(X,X), y )

p = model.predict( gaussianKernelGramMatrixFull(Xval, X) )
_
18
arturomp

効率上の理由から、SVCは、カーネルが 2つのサンプル行列Xおよびを受け入れる関数であると想定しています。 Y(トレーニング中にのみ2つの同一のものを使用します)そして行列Gを返す必要があります。ここで:

G_ij = K(X_i, Y_j)

Kは、「ポイントレベル」のカーネル関数です。

したがって、このような一般的な方法で機能するガウスカーネルを実装するか、次のような「プロキシ」関数を追加します。

def proxy_kernel(X,Y,K):
    gram_matrix = np.zeros((X.shape[0], Y.shape[0]))
    for i, x in enumerate(X):
        for j, y in enumerate(Y):
            gram_matrix[i, j] = K(x, y)
    return gram_matrix

そしてそれを次のように使用します:

from functools import partial
correct_gaussian_kernel = partial(proxy_kernel, K=gaussian_kernel)
6
lejlot