Scikit Aprende SVC decision_function y predice

Estoy tratando de entender 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 reunido que la función de decisión devuelve puntuaciones por pares entre clases. Tenía la impresión de que predecir elige la clase que maximiza su puntuación por pares, pero probé esto y obtuve diferentes resultados. Aquí está el código que estaba usando para tratar de entender la relación entre los dos. Primero, generé la matriz de puntuación por pares, y luego imprimí la clase que tiene la puntuación por pares máxima, que era diferente de la clase predicha por clf.predecir.

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 estas predicciones y la función de decisión?

No entiendo completamente su código, pero veamos el ejemplo de la página de documentación a la que hizo 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 predecamos a las muestras:

 clf.decision_function(X) clf.predict(X) 

La salida 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 de qué lado del hiperplano generado por el clasificador estamos (y qué tan lejos estamos de él). Basándose en esa información, el estimador luego etiqueta los ejemplos con la etiqueta correspondiente.

Cuando llama a decision_function() , obtiene la salida de cada uno de los clasificadores por pares (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 pone en votación cuál es la respuesta correcta (según el signo de la salida de ese clasificador); predict() devuelve la clase con más votos.

Para aquellos interesados, publicaré un ejemplo rápido de la función de predict traducida desde C ++ ( aquí ) 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 predict y decision_function , pero tenga en cuenta que todos estos son utilizados internamente por el modelo cuando se llama 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)) 

Hay una muy buena sesión de preguntas y respuestas para el escenario de clases múltiples uno-uno-uno en datascience.sx:

Pregunta

Tengo un clasificador SVM multiclase con las tags ‘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 usar la salida 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://stackoverflow.com/a/20114601/7760998 pero es para clasificadores binarios y no pude encontrar un buen recurso que explique la salida de decision_function para clasificadores multiclase con forma ovo (uno-uno-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 un valor más alto, pero en ovo (one-vs-one) hay (n * (n - 1)) / 2 valores en el lista resultante

¿Cómo deducir qué clase se seleccionaría según la función de decisión?

Responder

Su enlace tiene suficientes recursos, así que veamos:

Cuando llama a decision_function (), obtiene la salida de cada uno de los clasificadores por pares (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í, pero en la respuesta de Stackoverflow). Debería ver:

introduzca la descripción de la imagen aquí

  • La implementación SVM de Python utiliza uno contra uno. De eso es exactamente de lo que habla el libro.
  • Para cada comparación por pares, medimos la función de decisión
  • La función de decisión es simplemente el límite de decisión SVM binario regular

¿Qué tiene que ver eso con tu pregunta?

  • clf.decision_function () le dará $ D $ para 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]

Las etiquetamos por el signo. Obtenemos:

[A, C, A, C, B, C]

Por ejemplo, 96.42193513 es positivo y, por lo tanto, A es la etiqueta para AB.

Ahora tenemos tres C, C sería tu predicción. Si repites mi procedimiento para los otros dos ejemplos, obtendrás la predicción de Python. ¡Intentalo!

Probablemente tienen una relación matemática un poco complicada. Pero si usa la función de decision_function en el clasificador LinearSVC , ¡la relación entre esos dos será más clara! Porque luego decision_function le dará puntajes para cada etiqueta de clase (no igual que SVC) y predecirá le dará a la clase la mejor puntuación.