Saltar al contenido

Archivos de categoría Clasificación

Máquinas de soporte de vectores en Python

Vamos a utilizar Máquinas de Soporte de Vectores (SVM) (Support Vector Machines) para construir y entrenar un modelo utilizando registros de células humanas para luego clasificarlas en benignas o malignas. SVM trabaja enlazando datos con una dimensión espacial de tal forma que los puntos de datos sean categorizados, inclusive cuando los datos no son linealmente separables. Primero se encuentra un separador entre categorías, luego los datos se transorman para que el separador pueda dibujarse como un hiperplano y finalmente se utilizan los valores de nuevos datos para predecir el grupo al cual deberían pertenecer.

Primero, importemos las librerías necesarias:

import pandas as pd
import pylab as pl
import numpy as np
import scipy.optimize as opt
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
%matplotlib inline 
import matplotlib.pyplot as plt

Cargar datos de Cancer

El ejemplo se basa en un conjunto de datos que están disponibles al público en el Repositorio de Machine Learning de la UCI (Asuncion y Newman, 2007)[http://mlearn.ics.uci.edu/MLRepository.html]. El conjunto de datos consiste de varios registros de células humanas, cada una, conteniendo los valores de un conjunto de características de células. Los campos en cada registro son:

Field name Description
ID Clump thickness
Clump Clump thickness
UnifSize Uniformity of cell size
UnifShape Uniformity of cell shape
MargAdh Marginal adhesion
SingEpiSize Single epithelial cell size
BareNuc Bare nuclei
BlandChrom Bland chromatin
NormNucl Normal nucleoli
Mit Mitoses
Class Benign or malignant
!wget -O cell_samples.csv https://s3-api.us-geo.objectstorage.softlayer.net/cf-courses-data/CognitiveClass/ML0101ENv3/labs/cell_samples.csv
--2020-02-13 16:52:45--  https://s3-api.us-geo.objectstorage.softlayer.net/cf-courses-data/CognitiveClass/ML0101ENv3/labs/cell_samples.csv
Resolving s3-api.us-geo.objectstorage.softlayer.net (s3-api.us-geo.objectstorage.softlayer.net)... 67.228.254.196
Connecting to s3-api.us-geo.objectstorage.softlayer.net (s3-api.us-geo.objectstorage.softlayer.net)|67.228.254.196|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 20675 (20K)

Saving to: ‘cell_samples.csv’

cell_samples.csv 100%[===================>] 20.19K –.-KB/s in 0.02s

2020-02-13 16:52:45 (986 KB/s) – ‘cell_samples.csv’ saved [20675/20675]

Cargar los Datos a partir de un archivo CSV

cell_df = pd.read_csv("cell_samples.csv")
cell_df.head()
ID Clump UnifSize UnifShape MargAdh SingEpiSize BareNuc BlandChrom NormNucl Mit Class
0 1000025 5 1 1 1 2 1 3 1 1 2
1 1002945 5 4 4 5 7 10 3 2 1 2
2 1015425 3 1 1 1 2 2 3 1 1 2
3 1016277 6 8 8 1 3 4 3 7 1 2
4 1017023 4 1 1 3 2 1 3 1 1 2

El archivo ID contiene los identificadores del paciente. Las características de las muestras de las células de cada paciente están contenidas en los campos Clump to Mit. Los valores van del 1 al 10, siendo 1 el más cerca a benigno. El campo Class contiene el diagnóstico, como se confirmó por procedimientos médicos separados, si son las muestras benignas o no (valor = 2) o maligno (valor = 4). Miremos a la distribución de las clases basadas en el grosor y uniformidad del tamaña de la célula:

ax = cell_df[cell_df['Class'] == 4][0:50].plot(kind='scatter', x='Clump', y='UnifSize', color='DarkBlue', label='malignant');
cell_df[cell_df['Class'] == 2][0:50].plot(kind='scatter', x='Clump', y='UnifSize', color='Yellow', label='benign', ax=ax);
plt.show()

Preprocesamiento de Datos y selección

Miremos primero al tipo de dato de las columnas:

cell_df.dtypes
ID              int64
Clump           int64
UnifSize        int64
UnifShape       int64
MargAdh         int64
SingEpiSize     int64
BareNuc        object
BlandChrom      int64
NormNucl        int64
Mit             int64
Class           int64
dtype: object

Parece que la columna BareNuc incluye algunos valores que no son numéricos. Podemos eliminar esas filas:

cell_df = cell_df[pd.to_numeric(cell_df['BareNuc'], errors='coerce').notnull()]
cell_df['BareNuc'] = cell_df['BareNuc'].astype('int')
cell_df.dtypes
ID             int64
Clump          int64
UnifSize       int64
UnifShape      int64
MargAdh        int64
SingEpiSize    int64
BareNuc        int64
BlandChrom     int64
NormNucl       int64
Mit            int64
Class          int64
dtype: object
feature_df = cell_df[['Clump', 'UnifSize', 'UnifShape', 'MargAdh', 'SingEpiSize', 'BareNuc', 'BlandChrom', 'NormNucl', 'Mit']]
X = np.asarray(feature_df)
X[0:5]
array([[ 5,  1,  1,  1,  2,  1,  3,  1,  1],
       [ 5,  4,  4,  5,  7, 10,  3,  2,  1],
       [ 3,  1,  1,  1,  2,  2,  3,  1,  1],
       [ 6,  8,  8,  1,  3,  4,  3,  7,  1],
       [ 4,  1,  1,  3,  2,  1,  3,  1,  1]])

Queremos que el modelo prediga el valor de la columna Class (si es benigno (=2), si es maligno (=4)). Como este campo puede tener uno de dos valores posibles, necesitaremos cambiar su nivel de medición para reflejar eso.

cell_df['Class'] = cell_df['Class'].astype('int')
y = np.asarray(cell_df['Class'])
y [0:5]
array([2, 2, 2, 2, 2])

Train/Test dataset

Ahora, dividimos el set de datos en entrenamiento y prueba:

X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=4)
print ('Train set:', X_train.shape,  y_train.shape)
print ('Test set:', X_test.shape,  y_test.shape)
Train set: (546, 9) (546,)
Test set: (137, 9) (137,)

Modelado (SVM con aprendizaje Scikit)

El algoritmo SVM ofrece elegir funciones para realizar su procesamiento. Básicamente, mapear los datos en un espacio dimensional más alto se llama kernelling. La función matemática utilizada para la transformación se conoce como la función kernel, y puede ser de distintos tipos, a ser:

  1. Lineal
  2. Polimonial
  3. Función de base Radial (RBF)
  4. Sigmoide

Cada una de estas funciones tiene sus características, pros y contras y su ecuación, pero como no hay una forma sencilla de saber la función que mejor funcionaría, elegimos utilizar diferentes funciones y comparar los resultados. Utilicemos la función por omisión, RBF (Función Basada en Radio) para este lab.

from sklearn import svm
clf = svm.SVC(kernel='rbf')
clf.fit(X_train, y_train) 
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma='auto_deprecated',
  kernel='rbf', max_iter=-1, probability=False, random_state=None,
  shrinking=True, tol=0.001, verbose=False)

Luego que el modelo cuadró, se puede utilizar para predecir nuevos valores:

yhat = clf.predict(X_test)
yhat [0:5]
array([2, 4, 2, 4, 2])

Evaluación

from sklearn.metrics import classification_report, confusion_matrix
import itertools
def plot_confusion_matrix(cm, classes, normalize=False, title='Confusion matrix', cmap=plt.cm.Blues):
    """
    Esta función imprime y marca la matriz de confusión.
    Se puede aplicar Normalización seteando la variable `normalize=True`.
    """
    if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
        print("Normalized confusion matrix")
    else:
        print('Matriz de confusión, sin normalización')

    print(cm)

    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45)
    plt.yticks(tick_marks, classes)

    fmt = '.2f' if normalize else 'd'
    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, format(cm[i, j], fmt),
                 horizontalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('Etiqueta True')
    plt.xlabel('Etiqueta predecida')
# Computar la matriz de confusión
cnf_matrix = confusion_matrix(y_test, yhat, labels=[2,4])
np.set_printoptions(precision=2)

print (classification_report(y_test, yhat))

# Plot non-normalized confusion matrix
plt.figure()
plot_confusion_matrix(cnf_matrix, classes=['Benign(2)','Malignant(4)'],normalize= False,  title='Matriz de confusión')
              precision    recall  f1-score   support

           2       1.00      0.94      0.97        90
           4       0.90      1.00      0.95        47

   micro avg       0.96      0.96      0.96       137
   macro avg       0.95      0.97      0.96       137
weighted avg       0.97      0.96      0.96       137

Matriz de confusión, sin normalización
[[85  5]
 [ 0 47]]


Se puede utilizar facilmente el f1_score de la librería sklearn:

from sklearn.metrics import f1_score
f1_score(y_test, yhat, average='weighted')
0.9639038982104676

Intentemos el índice jaccard para dar precisión:

from sklearn.metrics import jaccard_similarity_score
jaccard_similarity_score(y_test, yhat)
0.9635036496350365

Utilizando otro ajuste

Se puede reconstruir de nuevo el modelo, pero esta vez con un kernel linear. Por supuesto, la exactitud cambia con la nueva función kernel.

clf2 = svm.SVC(kernel='linear')
clf2.fit(X_train, y_train) 
yhat2 = clf2.predict(X_test)
print("Avg F1-score: %.4f" % f1_score(y_test, yhat2, average='weighted'))
print("Jaccard score: %.4f" % jaccard_similarity_score(y_test, yhat2))
Avg F1-score: 0.9639
Jaccard score: 0.9635
0 Seguir leyendo →

Máquinas de soporte de vectores

Máquinas de soporte de vectores

Las máquinas de soporte de vectores (SVM – Support Vector Machine) es un algoritmo supervisado que puede clasificar los casos mediante la búsqueda de un separador. SVM trabaja primero correlacionando datos con un espacio de características de alta dimensión para que los puntos de datos puedan ser categorizados, incluso cuando los datos no son de otro modo separables linealmente. A continuación, se estima un separador para los datos. Los datos deben ser transformados de tal manera que un separador pueda ser dibujado como un hiperplano.
datos linealmente no separablesLa siguiente figura muestra la distribución de un conjunto pequeño de células en función del tamaño de la unidad y del grosor de la agrupación. Puede verse que los puntos de datos caen bajo dos categorías diferentes. Representa un conjunto de datos lineal y no separable. Las dos categorías se pueden separar con una curva, pero no con una línea. Es decir, representa un conjunto de datos linealmente no separable, que es el caso para la mayoría del conjunto de datos del mundo real.
Pero podemos transferir estos datos a un espacio dimensional más alto, cómo por ejemplo a un espacio 3-dimensional. Después de la transformación, el límite entre las dos categorías se puede definir por un hiperplano. Como estamos ahora en un espacio tridimensional, el separador se muestra como un plano. Este plano se puede utilizar para clasificar casos nuevos o desconocidos. Por lo tanto, el algoritmo SVM tiene como resultado a un hiperplano óptimo que categoriza nuevos ejemplos.
datos linealmente separables

Transformación de los datos

Por simplificar vamos a imaginar que nuestro conjunto de datos esta conformado por datos uni-dimensionales, por lo que sólo tenemos una característica x y que no son linealmente separables. Podemos transferirlo a un espacio bidimensional, por ejemplo aumentando la dimensión de los datos correlacionando x en un nuevo espacio utilizando una función, con salidas x y x-cuadrado. Ahora, los datos son linealmente separables. Hay que tener en cuenta que estamos en un espacio bidimensional, por lo que el hiperplano es una línea que divide a un plano en dos partes donde cada clase se coloca en cada lado. Ahora podemos utilizar esta línea para clasificar los nuevos casos.
transformación de datos
Básicamente, la correlación de datos en un espacio dimensional más alto se denomina kernelling. La función matemática utilizada para la transformación es conocida como la función kernel, y puede ser de diferentes tipos, como por ejemplo: Lineal, Polinomal, funcion Radial (o RBF) o Sigmoid. Cada una de estas funciones tiene sus propias características, sus pros y sus contras, y su ecuación, pero la buena noticia es que no necesitas conocerlos, ya que la mayoría de ellos ya están implementada en bibliotecas de lenguajes de programación de ciencia de datos. Además, como no es una forma fácil de saber qué función funciona mejor con cualquier conjunto de datos determinado, por lo general, elegimos diferentes funciones y comparamos los resultados. Puedes ver un ejemplo en este artículo: Máquinas de soporte de vectores en Python

Cómo encontrar el mejor separador de hiperplano después de la transformación

Búsqueda del mejor separadorLas SVM se basan en la idea de encontrar un hiperplano que mejor divide un conjunto de datos en dos clases. Como estamos en un espacio bidimensional, se puede pensar en el hiperplano como una línea que linealmente separa unos puntos de los otros. Una elección razonable como el mejor hiperplano es la que representa la mayor separación, o margen, entre las dos clases. Por lo tanto, el objetivo es elegir un hiperplano con un margen tan grande como sea posible. Los ejemplos más cercanos al hiperplano son los vectores de soporte. Es intuitivo que sólo los vectores de apoyo importan para lograr nuestro objetivo y, por lo tanto, otros ejemplos de entrenamiento pueden ser ignorados. Tratamos de encontrar el hiperplano de tal manera que tenga la distancia máxima con respecto a los vectores de soporte. Hay que tener en cuenta que las líneas de decisión de hiperplano y límite tienen sus propias ecuaciones. Por lo tanto, encontrar el hiperplano optimizado se puede formalizar utilizando una ecuación que involucra un poco más de matemáticas. Dicho esto, el hiperplano se aprende de los datos de entrenamiento usando un procedimiento de optimización que maximiza el margen y al igual que muchos otros problemas,e ste problema de optimización también puede ser resuelto por el descenso de gradiente.
Por lo tanto, la salida del algoritmo es los valores ‘w’ y ‘b’ para la línea. Puede realizar clasificaciones utilizando esta línea estimada. Es suficiente aplicar los valores de entrada en la ecuación de la línea, entonces, se puede calcular si un punto desconocido está por encima o por debajo de la línea. Si la ecuación devuelve un valor mayor que 0, entonces el punto pertenece a la primera clase, que está por encima de la línea, y viceversa.

Las dos principales ventajas de las máquinas de vectores de soporte son que son exactas en espacios dimensionales altos y utilizan un subconjunto de puntos de entrenamiento en la función de decisión (llamados vectores de soporte), así que también es eficiente en el manejo de la memoria. Las desventajas de las máquinas de vectores de soporte incluyen el hecho de que el algoritmo es propenso para el exceso de ajuste, si el número de características es mucho mayor que el número de muestras. Además, las SVM no proporcionan directamente estimaciones de probabilidad, que son deseables en la mayoría de problemas de clasificación. Y, por último, las SVM no son muy eficientes computacionalmente, si su conjunto de datos es muy grande, como cuando tiene más de mil filas.

Situaciones donde utilizar máquinas de soporte de vectores

SVM es bueno para las tareas de análisis de imagen, como la clasificación de imagen de reconocimiento de dígitos escritos a mano. Además, SVM es muy eficaz en tareas de minería de textos, particularmente debido a su efectividad en el tratamiento de datos de alta dimensión. Por ejemplo, se utiliza para detectar spam, asignación de categorías de texto y análisis de sentimientos. Otra aplicación de SVM se encuentra en la clasificación de datos de Expresión de Gene, de nuevo, debido a su potencia en la clasificación de datos de alta dimensión. SVM también se puede utilizar para otros tipos de problemas de machine learning, tales como regresión, detección de valores atípicos,y agrupación en clúster.

Ir al artículo anterior de la serie: Cálculo de los parámetros de la función logística

Ir al artículo siguiente de la serie: Introducción al clustering

0 Seguir leyendo →

Cálculo de los parámetros de la función logística

Cálculo de los parámetros de la función logística

El objetivo principal es el cálculo de los parámetros de la función logística para que sea la mejor estimación de las etiquetas de las muestras en el conjunto de datos. Resumiendolo mucho, primero tenemos que mirar la función de costo y ver cuál es la relación entre la función de coste y los parámetros \theta. Por lo tanto, debemos formular la función de coste y usando su derivada podemos encontrar cómo cambiar los parámetros para reducir el costo, o mejor dicho, el error.

1. Búsqueda de la función de costo

Normalmente hay una ecuación general para calcular el costo que es la diferencia entre los valores reales de “y” y el resultado de nuestro modelo. Esta es una regla general para la mayoría de las funciones de coste en Machine Learning (aprendizaje automatizado). Podemos mostrarlo como el “Coste de nuestro modelo comparándolo con las etiquetas reales”, o la “diferencia entre el
valor predicho de nuestro modelo y valor real del campo objetivo”. Normalmente se usa el cuadrado de esa diferencia para evitar resultados negativos, y, por simplificar, la mitad de ese valor se considera como la función de coste:

Cost(\hat y, y)=\frac{1}{2}(\sigma(\theta^T X) - y)^2

Ahora, podemos escribir la función de costo para todas las muestras de nuestro conjunto de datos como la suma promedio de las funciones de coste de todos los casos. También se le llama error cuadrado medio (Mean Squared Error), y, como es una función de un parámetro vector θ, se muestra como J(θ).

J(\theta)=\frac{1}{m}\displaystyle\sum_{i-1}^{m}Cost(\hat y, y)

Para encontrar los mejores pesos o parámetros que minimizan esta función de coste deberíamos calcular el punto mínimo de esta función. Este punto mínimo se calcula utilizando la derivada, pero no hay una manera fácil de encontrarla para el punto mínimo global. La solución es encontrar otra función de coste en su lugar, una que tenga el mismo comportamiento pero sea más fácil para encontrar su punto mínimo.

funcion -logRecordemos que nuestro modelo es \hat y, que el valor real es y (que es igual a 0 o 1) y que nuestro modelo trata de estimarlo. Vamos a suponer que el valor deseado para y es 1. Esto significa que nuestro modelo es mejor si estima y=1 y en ese caso la función de coste devería devolver 0, ya que es igual a la etiqueta real. El costo debería aumentar a medida que el resultado de nuestro modelo se aleje de 1, llegando a ser muy grande si el resultado de nuestro modelo es cercano a 0. Podemos ver que la función -log() proporciona tal función de coste. Por lo tanto, podemos usar la función -log() para calcular el costo de nuestro modelo de regresión logística. Ahora podemos conectarlo a nuestra función de costo total y reescribirlo como esta función. Por lo tanto, esta es la función de costo de regresión logística. Hay que recordar que \hat y no devuelve una clase como salida, sino que es un valor entre 0 y 1, lo que debe ser asumido como una probabilidad.

Cost(\hat y, y) = \left \{ \begin{matrix} -log(\hat y) & \mbox{si }y=1\\ -log(1 - \hat y) & \mbox{si }y=0\end{matrix}\right

J(\theta)=-\frac{1}{m}\displaystyle\sum_{i-1}^{m}y^{i}log(\hat y^i) + (1 - y^i)log(1 - \hat y^i)

2. Minimización de la función de costo

Para la minimización de la función de costo utilizamos un enfoque de optimización. Existen diferentes enfoques de optimización, pero vamos a utilizar uno de los más famosos y efectivos: el descenso gradual. Es un enfoque iterativo para encontrar el mínimo de la una función utilizando su derivada, así que con ella vamos a buscar el mínimo de la función de costo y así cambiar los valores de los parámetros, para minimizar el error.

Piense que los parámetros o pesos en nuestro modelo estan en un espacio bidimensional, por ejemplo, \theta_1, \theta_2, para 2 conjuntos de características, podrían ser edad e ingresos. Y tenemos una tercera dimensión que es el costo o error observado. Si trazamos la función de coste basada en todos los valores posibles de \theta_1, \theta_2, podemos ver algo como un tazón y representa el valor de error para diferentes valores de los parámetros. A esto se le llama “curva de error” o “tazón de error” de su función de costes. Ahora hay que buscar los valores de los parámetros que minimizan el valor de coste.
Se podría seleccionar valores de parámetros aleatorios que ubican un punto en el tazón y mientras que el valor del costo baje, podemos dar un paso más. También puede observarse que cuanto más empinada sea la pendiente, más lejos del punto mínimo estaremos, por lo que podremos elegir nuevos valores más lejos que los anteriores. Haciendo esto sucesivas veces y a medida que nos acercamos al punto más bajo, la pendiente disminuye, por lo que podemos dar pasos más pequeños hasta llegar a una superficie plana.

Para asegurarnos que descendemos, y qué los pasos son suficientemente grandes se debería calcular el gradiente de la función de coste en el punto estudiado. La derivada parcial de J(\theta) con respecto a cada parámetro en ese punto, da la pendiente del movimiento para cada parámetro en ese punto. Así que si nos movemos en la dirección opuesta a esa pendiente, garantizamos que bajamos en la curva de error. El valor del gradiente también indica el tamaño del paso a dar. Si la pendiente es grande, debemos dar un gran paso porque estamos lejos del mínimo y si la pendiente es pequeña deberíamos dar un paso más pequeño. El descenso en pendiente da pasos cada vez más pequeños hacia el mínimo con cada iteración. La derivada parcial de la función de coste J se calcula utilizando esta expresión.

\frac{\partial J}{\partial\theta_1}=-\frac{1}{m}\displaystyle\sum_{i=1}^{m}(y^i-\hat y^i)\hat y^i(1-\hat y^i)x_1

Esta ecuación devuelve la pendiente de ese punto, y deberíamos actualizar el parámetro en la dirección opuesta a la pendiente. Un vector de todas estas pendientes es el vector de gradiente:
\nabla J = \left [ \begin{matrix}\frac{\partial J}{\partial\theta_1} \\ \frac{\partial J}{\partial\theta_2} \\ \frac{\partial J}{\partial\theta_3} \\ \cdots \\ \frac{\partial J}{\partial\theta_k}\end{matrix} \right ]

Podemos usar este vector para cambiar o actualizar todos los parámetros, tomando los valores anteriores de los parámetros y restando la derivada de Error. Esto resulta en los nuevos parámetros para \theta que sabemos que disminuirá el costo: New \theta = old \theta - \nabla J. Además, si multiplicamos el valor del gradiente por un valor constante \eta, que se denomina velocidad de aprendizaje, tenemos un salto proporcional, dando un control adicional sobre la velocidad con la que nos movemos en la superficie: New \theta = old \theta - \eta\nabla J

En resumen, podemos decir simplemente que el descenso en pendiente es como dar pasos en la dirección actual de la pendiente, y el ritmo de aprendizaje es como la duración del paso que das. Así que, estos serían nuestros nuevos parámetros. Fíjate que es una operación iterativa y, en cada iteración, actualizamos los parámetros y minimizamos el coste, hasta que el algoritmo converge en un mínimo aceptable.

Recapitulando:

  • Paso 1. Inicializamos los parámetros con valores aleatorios.
  • Paso 2. Alimentamos la función de costes con la función y calcular el costo. Esperamos una alta tasa de error ya que los parámetros se establecen al azar.
  • Paso 3. Calculamos el gradiente del coste teniendo en cuenta que tenemos que usar una derivada parcial. Entonces, para calcular el vector de gradiente, necesitamos todos los datos de entrenamiento para alimentar la ecuación para cada parámetro. Por supuesto, esta es una parte costosa del algoritmo pero hay algunas soluciones para esto.
  • Paso 4. Las ponderaciones se actualizan con nuevos valores de parámetros.
  • Paso 5. Aquí volvemos al paso 2 y volvemos a alimentar la función de costes, que tiene nuevos parámetros. Esperamos menos errores a medida que vamos bajando por la superficie de los errores. Continuamos este ciclo hasta que alcanzamos un valor corto de costo, o un número limitado de iteraciones.
  • Paso 6. Los parámetros deben ser encontrados después de algunas iteraciones. Esto significa que el modelo está listo y podemos usarlo para predecir la probabilidad de que una observación pertenezca o no a una categoría.

Resulta obvio que todos estos pasos pueden realizarse mediante programas y sus librerias, puedes ver un ejemplo en este artículo: Regresión logística en Python

Ir al artículo anterior de la serie: Regresión lineal Vs. regresión logística

Ir al artículo siguiente de la serie: Máquinas de soporte de vectores

0 Seguir leyendo →

Regresión lineal Vs. regresión logística

Regresión lineal Vs. regresión logística

regresión linealVamos a ver la diferencia entre la regresión lineal vs. la regresión logística. Revisaremos la regresión lineal y veremos por qué no se puede utilizar correctamente para algunos problemas de clasificación binaria.

El objetivo de la regresión logística consiste en construir un modelo para predecir la clase de cada observación, y también la probabilidad de que cada muestra pertenezca a una clase. Idealmente, queremos construir un modelo, \hat y, que pueda estimar que la clase de una observación sea 1, dadas sus características, x. Hay que anotar que “y” son los “vectores de etiquetas” también llamados “valores reales” que nos gustaría predecir, y que “\hat y” es el vector de los valores pronosticados por nuestro modelo.

Cómo funciona la regresión lineal

Con la regresión lineal, se puede encajar una línea o polinomio a través de los datos. Podemos encontrar esta línea usando el entrenamiento de nuestro modelo, o calculándola matemáticamente basádonos en conjuntos de ejemplo. Por simplificar, vamos a decir que es una línea recta que tiene una ecuación a + b \cdot x_1. Ahora, utilizamos esta línea para predecir un valor continuo “y“.

funcion categorizadaPero, ¿podemos utilizar la misma técnica para predecir un campo categórico? Tenemos una característica, x_1, y una característica categórica con dos clases: por ejemplo “si” y “no”. Podemos correlacionar “si” y “no” con valores enteros, 0 y 1. Gráficamente, podríamos representar nuestro conjunto de datos con un gráfico de dispersión. Pero esta vez sólo tenemos 2 valores para el eje y. Con la regresión lineal se puede encajar de nuevo un polinomio a través de los datos, que se muestra tradicionalmente como a + b \cdto x. Este polinomio también se puede mostrar tradicionalmente como \theta_0 + \theta_1 \cdot x_1. Esta línea tiene 2 parámetros, que se muestran con el vector \theta, donde los valores del vector son \theta_0 y \theta_1. También podemos mostrar la ecuación de esta línea formalmente como \theta^T \cdot X = \theta_0 + \theta_1 \cdot x_1. Y, en general, podemos mostrar la ecuación de un espacio multidimensional como \theta^T \cdot X = \theta_0 + \theta_1 \cdot x_1 + \theta_2 \cdot x_2 + \cdots, donde θ son los parámetros de la línea en un espacio bidimensional, o parámetros de un plano en un espacio tri-dimensional, y así sucesivamente. Como \theta^T=\left [ \theta_0, \theta_1, \theta_2, \cdots \right ] es un vector de parámetros, y se supone que para ser multiplicado por X, se muestra convencionalmente como \theta^T. θ también se llama el “vector de peso” o “confianzas de la ecuación”, siendo estos dos términos usados indistintamente. Y X=\begin{bmatrix}{1}\\{x_1}\\{x_2}\\{\cdots}\end{bmatrix} es el conjunto de características, que representa una observación. De todos modos, dado un conjunto de datos, todos los conjuntos de características X, \theta parámetros, se pueden calcular a través de un algoritmo de optimización o matemáticamente, que resulta en la ecuación de la línea adecuada.
Por ejemplo, si los parámetros de esta línea son \theta^T=\left [ -1, 0.1 \right ], entonces la ecuación de la línea es \theta^T \cdot X = -1 + 0.1 \cdot x_1. Ahora, podemos utilizar esta línea de regresión para predecir. Por ejemplo, para un valor de 13 tenemos: \theta^T \cdot X = -1 + 0.1 \cdot x_1 = -1 + 0.1 \cdot 13 = 0.3. Ahora podemos definir un umbral, por ejemplo, en 0.5, para definir la clase. Así que escribimos una regla para nuestro modelo, \hat y, que nos permite separar la clase 0 de la clase 1. Si el valor de \theta^T \cdot X es menor que 0.5, entonces la clase es 0, de lo contrario, si el valor de \theta^T \cdot X es más de 0.5, entonces la clase es 1. Y debido a que el valor “y” de nuestro ejemplo es menor que el umbral, podemos decir que pertenece a la clase 0, basada en nuestro modelo.

Pero aquí hay un problema, ya que no es el mejor modelo para conocer la probabilidad de pertenencia a la clase. Además, si utilizamos la línea de regresión para calcular la clase de un punto, siempre devuelve un número independientemente de lo grande o pequeño, positivo o negativo que es la entrada. Así utilizando el umbral, podemos encontrar la clase de un registro sin importar lo grande que sea el valor, siempre que sea mayor que 0.5, simplemente es igual a 1. Y viceversa, independientemente de lo pequeño que sea el valor, la salida sería cero si es menor que 0.5. En otras palabras, no hay diferencia entre un valor de uno o de 1000; el resultado sería 1. Este método no nos da realmente la probabilidad de que una observación pertenezca a una clase, lo cual es muy deseable. Así que necesitamos un método que también nos pueda dar la probabilidad de caer en una clase.

Función sigmoide

Funcion sigmoideSi en vez de usar \theta^T \cdot X usamos una función específica llamada sigmoide (\sigma), entonces, \sigma(\theta^T \cdot X) = \sigma(\theta_0 + \theta_1 \cdot x_1 + \cdots) nos da la probabilidad de que un punto pertenezca a una clase, en lugar del valor de y directamente. En lugar de calcular el valor de \theta^T \cdot X directamente, devuelve la probabilidad de que un \theta^T \cdot X sea muy grande o muy pequeño. Siempre devuelve un valor entre 0 y 1 dependiendo de que tan grande es \thta^T \cdot Xrealmente.
Ahora, nuestro modelo es \sigma(\theta^T \cdot X), que representa la probabilidad de que la salida sea 1, dado x. La función sigmoide, también llamada la función logística, se asemeja a la función de paso y se utiliza la siguiente expresión en la regresión logística:

\sigma(\theta^T X) = \frac{1}{1+e^{-\theta^T X}}

Fíjese en que en la ecuación sigmoide, cuando \theta^T X se hace muy grande, el e^{-\theta^T X} en el denominador de la fracción se convierte en casi cero, y el valor de la función sigmoid se acerca más a 1. Si \theta^T X es muy pequeño, la función sigmoide se acerca a cero. Representando en el trazado sigmoide, cuando \theta^T X, se hace más grande, el valor de la función sigmoide se acerca a 1, y también, si el \theta^T X es muy pequeño, la función sigmoide se acerca a cero. Por lo tanto, el valor de la función sigmoide está entre 0 y 1, lo que hace que sea apropiado para interpretar los resultados como probabilidades. Es obvio que cuando el resultado de la función sigmoide se acerca más a 1, la probabilidad de y, dado x, sube, y en contraste, cuando el valor sigmoide está más cerca de cero, la probabilidad de y, dado x, es muy pequeña.

Regresión logística

En la regresión logística, modelamos la probabilidad de que una entrada X pertenezca a la clase por defecto Y=1, y podemos escribirlo formalmente como, P(Y=1 \vert X). También podemos escribir P(y=0 \vert x) = 1 - P(y=1 \vert x). Por lo tanto, nuestro trabajo es entrenar al modelo para que establezca sus valores de parámetros de tal manera que nuestro modelo es una buena estimación de P(y=1 \vert x). De hecho, esto es lo que un buen modelo clasificador construido por regresión logística se supone que debe hacer por nosotros. Además, debe ser una buena estimación de P(y=0 \vert x) que se puede mostrar como 1 - \sigma(\theta^T X).
Vamos a ver cuál es el proceso para lograr el cálculo:

  1. Inicializar el vector con valores aleatorios, como se hace con la mayoría de los algoritmos de aprendizaje automático.
  2. Calcular la salida del modelo, que es \sigma(\theta^T X), para una observación de la muestra. La salida de esta ecuación es el valor de la predicción, la probabilidad que el cliente pertenece a la clase 1.
  3. Comparar la salida de nuestro modelo, \hat y, con la etiqueta real de la observación. Luego, registre la diferencia como el error de nuestro modelo para esta observación. Este es el error para una sóla observación dentro del conjunto de datos.
  4. Calcular el error para todas las observaciones tal como lo hicimos en los pasos anteriores, y añadimos estos errores. El error total es el coste del modelo. La función de coste representa la diferencia entre el real y los valores pronosticados del modelo. Por lo tanto, el costo muestra lo mal que se encuentra el modelo estimando las etiquetas del cliente. Por lo tanto, cuanto más bajo es el costo, mejor es el modelo estimando correctamente las etiquetas del cliente. Por lo tanto, lo que queremos hacer es tratar de minimizar este costo.
  5. Pero, debido a que los valores iniciales para \theta fueron elegidos al azar, es muy probable que la función de coste sea muy alta. Por lo tanto, cambiamos la forma de ser de tal manera que esperemos reducir el coste total.
  6. Después de cambiar los valores de \theta, volvemos al paso 2.

A continuación, empezamos otra iteración y calculamos de nuevo el coste del modelo. Y seguimos haciendo esos pasos una y otra vez, cambiando los valores de \theta cada vez, hasta que el coste es lo suficientemente bajo. Por lo tanto, esto plantea dos preguntas: ¿Cómo podemos cambiar los valores de \theta de modo que el coste se reduzca en las iteraciones? ¿Cuándo debemos detener las iteraciones?
Hay diferentes maneras de cambiar los valores \theta, pero una de las formas más populares es la ascendencia gradiente. Además, hay varias formas de detener las iteraciones, pero esencialmente se detiene la formación mediante el cálculo de la precisión de su modelo, y detenerlo cuando sea satisfactorio.

Ir al artículo anterior de la serie: Introducción a la Regresión Logística

Ir al artículo siguiente de la serie: Cálculo de los parámetros de la función logística

0 Seguir leyendo →

Evaluación del modelo de clasificación

Evaluación del modelo de clasificación

Las métricas de evaluación del modelo de clasificación explican el rendimiento de un modelo. Para mostrar algunos modelos de evaluación para la clasificación, vamos a utilizar el supuesto de un conjunto de datos que muestra el ratio de abandono de clientes de una Empresa. Hemos entrenado al modelo,y ahora queremos calcular su precisión utilizando el set de pruebas. Pasamos el set de pruebas a nuestro modelo,y encontramos las etiquetas predichas. ¿Cómo de preciso es este modelo?

Básicamente, se comparan los valores reales del conjunto de pruebas con los valores pronosticados por el modelo, para calcular su precisión. Las métricas de evaluación del modelo de clasificación proporcionan un papel clave en el desarrollo de un modelo, ya que proporcionan pistas de las áreas que pueden mejorarse. Hay diferentes métricas de evaluación de modelos, pero vamos a evaluar las más usadas: índice de Jaccard, F1-score y Log Loss.

Índice de Jaccard

Es una de las medidas de precisión más simples, y también es conocido como el coeficiente de similaridad Jaccard. Para el cálculo de este índice se utiliza la teoría de conjuntos y se puede definir como la intersección de los conjuntos de valores predichos y reales dividido por unión de los dos conjuntos de datos. Si el conjunto completo de etiquetas predichas para una muestra coincide estrictamente con el conjunto verdadero de etiquetas, entonces la precisión del es 1.0, en el extremo contrario, si no coincide ningún valor, el índice es 0.0.

Matríz de confusión (F1-score)

La matriz de confusión muestra las predicciones correctas y exhaustivas, en comparación con las etiquetas reales. Cada fila de la matriz de confusión muestra las etiquetas Reales/Verdaderas del conjunto de pruebas, y las columnas muestran las etiquetas predichas por el clasificador. La matriz de confusión muestra la habilidad del modelo para predecir correctamente. En el caso específico de un clasificador binario podemos interpretar estos números como el recuento de positivos verdaderos (aciertos), positivos falsos (errores), negativos verdaderos (errores), y negativos falsos (aciertos). Basándonos en el conteo de cada sección, podemos calcular la precisión y la exhaustividad de cada una de las etiquetas. La precisión es una medida de la exactitud, a condición de que una etiqueta de clase se haya predicho correctamente.

Se define mediante:
Precision = \frac{Positivo\ verdadero}{(Positivo\ verdadero + Positivo\ Falso)}
Exhaustividad = \frac{Positivo\ verdadero}{(Positivo\ verdadero + Negativo\ Falso)}

Por lo tanto, podemos calcular la precisión y la exhaustividad de cada clase y con ello el F1-scores para cada etiqueta: El F1-score es el promedio armónico de la precisión y la exhaustividad, donde el F1-score alcanza su mejor valor en 1 (que representa la precisión y la exhaustividad perfecta) y su peor valor en 0. Se define utilizando la ecuación F1-score: F1\-score = 2 \cdot \frac{(Precision \cdot Exhaustividad)}{(Precision + Exhaustividad)}
Supongamos el siguiente ejemplo:
F1-score
Para el valor churn=0, Precision = \frac{24}{(24 + 9)} = \frac{24}{33} = 0.727 y Exhaustividad = \frac{24}{(24 + 1)} = \frac{24}{25} = 0.960 => F1\^-score = 2 \cdot \frac{(0.727 \cdot 0.960)}{(0.727 + 0.960)} = 2 \cdot \frac{0.698}{1.687} = 0.827
Para el valor churn=1, Precision = \frac{6}{(6 + 1)} = \frac{6}{7} = 0.857 y Exhaustividad = \frac{6}{(6 + 9)} = \frac{6}{15} = 0.400 => F1\^-score = 2 \cdot \frac{(0.857 \cdot 0.400)}{(0.857 + 0.400)} = 2 \cdot \frac{0.343}{1.257} = 0.546
Y finalmente la media ponderada es \frac{(0.827 \cdot 25) + (0.546 \cdot 15)}{25 + 15} = \frac{28.865}{40} = 0.722

Tenga en cuenta que tanto Jaccard como F1-score se pueden utilizar también para clasificadores multi-clase.

Log Loss

A veces, el resultado de un clasificador es la probabilidad de una etiqueta de clase, en lugar de la etiqueta. Por ejemplo, el resultado puede ser la probabilidad de abandono del cliente, es decir, si el resultado es 1, entonces el cliente abandonaría. Esta probabilidad es un valor entre 0 y 1. Log loss mide el rendimiento de un clasificador donde el resultado pronosticado es un valor de probabilidad entre 0 y 1.
Se puede calcular el Log loss para cada fila utilizando la ecuación de Log loss, que mide como de lejos está cada predicción con respecto a la etiqueta real. Luego calculamos el Log loss promedio en todas las filas del conjunto de pruebas:
LogLoss = -\frac{1}{n} \cdot \sum_{}^{}{(y \cdot \log{(y') + (1 - y) \cdot \log{(1 - y')}})}
Es evidente que los clasificadores más idóneos tienen valores progresivamente más pequeños de Log loss. Por lo tanto, el clasificador con menor Log loss tiene una mejor precisión.

Ir al artículo anterior de la serie: K-vecinos más próximos

Ir al artículo siguiente de la serie: Introducción a los árboles de decisión

0 Seguir leyendo →

K-vecinos más próximos en Python

Importación de los paquetes básicos

import itertools
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import NullFormatter
import pandas as pd
import numpy as np
import matplotlib.ticker as ticker
from sklearn import preprocessing
%matplotlib inline

Importación de los datos

Imagina un proveedor de telecomunicaciones que ha segmentado la base de sus clientes por servicio, categorizando a los clientes en cuatro grupos. Si los datos demográficos se pueden usar para predecir la pertenencia de grupo del envío, la compañía podría personalizar las ofertas para los prospectos. Es un problema de clasificación. Este ejemplo hace foco en datos demográficos, sean region, edad, estado civil, para predecir patrones de uso. El campo objetivo (target), llamado custcat, tiene cuatro valores posibles que corresponden a los cuatro grupos de clientes: 1- Servicio Básico 2- E-Servicio 3- Servicio Plus 4- Servicio Total

Nuestro objetivo es construir un clasificador para predecir la clase de casos desconocidos. Utilizaremos un tipo específico de clasificación llamado K vecino más cercano.

!wget -O teleCust1000t.csv https://s3-api.us-geo.objectstorage.softlayer.net/cf-courses-data/CognitiveClass/ML0101ENv3/labs/teleCust1000t.csv
df = pd.read_csv('teleCust1000t.csv')
df.head()
region tenure age marital address income ed employ retire gender reside custcat
0 2 13 44 1 9 64.0 4 5 0.0 0 2 1
1 3 11 33 1 7 136.0 5 5 0.0 0 6 4
2 3 68 52 1 24 116.0 1 29 0.0 1 2 3
3 2 33 33 0 12 33.0 2 0 0.0 1 1 1
4 2 23 30 1 9 30.0 1 2 0.0 0 4 3

Veamos cuántos de cada clase están en nuestro set de datos

df['custcat'].value_counts()
3    281
1    266
4    236
2    217
Name: custcat, dtype: int64

Puedes explorar fácilmente tus datos utilizando técnicas de visualización:

df.hist(column='income', bins=50)

Definamos feature sets, X:

df.columns
Index(['region', 'tenure', 'age', 'marital', 'address', 'income', 'ed',
       'employ', 'retire', 'gender', 'reside', 'custcat'],
      dtype='object')

Para utilizar la librería scikit-learn, tenemos que convertir el data frame de Panda en un Numpy array:

X = df[['region', 'tenure','age', 'marital', 'address', 'income', 'ed', 'employ','retire', 'gender', 'reside']] .values  #.astype(float)
X[0:5]
array([[  2.,  13.,  44.,   1.,   9.,  64.,   4.,   5.,   0.,   0.,   2.],
       [  3.,  11.,  33.,   1.,   7., 136.,   5.,   5.,   0.,   0.,   6.],
       [  3.,  68.,  52.,   1.,  24., 116.,   1.,  29.,   0.,   1.,   2.],
       [  2.,  33.,  33.,   0.,  12.,  33.,   2.,   0.,   0.,   1.,   1.],
       [  2.,  23.,  30.,   1.,   9.,  30.,   1.,   2.,   0.,   0.,   4.]])

¿Cuáles son nuestras etiquetas?

y = df['custcat'].values
y[0:5]
array([1, 4, 3, 1, 3])

Normalizar los Datos

La estandarización de datos haciendo que la media sea 0 y la varianza uno es buena práctica, especialmente para algoritmos tales como KNN el cual se basa en distancia de casos:

X = preprocessing.StandardScaler().fit(X).transform(X.astype(float))
X[0:5]
array([[-0.02696767, -1.055125  ,  0.18450456,  1.0100505 , -0.25303431,
        -0.12650641,  1.0877526 , -0.5941226 , -0.22207644, -1.03459817,
        -0.23065004],
       [ 1.19883553, -1.14880563, -0.69181243,  1.0100505 , -0.4514148 ,
         0.54644972,  1.9062271 , -0.5941226 , -0.22207644, -1.03459817,
         2.55666158],
       [ 1.19883553,  1.52109247,  0.82182601,  1.0100505 ,  1.23481934,
         0.35951747, -1.36767088,  1.78752803, -0.22207644,  0.96655883,
        -0.23065004],
       [-0.02696767, -0.11831864, -0.69181243, -0.9900495 ,  0.04453642,
        -0.41625141, -0.54919639, -1.09029981, -0.22207644,  0.96655883,
        -0.92747794],
       [-0.02696767, -0.58672182, -0.93080797,  1.0100505 , -0.25303431,
        -0.44429125, -1.36767088, -0.89182893, -0.22207644, -1.03459817,
         1.16300577]])

Dividimos la muestra en los conjuntos de datos para el entrenamiento y para la prueba de exactitud

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=4)
print ('Set de Entrenamiento:', X_train.shape,  y_train.shape)
print ('Set de Prueba:', X_test.shape,  y_test.shape)
Set de Entrenamiento: (800, 11) (800,)
Set de Prueba: (200, 11) (200,)

Clasificación

importar librería del Clasificador que implementa k-vecinos más cercanos.

from sklearn.neighbors import KNeighborsClassifier

Para el entrenamiento vamos a comenzar con el algoritmo con k=4 por ahora:

k = 4
#Entrenar el Modelo y Predecir  
neigh = KNeighborsClassifier(n_neighbors = k).fit(X_train,y_train)
neigh
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=None, n_neighbors=4, p=2,
           weights='uniform')

Usamos el modelo para predecir el set de prueba:

yhat = neigh.predict(X_test)
yhat[0:5]
array([1, 1, 3, 2, 4])

Para evaluar la certeza usamos la función classification accuracy score que computa la certeza del subconjunto. Esta función es igual a la función jaccard_similarity_score. Básicamente, calcula cómo se relacionan las etiquetas actuales con las etiquetas predichas dentro del set de pruebas.

from sklearn import metrics
print("Entrenar el set de Certeza: ", metrics.accuracy_score(y_train, neigh.predict(X_train)))
print("Probar el set de Certeza: ", metrics.accuracy_score(y_test, yhat))
Entrenar el set de Certeza:  0.5475
Probar el set de Certeza:  0.32

Para un K=6 tenemos los siguientes resultados

k = 6
neigh6 = KNeighborsClassifier(n_neighbors = k).fit(X_train,y_train)
yhat6 = neigh6.predict(X_test)
print("Certeza del Set de Entrenamiento: ", metrics.accuracy_score(y_train, neigh6.predict(X_train)))
print("Certeza del Set de Prueba: ", metrics.accuracy_score(y_test, yhat6))
Certeza del Set de Entrenamiento:  0.51625
Certeza del Set de Prueba:  0.31

Cálculo del mejor k

Elegimos k =1, lo utilizamos como parte del entrenamiento para modelar, y calculamos la certeza de la predicción utilizando todas las muestras del set de pruebas. Repetir este proceso, aumentando el k, y viendo luego, cual es el mejor k para el modelo.

Ks = 10
mean_acc = np.zeros((Ks-1))
std_acc = np.zeros((Ks-1))
ConfustionMx = [];
for n in range(1,Ks):
    #Entrenar el Modelo y Predecir  
    neigh = KNeighborsClassifier(n_neighbors = n).fit(X_train,y_train)
    yhat=neigh.predict(X_test)
    mean_acc[n-1] = metrics.accuracy_score(y_test, yhat)
    std_acc[n-1]=np.std(yhat==y_test)/np.sqrt(yhat.shape[0])
mean_acc
array([0.3  , 0.29 , 0.315, 0.32 , 0.315, 0.31 , 0.335, 0.325, 0.34 ])

Dibujo de la certeza del modelo para diferentes números de vecinos

plt.plot(range(1,Ks),mean_acc,'g')
plt.fill_between(range(1,Ks),mean_acc - 1 * std_acc,mean_acc + 1 * std_acc, alpha=0.10)
plt.legend(('Certeza ', '+/- 3xstd'))
plt.ylabel('Certeza ')
plt.xlabel('Número de Vecinos (K)')
plt.tight_layout()
plt.show()

print( "La mejor aproximación de certeza fue con ", mean_acc.max(), "con k=", mean_acc.argmax()+1) 
La mejor aproximación de certeza fue con  0.34 con k= 9
0 Seguir leyendo →

K-vecinos más próximos

K-vecinos más próximos

Para comprender el algorítmo de clasificación K-vecinos más próximos, imagine que un proveedor de telecomunicaciones ha segmentado su base de clientes según el patrón de uso de servicios, categorizando a los clientes en cuatro grupos. Si los datos demográficos se pueden utilizar para predecir la pertenencia a un grupo, la empresa puede personalizar ofertas para clientes potenciales. Se trata de un problema de clasificación. Es decir, dado el conjunto de datos, con las etiquetas predefinidas, tenemos que construir un modelo que se utilizará para predecir la clase de un caso nuevo o desconocido. El ejemplo se centra en el uso de datos demográficos, como la región, la edad y el estado civil, para predecir patrones de uso. El campo objetivo, tiene cuatro valores posibles que corresponden a los cuatro grupos de clientes: Servicio básico, servicio electrónico, servicio adicional y servicio total. Nuestro objetivo es construir un clasificador usando datos de clientes conocidos para predecir el grupo de un nuevo cliente.

Vamos a utilizar el criterio de clasificación llamado “vecino más próximo”. Para simplificar vamos a utilizar sólo dos campos como predictores, la Edad y el Salario, y luego pintar a los clientes en función de estos datos. Si ahora tenemos un nuevo cliente con una edad y salario conocido. ¿Cómo podemos encontrar la clase de este cliente? ¿Podemos encontrar uno de los casos más próximos y asignar la misma etiqueta de clase a nuestro nuevo cliente? ¿Podemos también decir que la clase de nuestro nuevo cliente es probablemente el mismo que el vecino más próximo? Sí, podemos. Pero ¿Hasta qué punto podemos confiar en nuestro juicio, que se basa en el el primer vecino más próximo? Podría ser un mal juicio, especialmente si el primer vecino más próximo es muy específico o un valor atípico, ¿correcto? Por esto, en lugar de elegir al primer vecino más próximo, ¿qué tal si elegimos a los cinco vecinos más próximos, y vemos que tipo es el más frecuente para definir la clase de nuestro nuevo cliente? ¿Esto no tiene más sentido? De hecho, sí.

Este ejemplo pone de relieve la intuición detrás del algoritmo del vecino más próximo.

Definición

El algoritmo del k-vecinos más próximos es un algoritmo de clasificación que toma un montón de puntos marcados y los utiliza para aprender a etiquetar otros puntos. Este algoritmo clasifica los casos basados en su similitud con otros casos. En los vecinos más próximos, los puntos de datos que están cerca entre sí se dicen que son “vecinos”. El algoritmo se basa en este paradigma: Casos similares con las mismas etiquetas de clase están cerca el uno al otro.
Por lo tanto, la distancia entre dos casos es una medida de su disimilitud. Existen diferentes maneras de calcular la similitud, la distancia o la disimilitud de dos puntos de datos. El más común es la distancia de Euclidia.

Funcionamiento (VER EJEMPLO EN PYTHON)

En un problema de clasificación, el algoritmo del vecino más próximo funciona de la siguiente forma:

  • Elegir un valor para K.
  • Calcular la distancia desde el nuevo caso (exclusión de cada uno de los casos del conjunto de datos).
  • Buscar las “k” observaciones en los datos de entrenamiento que son “más próximos” al punto de datos desconocido.
  • Predecir la respuesta del punto de datos desconocido utilizando el valor de respuesta más popular de los vecinos más próximos.

Hay dos partes en este algoritmo que pueden ser un poco confusas: Cómo seleccionar la K correcta y cómo calcular la similaridad entre los casos.

Calculo de similitud

Se puede utilizar la distancia Minkowski para calcular la distancia entre datos, que es en efecto, la distancia Euclidia: Dis(x_1, x_2) = \sqrt{\sum_{i=0}^{n}{(x_{1i} - x_{2i})^2}} Si tenemos más de una característica podemos seguir utilizando la misma fórmula, pero ahora lo usamos en un espacio bidimensional. También podemos usar la misma matriz de distancia para los vectores multidimensionales. Por supuesto, tenemos que normalizar nuestro conjunto de características para obtener la medida de disimilitud precisa. También hay otras medidas de disimilitud que pueden ser utilizadas para este propósito, pero, tal como se menciona, es altamente dependiente del tipo de datos y también el dominio que la clasificación está hecho por él.

Cálculo de K en el k-vecinos más próximos

En el algoritmo de K-vecinos más próximos, K es el número de vecinos más próximos a examinar. Se supone que debe ser especificado por el usuario.
¿Qué ocurre si elegimos un valor muy bajo de K, digamos, k= 1? Esto sería una mala predicción, ya que un caso específico puede hacer que el modelo falle. Podemos decir que hemos capturado el ruido en los datos, o elegimos uno de los puntos que era una anomalía en los datos. Un valor bajo de K causa también un modelo muy complejo, lo que podría resultar en un exceso de ajuste del modelo. Esto significa que el proceso de predicción no se generaliza lo suficiente como para ser utilizado para casos fuera de la muestra. Los datos de fuera de la muestra son datos que están fuera del conjunto de datos utilizado para entrenar el modelo. En otras palabras, no se puede confiar en que sea utilizado para la predicción de muestras desconocidas. Es importante recordar que el exceso de ajuste es malo, ya que queremos un modelo general que funcione para cualquier dato, no sólo los datos utilizados para el entrenamiento.
Ahora, en el lado opuesto del espectro, si elegimos un valor muy alto de K, tal como K=20, entonces el modelo se vuelve demasiado generalizado. Así que, ¿cómo podemos encontrar el mejor valor para K? La solución general es reservar una parte de los datos para probar la precisión del modelo. Una vez que se ha hecho, se elige k =1, y luego se usa la parte de entrenamiento para modelaje, y calcula la precisión de la predicción utilizando todos los ejemplos en el conjunto de pruebas. Se repite este proceso, incrementando el k, y se ve cuál de los k es el mejor para su modelo.

El análisis del vecinos más próximo también se puede utilizar para calcular valores para un objetivo continuo. En esta situación, se utiliza el valor de objetivo promedio o promedio de los vecinos más próximos para obtener el valor predicho para el nuevo caso. Por ejemplo, suponga que está prediciendo el precio de un inicio basado en su conjunto de características, tales como el número de habitaciones, las imágenes cuadradas, el año en que fue construido, etc. Puede encontrar fácilmente las tres casas vecinas más cercanas, por supuesto, no sólo en base a la distancia, si no también basado en todos los atributos, y luego predice el precio de la casa, como el promedio de los vecinos.

Ir al artículo anterior de la serie: Introducción a la clasificación

Ir al artículo siguiente de la serie: Evaluación del modelo de clasificación

0 Seguir leyendo →

Introducción a la clasificación

Introducción a la clasificación

Para realizar esta introducción a la clasificación tenemos que conocer que en Machine Learning, la clasificación es un enfoque de aprendizaje supervisado, que puede ser pensado como un medio de categorización o “clasificación” de algunos elementos desconocidos en un conjunto discreto de “clases”.
La clasificación intenta aprender la relación entre un conjunto de variables características y una variable objetivo. El atributo objetivo en clasificación es una variable categórica con valores discretos.

¿Cómo funcionan las clasificaciones y los clasificadores?

Dado un conjunto de datos de entrenamiento, junto con las etiquetas objetivo, la clasificación determina la etiqueta de clase para un caso de prueba no etiquetado. Veamos un ejemplo: Veamos como clasificar la predicción de incumplimiento de pago de un préstamo. Supongamos que un banco está preocupado por el incumplimiento de pago de sus préstamos. Si se puede usar datos previos de préstamos no pagados para predecir qué clientes podrían tener problemas pagando sus préstamos, estos clientes de “riesgo” pueden no obtener un prestamos o se les puede ofrecer productos alternativos. El objetivo es utilizar los datos de incumplimiento de préstamo existentes de los clientes (edad, ingresos, educación, etc.) para construir un clasificador, pasar a un nuevo cliente por el modelo y luego etiquetarlo como “no pagador” o “pagador”.

Así es como un clasificador predice un caso de prueba sin etiquetas. Hay que tener en cuenta que en este ejemplo específico era de un clasificador binario con dos valores. También podemos crear modelos de clasificadores multi-clases. Por ejemplo, si hemos recopilado datos acerca de un conjunto de pacientes, los cuales sufrieron todos de la misma enfermedad. Durante su tratamiento, cada paciente respondió a uno de tres medicamentos. Puede utilizar este conjuunto de datos etiquetado, con un algoritmo de clasificación, para contruir un modelo de clasificación. De esta manera puedes usarlo para averiguar qué medicamento podría ser apropiado para un futuro paciente con la misma enfermedad. Como puede ver, se trata de una muestra de clasificación multi-clases.

La clasificación tiene también diferentes casos de uso empresarial, por ejemplo:

  • Para predecir la categoría a la que pertenece un cliente
  • Para la detección del ratio de abandono,donde predecimos si un cliente cambia a otro proveedor o marca; o para predecir si un cliente responde o no a una campaña publicitaria en particular.
  • Para el filtrado de correos electrónico, reconocimiento de voz, reconocimiento de escritura a mano, identificación bio-métrica, clasificación de documentos, y mucho más.

Aquí tenemos algunos tipos de algoritmos de clasificación en machine learning.

  • Árboles de decisión
  • Naïve Bayes
  • Análisis Linear Discriminante
  • K-nearest neighbor
  • Regresión logística
  • Neural Networks
  • Support Vector Machines.

Ir al artículo anterior de la serie: Regresión no lineal

Ir al artículo siguiente de la serie: K-vecinos más próximos

0 Seguir leyendo →