sklearn - svc python
Scikit Learn SVC decision_function y predicción (5)
Estoy intentando comprender la relación entre decision_function y predict, que son métodos de instancia de SVC ( http://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html ). Hasta ahora he deducido que la función de decisión devuelve puntuaciones por parejas entre las clases. Tenía la impresión de que el predictor elige la clase que maximiza su puntuación por parejas, pero probé esto y obtuve resultados diferentes. Aquí está el código que estaba usando para tratar de entender la relación entre los dos. Primero genere la matriz de puntaje por pares, y luego imprimí la clase que tiene puntaje máximo por parejas que era diferente de la clase predicha por clf.predict.
result = clf.decision_function(vector)[0]
counter = 0
num_classes = len(clf.classes_)
pairwise_scores = np.zeros((num_classes, num_classes))
for r in xrange(num_classes):
for j in xrange(r + 1, num_classes):
pairwise_scores[r][j] = result[counter]
pairwise_scores[j][r] = -result[counter]
counter += 1
index = np.argmax(pairwise_scores)
class = index_star / num_classes
print class
print clf.predict(vector)[0]
¿Alguien sabe la relación entre estos predecir y la función de decisión?
Cuando llame a decision_function()
, obtendrá el resultado de cada uno de los clasificadores pairwise (n * (n-1) / 2 números en total). Consulte las páginas 127 y 128 de "Máquinas de vectores de soporte para la clasificación de patrones" .
Cada clasificador realiza una votación sobre cuál es la respuesta correcta (en función del signo de la salida de ese clasificador); predict()
devuelve la clase con la mayor cantidad de votos.
Hay muy buenas preguntas y respuestas para el escenario de clase uno contra uno en datascience.sx:
Pregunta
Tengo un clasificador multiclass SVM con etiquetas ''A'', ''B'', ''C'', ''D''.
Este es el código que estoy ejecutando:
>>>print clf.predict([predict_this]) [''A''] >>>print clf.decision_function([predict_this]) [[ 185.23220833 43.62763596 180.83305074 -93.58628288 62.51448055 173.43335293]]
¿Cómo puedo utilizar el resultado de la función de decisión para predecir la clase (A / B / C / D) con la mayor probabilidad y, si es posible, su valor? He visitado https://.com/a/20114601/7760998 pero es para clasificadores binarios y no pude encontrar un buen recurso que explique el resultado de decision_function para clasificadores multiclase con shape ovo (uno contra uno).
Editar:
El ejemplo anterior es para la clase ''A''. Para otra entrada, el clasificador predijo ''C'' y dio el siguiente resultado en decision_function
[[ 96.42193513 -11.13296606 111.47424538 -88.5356536 44.29272494 141.0069203 ]]
Para otra entrada diferente que el clasificador predijo como ''C'' dio el siguiente resultado de decision_function,
[[ 290.54180354 -133.93467605 116.37068951 -392.32251314 -130.84421412 284.87653043]]
Si hubiera sido ovr (one-vs-rest), sería más fácil seleccionando el que tiene mayor valor, pero en ovo (uno-contra-uno) hay
(n * (n - 1)) / 2
valores en el lista resultante¿Cómo deducir qué clase se seleccionaría en función de la función de decisión?
Responder
Su enlace tiene recursos suficientes, así que veamos:
Cuando llame a decision_function (), obtendrá el resultado de cada uno de los clasificadores pairwise (n * (n-1) / 2 números en total). Consulte las páginas 127 y 128 de "Máquinas de vectores de soporte para la clasificación de patrones".
Haga clic en el enlace "página 127 y 128" (no se muestra aquí, sino en la respuesta ). Debería ver:
- La implementación de SVM de Python usa uno contra uno. Eso es exactamente de lo que habla el libro.
- Para cada comparación por parejas, medimos la función de decisión
- La función de decisión es el límite de decisión binario SVM regular
¿Qué tiene eso que ver con tu pregunta?
- clf.decision_function () le dará los $ D $ por cada comparación por pares
- La clase con más votos gana
Por ejemplo,
[[96.42193513 -11.13296606 111.47424538 -88.5356536 44.29272494 141.0069203]]
está comparando:
[AB, AC, AD, BC, BD, CD]
Etiquetamos cada uno de ellos por el signo. Obtenemos:
[A, C, A, C, B, C]
Por ejemplo, 96.42193513 es positivo y, por lo tanto, A es la etiqueta de AB.
Ahora tenemos tres C, C sería su predicción. Si repites mi procedimiento para los otros dos ejemplos, obtendrás la predicción de Python. ¡Intentalo!
No entiendo completamente tu código, pero vamos a través del ejemplo de la página de documentación a la que hiciste referencia:
import numpy as np
X = np.array([[-1, -1], [-2, -1], [1, 1], [2, 1]])
y = np.array([1, 1, 2, 2])
from sklearn.svm import SVC
clf = SVC()
clf.fit(X, y)
Ahora apliquemos la función de decisión y pronosticamos las muestras:
clf.decision_function(X)
clf.predict(X)
El resultado que obtenemos es:
array([[-1.00052254],
[-1.00006594],
[ 1.00029424],
[ 1.00029424]])
array([1, 1, 2, 2])
Y eso es fácil de interpretar: la función desion nos dice en qué lado del hiperplano está generado por el clasificador que somos (y qué tan lejos estamos de él). En base a esa información, el estimador luego etiqueta los ejemplos con la etiqueta correspondiente.
Para aquellos interesados, publicaré un ejemplo rápido de la función de predict
traducida de C ++ ( here ) a python:
# I''ve only implemented the linear and rbf kernels
def kernel(params, sv, X):
if params.kernel == ''linear'':
return [np.dot(vi, X) for vi in sv]
elif params.kernel == ''rbf'':
return [math.exp(-params.gamma * np.dot(vi - X, vi - X)) for vi in sv]
# This replicates clf.decision_function(X)
def decision_function(params, sv, nv, a, b, X):
# calculate the kernels
k = kernel(params, sv, X)
# define the start and end index for support vectors for each class
start = [sum(nv[:i]) for i in range(len(nv))]
end = [start[i] + nv[i] for i in range(len(nv))]
# calculate: sum(a_p * k(x_p, x)) between every 2 classes
c = [ sum(a[ i ][p] * k[p] for p in range(start[j], end[j])) +
sum(a[j-1][p] * k[p] for p in range(start[i], end[i]))
for i in range(len(nv)) for j in range(i+1,len(nv))]
# add the intercept
return [sum(x) for x in zip(c, b)]
# This replicates clf.predict(X)
def predict(params, sv, nv, a, b, cs, X):
'''''' params = model parameters
sv = support vectors
nv = # of support vectors per class
a = dual coefficients
b = intercepts
cs = list of class names
X = feature to predict
''''''
decision = decision_function(params, sv, nv, a, b, X)
votes = [(i if decision[p] > 0 else j) for p,(i,j) in enumerate((i,j)
for i in range(len(cs))
for j in range(i+1,len(cs)))]
return cs[max(set(votes), key=votes.count)]
Hay muchos argumentos de entrada para la función de predict
y decision_function
, pero tenga en cuenta que el modelo usa todos internamente cuando llama a predict(X)
. De hecho, todos los argumentos son accesibles para usted dentro del modelo después de la adaptación:
# Create model
clf = svm.SVC(gamma=0.001, C=100.)
# Fit model using features, X, and labels, Y.
clf.fit(X, y)
# Get parameters from model
params = clf.get_params()
sv = clf.support_vectors
nv = clf.n_support_
a = clf.dual_coef_
b = clf._intercept_
cs = clf.classes_
# Use the functions to predict
print(predict(params, sv, nv, a, b, cs, X))
# Compare with the builtin predict
print(clf.predict(X))
Probablemente tengan una relación matemática algo complicada. ¡Pero si utiliza la función decision_function
en el clasificador LinearSVC
, la relación entre esos dos será más clara! Debido a que decision_function
le dará puntajes para cada etiqueta de clase (no es lo mismo que SVC) y predecir dará la clase con la mejor puntuación.