python - score - ¿Cómo usar un kernel SVM personalizado?
svm parameters (2)
Por razones de eficiencia, SVC supone que su kernel es una función que acepta dos matrices de muestras , X
e Y
(usará dos idénticas solo durante el entrenamiento) y debe devolver una matriz G
donde:
G_ij = K(X_i, Y_j)
y K
es su función de kernel de "nivel de punto".
Entonces, implemente un kernel gaussiano que funcione de una manera genérica o agregue una función de "proxy" como:
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
y úsalo como:
from functools import partial
correct_gaussian_kernel = partial(proxy_kernel, K=gaussian_kernel)
Me gustaría implementar mi propio kernel gaussiano en Python, solo para hacer ejercicio. Estoy usando: sklearn.svm.SVC(kernel=my_kernel)
pero realmente no entiendo lo que está pasando.
Espero que se llame a la función mi_kernel con las columnas de la matriz X
como parámetros, en lugar de eso la llamé con X
, X
como argumentos. Mirando los ejemplos, las cosas no son más claras.
¿Qué me estoy perdiendo?
Este es mi código:
''''''
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)
Después de leer la respuesta anterior, y algunas otras preguntas y sitios ( 1 , 2 , 3 , 4 , 5 ), puse esto para un núcleo gaussiano en svm.SVC()
.
Llame a svm.SVC()
con kernel=precomputed
.
Luego calcule una Matriz Gram, también conocida como Kernel Matrix (a menudo abreviada como K).
Luego use esta matriz de Gram como primer argumento ( es decir, X) para svm.SVC().fit()
:
Comienzo con el siguiente código :
C=0.1
model = svmTrain(X, y, C, "gaussian")
que llama a sklearn.svm.SVC()
en svmTrain()
, y luego a 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)
el cálculo de Gram Matrix - utilizado como parámetro para sklearn.svm.SVC().fit()
- se realiza en 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
que usa gaussianKernel()
para obtener un núcleo de función de base radial entre x1 y x2 ( una medida de similitud basada en una distribución gaussiana centrada en x1 con sigma = 0.1 ):
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
Luego, una vez que el modelo se entrena con este kernel personalizado, predecimos con "el núcleo [personalizado] entre los datos de prueba y los datos de entrenamiento" :
predictions = model.predict( gaussianKernelGramMatrix(Xval, X) )
En resumen, para usar un kernel gaussiano SVM personalizado, puede usar este fragmento:
import numpy as np
from sklearn import svm
def gaussianKernelGramMatrix(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( gaussianKernelGramMatrix(X,X), y )
p = model.predict( gaussianKernelGramMatrix(Xval, X) )