Cálculo de la función de decisión de SVM manualmente.

Estoy tratando de calcular MANUALMENTE la decisión de la función de un clasificador SVC (en lugar de usar el método incorporado) usando la biblioteca de Python SKLearn.

Sin embargo, he intentado varios métodos, pero solo puedo obtener el cálculo manual para que coincida cuando no escala mis datos.

z es un dato de prueba (que se ha escalado) y creo que las otras variables hablan por sí mismas (también, estoy usando un kernel rbf si eso no es obvio en el código).

Aquí están los métodos que he probado:

1 Método de bucle:

 dec_func = 0 for j in range(np.shape(sup_vecs)[0]): norm2 = np.linalg.norm(sup_vecs[j, :] - z)**2 dec_func = dec_func + dual_coefs[0, j] * np.exp(-gamma*norm2) dec_func += intercept 

2 Método Vectorizado

 diff = sup_vecs - z norm2 = np.sum(np.sqrt(diff*diff), 1)**2 dec_func = dual_coefs.dot(np.exp(-gamma_params*norm2)) + intercept 

Sin embargo, ninguno de estos devuelve el mismo valor que decision_function . Creo que puede tener algo que ver con volver a escalar mis valores o, más probablemente, ¡es algo tonto que he estado observando!

Cualquier ayuda sería apreciada.

Así que después de un poco más de excavación y rascarse la cabeza, lo he descubierto.

Como mencioné anteriormente, z es un dato de prueba que se ha escalado. Para escalarlo tuve que extraer los .mean_ y .std_ del objeto preprocessing.StandardScaler () (luego de llamar a .fit () en mis datos de entrenamiento, por supuesto).

Entonces estaba usando este z escalado como una entrada para mis cálculos manuales y para la función incorporada. Sin embargo, la función incorporada era parte de una tubería que ya tenía a StandardScaler como su primer ‘tubo’ en la tubería y, como resultado, ¡ z estaba escalando dos veces! Por lo tanto, cuando eliminé la escala de mi canalización, el manual responde “coincide” con la respuesta de la función incorporada.

Por cierto, digo “emparejados” entre comillas, ya que siempre tuve que voltear el signo de mis cálculos manuales para coincidir con la versión incorporada. Actualmente no tengo idea de por qué este es el caso.

Para concluir, entendí mal cómo funcionaban las tuberías.

Para aquellos que estén interesados, aquí están las versiones finales de mis métodos manuales:

 diff = sup_vecs - z_scaled # Looping Method dec_func_loop = 0 for j in range(np.shape(sup_vecs)[0]): norm2 = np.linalg.norm(diff[j,:]) dec_func_loop = dec_func_loop + dual_coefs[j] * np.exp(-gamma*(norm2**2)) dec_func_loop = -1 * (dec_func_loop - intercept) # Vectorized method norm2 = np.array([np.linalg.norm(diff[n, :]) for n in range(np.shape(sup_vecs)[0])]) dec_func_vec = -1 * (dual_coefs.dot(np.exp(-gamma*(norm2**2))) - intercept) 

Apéndice

Para aquellos que estén interesados ​​en implementar un método manual para un SVC multiclase, el siguiente enlace es útil: https://stackoverflow.com/a/27752709/1182556