sábado, 31 de julio de 2021

Regresión logística y clasificación para Machine Learning II. Clasificación

En este post veremos cómo utilizar el concepto de regresión logística para resolver problemas de clasificación. En cualquier clasificación, primero observaremos los atributos de los datos que tenemos. Y luego, basándonos en esos atributos, realizaremos una categorización o clasificación. La forma más simple de clasificación es una clasificación binaria, en la que solo tenemos dos resultados posibles. Por ejemplo, si un correo electrónico ingresa en nuestra bandeja de entrada, tendremos que clasificarlo como spam o genuino es decir, como correo electrónico auténtico.

En un problema de regresión logística, lo que estamos tratando de predecir es una probabilidad que toma valores entre cero y uno. (en realidad entre 0 y 100%) esto se puede trazar mediante una curva en S.

Regresión logística y clasificación para Machine Learning
Si queremos utilizar un modelo de regresión logística cuyas salidas son probabilidades para hacer una clasificación, tendremos que establecer algún tipo de umbral. Y  hecho esto, podemos decir que cualquier valor que caiga en un lado de este umbral, cae en una clase y los del otro, caen en otra categoría. Una vez que se hayamos establecido este umbral, podríamos utilizarlo. Por ejemplo, si queremos que un clasificador categorice nuestros correos electrónicos como spam o genuinos, debemos introducir el correo electrónico en nuestro clasificador para que realice una serie de verificaciones y estime la probabilidad, según la cual el correo electrónico se clasificará como spam o genuino. El un modelo clasificador basado en (Machine Learning) ML, tendremos que entrenar nuestro modelo de red neuronal clasificadora con un corpus de datos. Este corpus necesita correos electrónicos preclasificados. Y estos se introducirán en nuestro modelo clasificador, que realizará algún tipo de categorización. Compara la salida de la clasificación con los valores reales y luego estima una pérdida. Y este dato de pérdida o diferencia entre la salida y la realidad, retroalimentarán al clasificador para que pueda ajustarse a sí mismo, con el fin de hacer una mejor predicción en el futuro. 

Una vez completada la capacitación, lo que queda es un modelo de regresión logística, que puede utilizarse para hacer predicciones.  Una vez que tengamos nuestro clasificador basado en aprendizaje automático, podemos asegurarnos de que cuando un correo electrónico llegue a nuestra bandeja de entrada, este se envíe a este clasificador. Basado en lo que ha aprendido durante la capacitación, el modelo tomará una decisión. Si el  correo electrónico es genuino o es spam. 

Regresión logística y clasificación para Machine Learning
Si llega un correo electrónico y resulta que intenta vendernos algún producto. Se trata de un correo electrónico bastante comercial que se envía a varios destinatarios diferentes., y  contiene un saludo genérico. Este correo electrónico se enviará a nuestro clasificador, que debe tomar una decisión. Aplicará el principio de regresión logística y estimará una probabilidad. Si por ejemplo calcula que la probabilidad de que este correo electrónico sea spam es del 55%. Y luego, dependiendo de dónde se haya establecido el umbral para realizar esta clasificación, este correo electrónico se marcará como spam o genuino. 

Esta es la región de regresión logística del modelo, que es muy sensible a cualquier cambio en la entrada. Puede haber algunas características en el correo electrónico que hagan que nuestro modelo de regresión logística decida que hay un 99% de probabilidad de que se trate de spam. Nuestro modelo puede calcular un solo valor de probabilidad. Si necesitamos realizar una clasificación utilizando este modelo de regresión logística, deberemos establecer un umbral. La regla del 50% dicta que, en caso de una clasificación binaria, este umbral debe establecerse en una probabilidad del 50%.

Por lo tanto, cualquier probabilidad de spam inferior al 50% debe clasificarse como genuino, y cualquier probabilidad mayor debe marcarse como spam. Si solo hay dos resultados posibles para este clasificador, cada uno de ellos opera sobre un rango de valores de probabilidad. La combinación de la curva S de regresión logística y el establecimiento de un valor umbral, nos ayudará a realizar la clasificación.


sábado, 24 de julio de 2021

Árboles de decisión, Decision trees (Clasificación múltiple etiquetada)

Los árboles de decisión son algoritmos de Machine Learning utilizados para clasificación múltiple de datasets etiquetados.

Vamos a comenzar con ejemplos prácticos con nuestro propio dataset (y ahora si) esta es la técnica más adecuada para este dataset aunque ya lo hemos utilizado para explicar otros conceptos de Machine Learning. 

Estos post están pensados para que el lector realice las pruebas con sus propios Datasets, pues muchas veces seguimos ejemplos con instrucciones para tratar un dataset previamente descargado de internet con datos que ni entendemos ni nos sirven de mucho. Creo que se aprende mucho más creando nuestro propio dataset y adaptando las instrucciones a nuestras necesidades en vez de ejecutar las instrucciones del script.   Aquí, Como crear nuestro propio dataset 

El dataset que utilizaré es uno con los resultados de partidos de fútbol con la intención de calcular la quiniela más adecuada.

Comenzaremos importando las librerías necesarias y nuestro dataset.

Estas son las inicializaciones de rigor

# Requiere Python ≥3.

import sys

assert sys.version_info >= (3, 5)

# Requiera Scikit-Learn ≥0.20

import sklearn

assert sklearn.__version__ >= "0.20"

# importaciones comunes

import numpy as np

import pandas as pd

import os

# para hacer la salida de este notebook estable

np.random.seed(42)

# Para generar imágenes y gráficos

%matplotlib inline

import matplotlib as mpl

import matplotlib.pyplot as plt

mpl.rc('axes', labelsize=14)

mpl.rc('xtick', labelsize=12)

mpl.rc('ytick', labelsize=12)

Y ahora cargamos el dataset y comprobamos sus datos mostrando la cabecera

from sklearn.tree import DecisionTreeClassifier

quinielas = pd.read_csv('Completo_Etiquetado_Puntuado_2.csv') #tiene goles quiniela y quinigol

quinielas.head()

Podemos echar un vistazo a nuestro dataset para comprobar su estructura. Por ejemplo para ver las columnas hacemos

#Para echar un vistazo a nuestro dataset, nos muestra las columnas del dataset

list(quinielas.keys())

Ahora asociamos el dataset al árbol de decisión, en la X le asignamos el dataset al que le eliminamos las columnas de etiquetas y las que no son relevantes o no están normalizadas.

A la ‘y’ le asignamos la etiqueta de las Q1 en este caso y creamos una variable llamada arbol_clasificador a la que asignamos nuestro árbol con la instrucción  DecisionTreeClassifier entrenado con las variables X e y.

#las X contienen los datos relevantes para hacer predicciones quitamos todas las etiquetas

X = quinielas.drop(columns=['idPartido','temporada','Q1','QX','Q2','QGC0','QGC1','QGC2','QGCM','QGF0','QGF1','QGF2','QGFM','timestamp','golesLocal','golesVisitante','fecha','quiniela_arbol_decision'])

#las Y son las etiquetas a predecir, en este caso quitamos todo excepto 'Q1','QX','Q2'

y = quinielas.drop(columns=['division','jornada','idPartido','temporada','PuntosLocal','PuntosVisitante','EquipoLocal','Puntos_Normalizados','EquipoVisitante','QGC0','QGC1','QGC2','QGCM','QGF0','QGF1','QGF2','QGFM','timestamp','golesLocal','golesVisitante','fecha','timestamp','quiniela_arbol_decision'])

arbol_clasificador = DecisionTreeClassifier(max_depth=2, random_state=42)

arbol_clasificador.fit(X, y)

 

Árboles de decisión

Una vez entrenado nuestro árbol, vamos a realizar una primera predicción, pera ello lo primero que hacemos es mostrar la X para ver en qué orden tenemos que introducir los datos y cuales hay que introducir y cuales no.

#echamos un vistazo a las X

X.head()

#echamos un vistazo a las y

y.head()

A continuación tomamos una línea al azar (en este caso la hemos cogido del dataset y probamos su predicción de probabilidades

#intentamos predecir esta línea

# 1ª división jornada 25 ,(18 codigo del equipo) Villareal 26 puntos - (46 codigo del equipo) Levante 18 puntos 26/18 = 1,44

arbol_clasificador.predict_proba([[1,25,18,46,26,18,1.44]])

Decision trees
Y para ver los resultados que predice hacemos 

arbol_clasificador.predict([[1,25,18,46,26,18,1.44]])

Árboles de decisión

En este caso estamos intentando predecir la Q1, QX y Q2 y nos devuelve un array con la probabilidad de que sea no 1 (38,94 %) o 1  (61,05%), para la no X tenemos 74,17% frente a 25,82% de X y para el no 2 tenemos 86,87% frente al 13,12% de 2.  (Nótese que primero predice la probabilidad de la negada, no del resultado) Como se puede ver, el array de resultados es [1,0,0] es decir 1. [0,1,0] sería X y [0,0,1] sería 2.

Árboles de decisión con Python

El conocimiento que un árbol de decisión adquiere a través del entrenamiento se expresa directamente como una estructura jerárquica. Y esta estructura retiene y muestra este conocimiento para que se entienda fácilmente. A continuación un ejemplo completo más sencillo que el anterior pero posiblemente más preciso.

Vamos a construir aquí un árbol de decisión. 

import numpy as np

import matplotlib.pyplot as plt

%matplotlib inline

import pandas as pd

from sklearn.model_selection import train_test_split

from sklearn import tree

quinielas = pd.read_csv('Completo_Etiquetado_Puntuado_3.csv') #tiene goles quiniela y quinigol

Echamos un vistazo al dataset con:

quinielas.head()

Y asociamos las X a los datos del Dataset y las Y a las etiquetas (en este caso sólo a Q1, QX y Q2)

#las X contienen los datos relevantes para hacer predicciones quitamos todas las etiquetas

X = quinielas.drop(columns=['idPartido','temporada','Q1','QX','Q2','QGC0','QGC1','QGC2','QGCM','QGF0','QGF1','QGF2','QGFM','timestamp','golesLocal','golesVisitante','fecha'])

#las Y son las etiquetas a predecir, en este caso quitamos todo excepto 'Q1','QX','Q2'

y = quinielas.drop(columns=['division','jornada','idPartido','temporada','PuntosLocal','PuntosVisitante','EquipoLocal','Puntos_Normalizados','EquipoVisitante','QGC0','QGC1','QGC2','QGCM','QGF0','QGF1','QGF2','QGFM','timestamp','golesLocal','golesVisitante','fecha','timestamp'])

Ahora dividimos el Dataset en una parte de entrenamiento y otra de testeo.

#Definimos la parte del Dataset que es de entrenamiento y la de testeo

X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2, random_state=42)

Creamos una instancia para el árbol clasificador

Arbol_Clasificador = tree.DecisionTreeClassifier()

Y luego entrenamos el árbol de decisiones, pasándole X_train e y_train. Porque al igual que con otros clasificadores, DecisionTreeClassifier toma como entrada dos matrices, las matrices X e y.

Ahora creamos algunas predicciones. Primero entrenamos el árbol

Arbol_Clasificador = Arbol_Clasificador.fit(X_train, y_train)

Y a continuación generamos las predicciones

#Evaluamos las predicciones con el subconjunto de testeo

Predicciones =  Arbol_Clasificador.predict(X_test)

Y finalmente vemos los resultados

#vemos los resultados

from sklearn.metrics import classification_report

print(classification_report(y_test,Predicciones))

Árboles de decisión

En este caso 0 se corresponde con 1, 1 con X y 2 con el 2. Tenemos un 83% de aciertos para el 1, un 58% para la X y un 70 % para el dos lo cual no está nada mal.

Árboles de Regresión

Los árboles de decisión también son capaces de ejecutar tareas de regresión. Como ejemplo, vamos a construir un árbol de regresión utilizando la clase DecisionTreeRegressor de la  librería de Scikit-Learn y la vamos a entrenar con nuestro dataset para una profundidad máxima de 2 y de 3.

from sklearn.tree import DecisionTreeRegressor

arbol_regresion_1 = DecisionTreeRegressor(max_depth=2, random_state=42)

arbol_regresion_2 = DecisionTreeRegressor(max_depth=3, random_state=42)

arbol_regresion_1.fit(X, y)

arbol_regresion_2.fit(X, y)

#intentamos predecir esta línea

# 1ª división jornada 25 ,(18 codigo del equipo) Villareal 26 puntos - (46 codigo del equipo) Levante 18 puntos 26/18 = 1,44

arbol_regresion_1.predict([[1,25,18,46,26,18,1.44]])

arbol_regresion_2.predict([[1,25,18,46,26,18,1.44]])

árboles de regresión

En este caso sólo nos muestra la probabilidad del resultado, que es bastante cercana a la que vimos antes, en ambos caso es [1,0,0]

La diferencia entre un árbol de decisión y un árbol de regresión es que en el árbol de regresión en vez de tratar de predecir una clase en cada nodo, se predice un valor. Por ejemplo si queremos hacer una predicción para una nueva instancia, sea X= 1,444 comenzamos el árbol desde la raíz y alcanzamos una hoja nodo que predice el valor  [1,0,0]. Esta predicción es el valor objetivo después de un entrenamiento de casi 2000 instancias asociadas a esta hoja del nodo.

Los árboles de regresión son propensos al sobreajuste, sobre todo cuando utilizamos los parámetros por defecto

Inestabilidad 

Pero los árboles de decisión tienen mucho a su favor, son sencillos de comprender e interpretar, fáciles de usar, versátiles y potentes. Sin embargo tienen algunas limitaciones, por ejemplo sus límites de decisión son ortogonales (líneas rectas perpendiculares a los ejes) lo que les hace sensibles a la rotación. Este problema se puede tratar de solventar utilizando PCA 

Pero el principal problema de los árboles de decisión es que son muy sensibles a pequeñas variaciones en los datos de entrenamiento, pues el cambio en un solo dato puede dar como resultado unos límites del árbol completamente diferentes.


sábado, 17 de julio de 2021

Regresión Logística para clasificadores de Machine Learning I: la curva de regresión logística.

Los algoritmos de regresión logística  pueden ser utilizados para clasificación (fundamentalmente binaria ver esquema general de IA). Son utilizados para estimar la probabilidad de que una instancia pertenezca a una clase particular o no. De modo que si la probabilidad de pertenecer a una clase A es superior a 50% el modelo predice que esa instancia pertenece a la clase A y la etiqueta como 1. En caso contrario, predice que no pertenece y la etiqueta como 0. Esto forma un clasificador binario.

Estimado las probabilidades

Un modelo de regresión logística computa una suma ponderada de características de entrada (más un término de desplazamiento) y da como resultado un porcentaje entre 0 (0) y 100% (1). Su función es una sigmoide.

 

Regresión Logística para clasificadores de Machine Learning

En el modelo concreto de arriba el 50% está justo para t=0 de modo que podemos decir que la predicción de este modelo es de 0 para t<0 y 1 para t >0.

Este tipo de función es especialmente adecuado para características separadas que se unen en un estrecho rango. Por ejemplo a la hora de distinguir entre dos especies de flor Iris Virgínica o Iris Versiocolor en función de la longitud de sus pétalos. O bien las posibilidades de default de un pagador frente a su acreedor en función del tiempo que tarda en devolver el préstamo.

Así por ejemplo en el caso de las flores, la anchura del pétalo de Iris Virgínica oscila entre 1,4 cm y 2,5 cm mientras que la de Iris Versicolor va desde los 0,1 cm hasta los 1,8. En este caso hay un pequeño solapamiento en el cual el modelo tendrá difícil saber de qué especie se trata, pero en el resto del dataset será realivamente fácil clasificar una u otra variedad.

La curva de regresión logística

Para explicar la regresión logística consideraremos un problema de la vida real. Si queremos comprar un coche podemos pagar de dos formas. Una sería con tarjeta de débito, en el que nos aseguramos de que nuestra cuenta bancaria tenga todo el dinero necesario para pagar la cantidad total. De forma que realizamos el pago completo por adelantado y no tenemos que preocuparnos por los pagos más adelante. El problema aquí es que es posible que nos quedemos sin efectivo para realizar otros pagos. En el otro extremo, tenemos la tarjeta de crédito. Donde no realiza el pago completo, pero pagamos una cuota mensual acumulando una gran cantidad de intereses sobre el monto pendiente. Ninguno de estos enfoques es realmente óptimo. 

Para encontrar la mejor solución, intentaremos cuantificar cada uno de estos enfoques. Con la tarjeta de crédito, tenemos un 100% de probabilidad de tener dinero para pagar otros gastos importantes. Pero la probabilidad de que paguemos el préstamo completamente se reduce significativamente. Los beneficios de este enfoque son que tendremos dinero disponible para otros gastos importantes. Por otra parte con la tarjeta de débito, tenemos una probabilidad cercana a cero de tener dinero para otros gastos importantes. Sin embargo, en este caso, la probabilidad de tener que reembolsar el préstamo no procede ya que no hemos pedido un préstamo. Los dos enfoques que acabamos de discutir son bastante extremos y, por lo general, hay un término medio

Pero si pagamos la mitad a crédito y el resto con el saldo de la tarjeta de débito tenemos un enfoque mixto en el cual podemos tener un 90% de éxito en ambas variables. Esto sería una representación más precisa de escenarios del mundo real para la mayoría de las personas. Donde, no hay certeza sobre un pago de un préstamo. Pero siempre hay una probabilidad asociada.

Regresión Logística para clasificadores de Machine Learning I: la curva de regresión logística.


Si vemos este problema particular desde el punto de vista de un acreedor. El acreedor está haciendo los préstamos. Necesita planificar sus finanzas de acuerdo con la probabilidad de incumplimiento de cada uno de sus clientes.

El problema que enfrenta el acreedor que emite un préstamo es de regresión logística. Para representarlo gráficamente a lo largo del eje X, traza el retraso en el pago de cada cliente en número de días y en el eje Y se utiliza para estimar la probabilidad de que el cliente no pague su préstamo. Cada uno de estos ejes responde a diferentes preguntas. A lo largo del eje X, la pregunta que debe hacerse es ¿cuántos días más tiene el cliente para liquidar el préstamo antes de que se considere que está en mora? Y a lo largo del eje Y, obtenemos la respuesta a la pregunta, ¿cuál es la probabilidad de que el cliente incumpla el pago? 

Esta relación se puede mapear trazando una curva en S. Esto se debe a que el plazo de amortización es binario. Una vez que hayamos cruzado la fecha límite, habremos perdido la oportunidad de pagar y definitivamente se nos considera morosos. Esta es la razón por la que la curva en S se aplana al final después de que se alcanza la fecha límite de reembolso. El valor mínimo de esta curva en S es 0, mientras que el techo es 1, lo que representa un rango de probabilidades. Esto contrasta con la regresión lineal, donde el rango de valores de y normalmente va desde menos infinito hasta más infinito. 

La curva en S ayuda al acreedor a responder a la pregunta de cuál es la probabilidad de que el cliente liquide su préstamo a tiempo. La solución al problema de la regresión logística es encontrar la curva de mejor ajuste para representar nuestros datos. Por tanto, las curvas en S se utilizan mucho y están representadas por esta ecuación:

 y = 1 / (1 + e ^ - (A + Bx)

Para nuestro ejemplo de reembolso de préstamo, la probabilidad de incumplimiento se puede representar mediante esta curva en forma de S. 

Curva en S de Regresión Logística
En esta ecuación, A es el valor de la intersección, mientras que B se llama coeficiente de regresión. Al construir un modelo de regresión logística, estos son los dos valores que debemos determinar. e es la base de los logaritmos naturales, que tiene un valor aproximado de 2.71828. Si los valores de A y B son positivos, la curva en forma de S se verá así. 

Donde en el rango de valores de x va desde de menos infinito a 0, la probabilidad es 0. Mientras que, la probabilidad es 1 para cualquier valor positivo de x. Por otro lado, cuando 

tanto A como B son negativos, la regresión logística nos ayuda a comprender cómo las probabilidades de ciertos resultados se ven afectadas por las acciones. 

Cuando echamos un vistazo a nuestra curva S, vemos que hay un valor mínimo para la probabilidad, que es 0. Esto está representado por todos los valores hacia la izquierda de este gráfico. Si un cliente tiene solo unos días para pagar, significa que es más probable que solo esté esperando el momento adecuado para pagar. Y la probabilidad de incumplimiento se puede considerar 0 en este rango en particular. Sin embargo, en el otro extremo de la escala, tenemos clientes que están muy cerca de su fecha límite o la han excedido. Y su probabilidad de incumplimiento puede considerarse 1. Sin embargo, entre estos dos extremos se encuentra la sección más interesante. 

 Y aquí es donde incluso un pequeño cambio en el valor de x puede resultar en un cambio significativo en el valor de y. De hecho, esta es una representación muy precisa de cómo se desarrollan las cosas en el mundo real. En la región verde del gráfico, la probabilidad de incumplimiento es muy sensible a cualquier retraso en el pago. Para ilustrar esto, consideremos dos clientes diferentes que realizan sus pagos los días X1 y X2. En comparación con otras secciones de este gráfico, la probabilidad de que estos clientes incumplan varía bastante en esta región.

Como acreedores, podemos trazar la curva S, que mapea la probabilidad de incumplimiento, de acuerdo con el retraso en el pago. Y después establecemos un valor de umbral a lo largo del eje X para el retraso del reembolso. 

Regresión Logística para Machine Learning
Por ejemplo, podemos elegir su umbral X para que corresponda con la probabilidad de incumplimiento del 50%. Nuestra estimación en este caso es que cualquier cliente cuyo retraso en el pago sea menor que el valor de este límite no incurrirá en incumplimiento. Considerando que, cualquier retraso más allá de ese umbral significará que el cliente incurrirá en morosidad