Python 如何使用自定义SVM内核?

Python 如何使用自定义SVM内核?,python,machine-learning,scikit-learn,svm,gaussian,Python,Machine Learning,Scikit Learn,Svm,Gaussian,我想用Python实现我自己的高斯内核,只是为了练习。我正在使用: sklearn.svm.SVC(kernel=my_kernel)但我真的不明白发生了什么 我希望调用函数my_kernel时使用X矩阵的列作为参数,而不是使用X,X作为参数。从这些例子来看,情况并不清楚 我错过了什么 这是我的代码: ''' Created on 15 Nov 2014 @author: Luigi ''' import scipy.io import numpy as np from sklearn imp

我想用Python实现我自己的高斯内核,只是为了练习。我正在使用:
sklearn.svm.SVC(kernel=my_kernel)
但我真的不明白发生了什么

我希望调用函数my_kernel时使用
X
矩阵的列作为参数,而不是使用
X
X
作为参数。从这些例子来看,情况并不清楚

我错过了什么

这是我的代码:

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

出于效率考虑,SVC假设您的内核是一个接受函数,
X
Y
(它将仅在培训期间使用两个相同的函数),您应该返回一个矩阵
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)

在阅读了上面的答案,以及其他一些问题和网站(,)之后,我把这些放在一起,作为一个高斯内核

使用
kernel=precomputed
调用
svm.SVC()

然后计算a.k.a.内核矩阵(通常缩写为k)

然后使用此Gram矩阵作为第一个参数(即X),以:

我从以下几点开始:

在中调用
sklearn.svm.SVC()
,然后调用
sklearn.svm.SVC().fit()

Gram矩阵计算-用作
sklearn.svm.SVC().fit()
的参数-在以下位置完成:

用于获取x1和x2()之间的径向基函数核:

然后,一旦使用此自定义内核对模型进行训练,我们将使用以下方法进行预测:

简而言之,要使用自定义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) )

对不起,我不明白,可能是因为我是ML的初学者。返回一个包含n=n_行(X)的方阵是不够的,元素是X[:,0]和X[:,1]之间的所有组合?正如我所说,它不会总是用两个X作为参数来调用,所以不。此外,您的数据是多维的,所以X[:,0]这只是每个向量的第一维,和这里无关。我应该返回什么?一个Gram矩阵,和答案中写的一模一样。矩阵,其中第i行和第j列由第一个数组的第i个向量和第二个数组的第j个向量之间的核值组成,所以核(X,Y){ij}=K(X_i,Y_j)@lejlot我的问题可能直接相关,因为我使用的是自计算核。你能看一下在这种情况下你的“Xval”是什么吗?这是运行预测的训练集吗?此外,由于“gaussianKernelGramMatrixFull”的输入必须是相同的尺寸,您是否必须手动调整X的大小以正确生成Gram?@VinitNayak not Twould-
Xval
s是我们希望获得其预测的值。我们在训练集
x
上使用已知的标签
y
,但我们不知道
Xval
的标签是什么,所以我们预测它们。@VinitNayak
x
Xval
不需要相同的大小。它们只需具有相同的列数(在
m
by
n
矩阵中的
n
),正如您预期的训练数据和预测的数据一样(即,它们不应具有相同数量的样本,但应具有相同数量的特征)。My
X
是一个622x9矩阵,
y
是622x1矩阵,
Xval
(这是我的交叉验证集)是266x9。当我运行上面的程序时,我在预测时得到以下错误:
svm/base.py”,第455行,在_-validate_中为_-predict(X.shape[1],self.shape_-fit[0])值错误:X.shape[1]=9应该等于622,即训练时的样本数
您的X中有622个样本和9个特征?在这种情况下,您也有266个测试数据点和9个特征。您可能只需要转置数组。您可以在numpy中作为
my_array.T
from sklearn import svm

if kernelFunction == "gaussian":
    clf = svm.SVC(C = C, kernel="precomputed")
    return clf.fit(gaussianKernelGramMatrix(X,X), y)
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
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) )
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) )