6.8. Métricas por pares, afinidades y núcleos

El submódulo sklearn.metrics.pairwise implementa utilidades para evaluar las distancias por pares o la afinidad de conjuntos de muestras.

Este módulo contiene métricas de distancia y núcleos. Aquí se presenta un breve resumen de ambos.

Las métricas de distancia son funciones d(a, b) tales que d(a, b) < d(a, c) si los objetos a y b se consideran «más similares» que los objetos a y c. Dos objetos exactamente iguales tendrían una distancia de cero. Uno de los ejemplos más populares es la distancia Euclidiana. Para ser una «verdadera» métrica, debe obedecer las siguientes cuatro condiciones:

1. d(a, b) >= 0, for all a and b
2. d(a, b) == 0, if and only if a = b, positive definiteness
3. d(a, b) == d(b, a), symmetry
4. d(a, c) <= d(a, b) + d(b, c), the triangle inequality

Los núcleos son medidas de similitud, es decir, s(a, b) > s(a, c) si los objetos a y b son considerados «más similares» que los objetos a y c. Un núcleo también debe ser semi-definido positivo.

Hay varias formas de convertir entre una métrica de distancia y una medida de similitud, como un núcleo. Sea D la distancia y S el núcleo:

  1. S = np.exp(-D * gamma), donde una heurística para elegir gamma es 1 / num_features

  2. S = 1. / (D / np.max(D))

Las distancias entre los vectores fila de X y los vectores fila de Y pueden evaluarse utilizando pairwise_distances. Si se omite Y se calculan las distancias por pares de los vectores fila de X. Del mismo modo, pairwise.pairwise_kernels puede utilizarse para calcular el núcleo entre X y Y utilizando diferentes funciones de núcleo. Consulte la referencia de la API para obtener más detalles.

>>> import numpy as np
>>> from sklearn.metrics import pairwise_distances
>>> from sklearn.metrics.pairwise import pairwise_kernels
>>> X = np.array([[2, 3], [3, 5], [5, 8]])
>>> Y = np.array([[1, 0], [2, 1]])
>>> pairwise_distances(X, Y, metric='manhattan')
array([[ 4.,  2.],
       [ 7.,  5.],
       [12., 10.]])
>>> pairwise_distances(X, metric='manhattan')
array([[0., 3., 8.],
       [3., 0., 5.],
       [8., 5., 0.]])
>>> pairwise_kernels(X, Y, metric='linear')
array([[ 2.,  7.],
       [ 3., 11.],
       [ 5., 18.]])

6.8.1. Similitud del coseno

cosine_similarity calcula el producto punto normalizado L2 de los vectores. Es decir, si \(x\) y \(y\) son vectores de fila, su similitud coseno \(k\) se define como:

\[k(x, y) = \frac{x y^\top}{\|x\| \|y\|}\]

Esto se llama similitud del coseno, porque la normalización euclidiana (L2) proyecta los vectores sobre la esfera unitaria, y su producto de puntos es entonces el coseno del ángulo entre los puntos denotados por los vectores.

Este núcleo es una opción popular para calcular la similitud de documentos representados como vectores tf-idf. cosine_similarity acepta matrices scipy.sparse. (Ten en cuenta que la funcionalidad tf-idf en sklearn.feature_extraction.text puede producir vectores normalizados, en cuyo caso cosine_similarity es equivalente a linear_kernel, sólo que más lento.)

Referencias:

6.8.2. Núcleo lineal

La función linear_kernel calcula el núcleo lineal, es decir, un caso especial de polynomial_kernel con degree=1 y coef0=0 (homogéneo). Si x y y son vectores columna, su núcleo lineal es:

\[k(x, y) = x^\top y\]

6.8.3. Núcleo polinomial

La función polynomial_kernel calcula el kernel polinomial de grado-d entre dos vectores. El kernel polinomial representa la similitud entre dos vectores. Conceptualmente, el kernel polinomial considera no sólo la similitud entre vectores bajo la misma dimensión, sino también entre dimensiones. Cuando se utiliza en algoritmos de aprendizaje automático, esto permite tener en cuenta la interacción de las características.

El núcleo polinomial se define como:

\[k(x, y) = (\gamma x^\top y +c_0)^d\]

donde:

  • x, y son los vectores de entrada

  • d es el grado del núcleo

Si \(c_0 = 0\) se dice que el núcleo es homogéneo.

6.8.4. Núcleo sigmoidal

La función sigmoid_kernel calcula el núcleo sigmoidal entre dos vectores. El núcleo sigmoidal también se conoce como tangente hiperbólica, o Perceptrón Multicapa (porque, en el campo de las redes neuronales, se utiliza a menudo como función de activación de las neuronas). Se define como:

\[k(x, y) = \tanh( \gamma x^\top y + c_0)\]

donde:

  • x, y son los vectores de entrada

  • \(\gamma\) es conocido como pendiente

  • \(c_0\) es conocido como intersección

6.8.5. Núcleo RBF

La función rbf_kernel calcula el núcleo de la función de base radial (RBF) entre dos vectores. Este núcleo se define como:

\[k(x, y) = \exp( -\gamma \| x-y \|^2)\]

donde x y y son los vectores de entrada. Si \(\gamma = \sigma^{-2}\) el núcleo es conocido como el núcleo Gaussiano de varianza \(\sigma^2\).

6.8.6. Núcleo Laplaciano

La función laplacian_kernel es una variante en el núcleo de la función radial definida como:

\[k(x, y) = \exp( -\gamma \| x-y \|_1)\]

donde x y y son los vectores de entrada y \(\|x-y\|_1\) es la distancia de Manhattan entre los vectores de entrada.

Se ha demostrado su utilidad en el aprendizaje automático aplicado a datos sin ruido. Ver, por ejemplo, Machine learning for quantum mechanics in a nutshell.

6.8.7. Núcleo chi-cuadrado

El núcleo chi-cuadrado es una opción muy popular para entrenar SVMs no lineales en aplicaciones de visión por computadora. Se puede calcular utilizando chi2_kernel y luego pasar a una SVC con kernel="precomputed":

>>> from sklearn.svm import SVC
>>> from sklearn.metrics.pairwise import chi2_kernel
>>> X = [[0, 1], [1, 0], [.2, .8], [.7, .3]]
>>> y = [0, 1, 0, 1]
>>> K = chi2_kernel(X, gamma=.5)
>>> K
array([[1.        , 0.36787944, 0.89483932, 0.58364548],
       [0.36787944, 1.        , 0.51341712, 0.83822343],
       [0.89483932, 0.51341712, 1.        , 0.7768366 ],
       [0.58364548, 0.83822343, 0.7768366 , 1.        ]])

>>> svm = SVC(kernel='precomputed').fit(K, y)
>>> svm.predict(K)
array([0, 1, 0, 1])

También puede ser utilizado directamente como el argumento núcleo:

>>> svm = SVC(kernel=chi2_kernel).fit(X, y)
>>> svm.predict(X)
array([0, 1, 0, 1])

El núcleo chi cuadrado es dado por

\[k(x, y) = \exp \left (-\gamma \sum_i \frac{(x[i] - y[i]) ^ 2}{x[i] + y[i]} \right )\]

Se supone que los datos son no negativos, y a menudo se normalizan para que tengan una norma L1 de uno. La normalización se racionaliza con la conexión a la distancia chi cuadrada, que es una distancia entre distribuciones de probabilidad discretas.

El núcleo chi cuadrado es el más utilizado en los histogramas (bolsas) de palabras visuales.

Referencias: