Regresión logística en Python - Guía rápida

La regresión logística es un método estadístico de clasificación de objetos. Este capítulo dará una introducción a la regresión logística con la ayuda de algunos ejemplos.

Clasificación

Para comprender la regresión logística, debe saber qué significa clasificación. Consideremos los siguientes ejemplos para comprender esto mejor:

  • Un médico clasifica el tumor como maligno o benigno.
  • Una transacción bancaria puede ser fraudulenta o genuina.

Durante muchos años, los humanos han realizado este tipo de tareas, aunque son propensos a errores. La pregunta es ¿podemos entrenar máquinas para que realicen estas tareas por nosotros con mayor precisión?

Un ejemplo de máquina que realiza la clasificación es el correo electrónico Clienten su máquina que clasifica cada correo entrante como "spam" o "no spam" y lo hace con una precisión bastante grande. La técnica estadística de regresión logística se ha aplicado con éxito en el cliente de correo electrónico. En este caso, hemos entrenado nuestra máquina para resolver un problema de clasificación.

La regresión logística es solo una parte del aprendizaje automático que se utiliza para resolver este tipo de problema de clasificación binaria. Hay varias otras técnicas de aprendizaje automático que ya están desarrolladas y se encuentran en la práctica para resolver otros tipos de problemas.

Si ha notado, en todos los ejemplos anteriores, el resultado de la predicación tiene solo dos valores: Sí o No. Los llamamos clases, para decir que decimos que nuestro clasificador clasifica los objetos en dos clases. En términos técnicos, podemos decir que el resultado o la variable objetivo es de naturaleza dicotómica.

Existen otros problemas de clasificación en los que la salida se puede clasificar en más de dos clases. Por ejemplo, si se le da una canasta llena de frutas, se le pide que separe frutas de diferentes tipos. Ahora, la canasta puede contener naranjas, manzanas, mangos, etc. Entonces, cuando separa las frutas, las separa en más de dos clases. Este es un problema de clasificación multivariante.

Considere que un banco se acerca a usted para desarrollar una aplicación de aprendizaje automático que les ayudará a identificar a los clientes potenciales que abrirían un Depósito a plazo (también llamado Depósito fijo por algunos bancos) con ellos. El banco realiza periódicamente una encuesta mediante llamadas telefónicas o formularios web para recopilar información sobre los clientes potenciales. La encuesta es de naturaleza general y se lleva a cabo con un público muy amplio, de los cuales muchos pueden no estar interesados ​​en tratar con este banco en sí. Del resto, solo unos pocos pueden estar interesados ​​en abrir un depósito a plazo. Otros pueden estar interesados ​​en otras facilidades que ofrece el banco. Por lo tanto, la encuesta no se realiza necesariamente para identificar a los clientes que abren TD. Su tarea es identificar a todos aquellos clientes con alta probabilidad de abrir TD a partir de los enormes datos de la encuesta que el banco compartirá con usted.

Afortunadamente, uno de esos tipos de datos está disponible públicamente para aquellos que aspiran a desarrollar modelos de aprendizaje automático. Estos datos fueron preparados por algunos estudiantes de UC Irvine con financiamiento externo. La base de datos está disponible como parte deUCI Machine Learning Repositoryy es ampliamente utilizado por estudiantes, educadores e investigadores de todo el mundo. Los datos se pueden descargar desde aquí .

En los siguientes capítulos, realicemos ahora el desarrollo de la aplicación utilizando los mismos datos.

En este capítulo, comprenderemos el proceso involucrado en la configuración de un proyecto para realizar regresión logística en Python, en detalle.

Instalación de Jupyter

Usaremos Jupyter, una de las plataformas más utilizadas para el aprendizaje automático. Si no tiene Jupyter instalado en su máquina, descárguelo desde aquí . Para la instalación, puede seguir las instrucciones en su sitio para instalar la plataforma. Como sugiere el sitio, es posible que prefiera utilizarAnaconda Distributionque viene junto con Python y muchos paquetes de Python de uso común para informática científica y ciencia de datos. Esto aliviará la necesidad de instalar estos paquetes individualmente.

Después de la instalación exitosa de Jupyter, comience un nuevo proyecto, su pantalla en esta etapa se vería como la siguiente lista para aceptar su código.

Ahora, cambie el nombre del proyecto de Untitled1 to “Logistic Regression” haciendo clic en el nombre del título y editándolo.

Primero, vamos a importar varios paquetes de Python que necesitaremos en nuestro código.

Importación de paquetes de Python

Para ello, escriba o corte y pegue el siguiente código en el editor de código:

In [1]: # import statements
   import pandas as pd
   import numpy as np
   import matplotlib.pyplot as plt

   from sklearn import preprocessing
   from sklearn.linear_model import LogisticRegression
   from sklearn.model_selection import train_test_split

Tu Notebook debería tener el siguiente aspecto en esta etapa:

Ejecute el código haciendo clic en el Runbotón. Si no se generan errores, ha instalado Jupyter correctamente y ahora está listo para el resto del desarrollo.

Las primeras tres declaraciones de importación importan paquetes pandas, numpy y matplotlib.pyplot en nuestro proyecto. Las siguientes tres declaraciones importan los módulos especificados de sklearn.

Nuestra siguiente tarea es descargar los datos necesarios para nuestro proyecto. Aprenderemos esto en el próximo capítulo.

Los pasos involucrados en la obtención de datos para realizar la regresión logística en Python se analizan en detalle en este capítulo.

Descarga de conjunto de datos

Si aún no ha descargado el conjunto de datos UCI mencionado anteriormente, descárguelo ahora desde aquí . Haga clic en la carpeta de datos. Verá la siguiente pantalla:

Descargue el archivo bank.zip haciendo clic en el enlace proporcionado. El archivo zip contiene los siguientes archivos:

Usaremos el archivo bank.csv para el desarrollo de nuestro modelo. El archivo bank-names.txt contiene la descripción de la base de datos que necesitará más adelante. Bank-full.csv contiene un conjunto de datos mucho más grande que puede utilizar para desarrollos más avanzados.

Aquí hemos incluido el archivo bank.csv en el zip de origen descargable. Este archivo contiene los campos delimitados por comas. También hemos realizado algunas modificaciones en el archivo. Se recomienda que utilice el archivo incluido en el código fuente del proyecto para su aprendizaje.

Cargando datos

Para cargar los datos del archivo csv que acaba de copiar, escriba la siguiente declaración y ejecute el código.

In [2]: df = pd.read_csv('bank.csv', header=0)

También podrá examinar los datos cargados ejecutando la siguiente declaración de código:

IN [3]: df.head()

Una vez que se ejecuta el comando, verá el siguiente resultado:

Básicamente, imprimió las primeras cinco filas de los datos cargados. Examine las 21 columnas presentes. Usaremos solo algunas columnas de estas para el desarrollo de nuestro modelo.

A continuación, necesitamos limpiar los datos. Los datos pueden contener algunas filas conNaN. Para eliminar tales filas, use el siguiente comando:

IN [4]: df = df.dropna()

Afortunadamente, bank.csv no contiene filas con NaN, por lo que este paso no es realmente necesario en nuestro caso. Sin embargo, en general, es difícil descubrir tales filas en una base de datos enorme. Por lo tanto, siempre es más seguro ejecutar la declaración anterior para limpiar los datos.

Note - Puede examinar fácilmente el tamaño de los datos en cualquier momento utilizando la siguiente declaración:

IN [5]: print (df.shape)
(41188, 21)

El número de filas y columnas se imprimirá en la salida como se muestra en la segunda línea de arriba.

Lo siguiente que debe hacer es examinar la idoneidad de cada columna para el modelo que estamos tratando de construir.

Siempre que una organización realiza una encuesta, intenta recopilar la mayor cantidad de información posible del cliente, con la idea de que esta información sería útil para la organización de una forma u otra, en un momento posterior. Para resolver el problema actual, tenemos que recoger la información que sea directamente relevante para nuestro problema.

Visualización de todos los campos

Ahora, veamos cómo seleccionar los campos de datos que nos son útiles. Ejecute la siguiente declaración en el editor de código.

In [6]: print(list(df.columns))

Verá la siguiente salida:

['age', 'job', 'marital', 'education', 'default', 'housing', 'loan', 
'contact', 'month', 'day_of_week', 'duration', 'campaign', 'pdays', 
'previous', 'poutcome', 'emp_var_rate', 'cons_price_idx', 'cons_conf_idx', 
'euribor3m', 'nr_employed', 'y']

La salida muestra los nombres de todas las columnas de la base de datos. La última columna "y" es un valor booleano que indica si este cliente tiene un depósito a plazo con el banco. Los valores de este campo son "y" o "n". Puede leer la descripción y el propósito de cada columna en el archivo banks-name.txt que se descargó como parte de los datos.

Eliminar campos no deseados

Al examinar los nombres de las columnas, sabrá que algunos de los campos no tienen importancia para el problema en cuestión. Por ejemplo, campos comomonth, day_of_week, campaña, etc. no nos sirven. Eliminaremos estos campos de nuestra base de datos. Para soltar una columna, usamos el comando soltar como se muestra a continuación:

In [8]: #drop columns which are not needed.
   df.drop(df.columns[[0, 3, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19]], 
   axis = 1, inplace = True)

El comando dice que suelte la columna número 0, 3, 7, 8, etc. Para asegurarse de que el índice esté seleccionado correctamente, utilice la siguiente declaración:

In [7]: df.columns[9]
Out[7]: 'day_of_week'

Esto imprime el nombre de la columna para el índice dado.

Después de descartar las columnas que no son necesarias, examine los datos con la declaración principal. La salida de la pantalla se muestra aquí:

In [9]: df.head()
Out[9]:
      job   marital  default  housing  loan  poutcome    y
0     blue-collar    married  unknown yes no nonexistent 0
1     technician     married  no    no    no nonexistent 0
2     management     single   no    yes   no success     1
3     services       married  no    no    no nonexistent 0
4     retired        married  no    yes   no success     1

Ahora, solo tenemos los campos que creemos que son importantes para nuestro análisis y predicción de datos. La importancia deData Scientistentra en escena en este paso. El científico de datos tiene que seleccionar las columnas apropiadas para la construcción del modelo.

Por ejemplo, el tipo de jobaunque a primera vista puede que no convenza a todo el mundo para su inclusión en la base de datos, será un campo muy útil. No todos los tipos de clientes abrirán el TD. Es posible que las personas de ingresos más bajos no abran los TD, mientras que las personas de ingresos más altos suelen aparcar su dinero excedente en los TD. Entonces, el tipo de trabajo se vuelve significativamente relevante en este escenario. Asimismo, seleccione cuidadosamente las columnas que crea que serán relevantes para su análisis.

En el próximo capítulo, prepararemos nuestros datos para construir el modelo.

Para crear el clasificador, debemos preparar los datos en un formato solicitado por el módulo de construcción del clasificador. Preparamos los datos haciendoOne Hot Encoding.

Codificación de datos

Discutiremos en breve lo que queremos decir con la codificación de datos. Primero, ejecutemos el código. Ejecute el siguiente comando en la ventana de código.

In [10]: # creating one hot encoding of the categorical columns.
data = pd.get_dummies(df, columns =['job', 'marital', 'default', 'housing', 'loan', 'poutcome'])

Como dice el comentario, la declaración anterior creará la única codificación en caliente de los datos. Veamos qué ha creado. Examine los datos creados llamados“data” imprimiendo los registros de cabecera en la base de datos.

In [11]: data.head()

Verá la siguiente salida:

Para comprender los datos anteriores, enumeraremos los nombres de las columnas ejecutando el data.columns comando como se muestra a continuación -

In [12]: data.columns
Out[12]: Index(['y', 'job_admin.', 'job_blue-collar', 'job_entrepreneur',
'job_housemaid', 'job_management', 'job_retired', 'job_self-employed', 
'job_services', 'job_student', 'job_technician', 'job_unemployed',
'job_unknown', 'marital_divorced', 'marital_married', 'marital_single', 
'marital_unknown', 'default_no', 'default_unknown', 'default_yes', 
'housing_no', 'housing_unknown', 'housing_yes', 'loan_no',
'loan_unknown', 'loan_yes', 'poutcome_failure', 'poutcome_nonexistent', 
'poutcome_success'], dtype='object')

Ahora, explicaremos cómo se realiza la codificación en caliente get_dummiesmando. La primera columna en la base de datos recién generada es el campo "y" que indica si este cliente se ha suscrito a un TD o no. Ahora, veamos las columnas que están codificadas. La primera columna codificada es“job”. En la base de datos, encontrará que la columna "trabajo" tiene muchos valores posibles, como "admin", "obrero", "emprendedor", etc. Para cada valor posible, tenemos una nueva columna creada en la base de datos, con el nombre de la columna agregado como prefijo.

Por lo tanto, tenemos columnas llamadas "job_admin", "job_blue-collar", etc. Para cada campo codificado en nuestra base de datos original, encontrará una lista de columnas agregadas en la base de datos creada con todos los valores posibles que la columna toma en la base de datos original. Examine cuidadosamente la lista de columnas para comprender cómo se asignan los datos a una nueva base de datos.

Comprender el mapeo de datos

Para comprender los datos generados, imprimamos todos los datos usando el comando de datos. La salida parcial después de ejecutar el comando se muestra a continuación.

In [13]: data

La pantalla anterior muestra las primeras doce filas. Si se desplaza hacia abajo más, verá que el mapeo se realiza para todas las filas.

Aquí se muestra una salida de pantalla parcial más abajo en la base de datos para su referencia rápida.

Para comprender los datos mapeados, examinemos la primera fila.

Dice que este cliente no se ha suscrito a TD como lo indica el valor en el campo "y". También indica que este cliente es un cliente "manual". Desplazándose hacia abajo horizontalmente, le dirá que tiene una "vivienda" y no ha tomado ningún "préstamo".

Después de esta codificación en caliente, necesitamos un poco más de procesamiento de datos antes de que podamos comenzar a construir nuestro modelo.

Dejar lo "desconocido"

Si examinamos las columnas en la base de datos mapeada, encontrará la presencia de algunas columnas que terminan en "desconocido". Por ejemplo, examine la columna en el índice 12 con el siguiente comando que se muestra en la captura de pantalla:

In [14]: data.columns[12]
Out[14]: 'job_unknown'

Esto indica que se desconoce el trabajo para el cliente especificado. Obviamente, no tiene sentido incluir tales columnas en nuestro análisis y construcción de modelos. Por lo tanto, todas las columnas con el valor "desconocido" deben descartarse. Esto se hace con el siguiente comando:

In [15]: data.drop(data.columns[[12, 16, 18, 21, 24]], axis=1, inplace=True)

Asegúrese de especificar los números de columna correctos. En caso de duda, puede examinar el nombre de la columna en cualquier momento especificando su índice en el comando de columnas como se describió anteriormente.

Después de eliminar las columnas no deseadas, puede examinar la lista final de columnas como se muestra en el resultado a continuación:

In [16]: data.columns
Out[16]: Index(['y', 'job_admin.', 'job_blue-collar', 'job_entrepreneur', 
'job_housemaid', 'job_management', 'job_retired', 'job_self-employed', 
'job_services', 'job_student', 'job_technician', 'job_unemployed',
'marital_divorced', 'marital_married', 'marital_single', 'default_no', 
'default_yes', 'housing_no', 'housing_yes', 'loan_no', 'loan_yes',
'poutcome_failure', 'poutcome_nonexistent', 'poutcome_success'], 
dtype='object')

En este punto, nuestros datos están listos para la construcción de modelos.

Tenemos cuarenta y un mil y tantos registros. Si usamos todos los datos para la construcción de modelos, no nos quedarán datos para probar. Entonces, generalmente, dividimos todo el conjunto de datos en dos partes, digamos un porcentaje de 70/30. Usamos el 70% de los datos para la construcción de modelos y el resto para probar la precisión en la predicción de nuestro modelo creado. Puede utilizar una relación de división diferente según sus necesidades.

Creación de una matriz de características

Antes de dividir los datos, los separamos en dos matrices X e Y. La matriz X contiene todas las características (columnas de datos) que queremos analizar y la matriz Y es una matriz unidimensional de valores booleanos que es el resultado de la predicción. Para entender esto, ejecutemos un código.

En primer lugar, ejecute la siguiente declaración de Python para crear la matriz X:

In [17]: X = data.iloc[:,1:]

Para examinar el contenido de X utilizar headpara imprimir algunos registros iniciales. La siguiente pantalla muestra el contenido de la matriz X.

In [18]: X.head ()

La matriz tiene varias filas y 23 columnas.

A continuación, crearemos una matriz de salida que contenga "y" valores.

Crear matriz de salida

Para crear una matriz para la columna de valor predicho, use la siguiente declaración de Python:

In [19]: Y = data.iloc[:,0]

Examine su contenido llamando head. La salida de pantalla a continuación muestra el resultado:

In [20]: Y.head()
Out[20]: 0   0
1    0
2    1
3    0
4    1
Name: y, dtype: int64

Ahora, divida los datos usando el siguiente comando:

In [21]: X_train, X_test, Y_train, Y_test = train_test_split(X, Y, random_state=0)

Esto creará las cuatro matrices llamadas X_train, Y_train, X_test, and Y_test. Como antes, puede examinar el contenido de estas matrices usando el comando head. Utilizaremos las matrices X_train e Y_train para entrenar nuestro modelo y las matrices X_test e Y_test para probar y validar.

Ahora, estamos listos para construir nuestro clasificador. Lo veremos en el próximo capítulo.

No es necesario que tenga que construir el clasificador desde cero. La construcción de clasificadores es compleja y requiere el conocimiento de varias áreas como estadística, teorías de probabilidad, técnicas de optimización, etc. Hay varias bibliotecas preconstruidas disponibles en el mercado que tienen una implementación completamente probada y muy eficiente de estos clasificadores. Usaremos uno de esos modelos prediseñados delsklearn.

El clasificador sklearn

La creación del clasificador de regresión logística a partir del kit de herramientas de sklearn es trivial y se realiza en una sola declaración de programa como se muestra aquí:

In [22]: classifier = LogisticRegression(solver='lbfgs',random_state=0)

Una vez creado el clasificador, introducirá sus datos de entrenamiento en el clasificador para que pueda ajustar sus parámetros internos y esté listo para las predicciones de sus datos futuros. Para ajustar el clasificador, ejecutamos la siguiente declaración:

In [23]: classifier.fit(X_train, Y_train)

El clasificador ahora está listo para probar. El siguiente código es el resultado de la ejecución de las dos declaraciones anteriores:

Out[23]: LogisticRegression(C = 1.0, class_weight = None, dual = False, 
   fit_intercept=True, intercept_scaling=1, max_iter=100, 
   multi_class='warn', n_jobs=None, penalty='l2', random_state=0, 
   solver='lbfgs', tol=0.0001, verbose=0, warm_start=False))

Ahora, estamos listos para probar el clasificador creado. Trataremos de esto en el próximo capítulo.

Necesitamos probar el clasificador creado anteriormente antes de ponerlo en producción. Si la prueba revela que el modelo no cumple con la precisión deseada, tendremos que volver al proceso anterior, seleccionar otro conjunto de características (campos de datos), construir el modelo nuevamente y probarlo. Este será un paso iterativo hasta que el clasificador cumpla con su requisito de precisión deseada. Así que probemos nuestro clasificador.

Predicción de datos de prueba

Para probar el clasificador, utilizamos los datos de prueba generados en la etapa anterior. Llamamos alpredict método en el objeto creado y pasar el X matriz de los datos de prueba como se muestra en el siguiente comando:

In [24]: predicted_y = classifier.predict(X_test)

Esto genera una matriz unidimensional para todo el conjunto de datos de entrenamiento que proporciona la predicción para cada fila en la matriz X. Puede examinar esta matriz utilizando el siguiente comando:

In [25]: predicted_y

La siguiente es la salida tras la ejecución de los dos comandos anteriores:

Out[25]: array([0, 0, 0, ..., 0, 0, 0])

El resultado indica que los primeros y últimos tres clientes no son los candidatos potenciales para el Term Deposit. Puede examinar toda la matriz para clasificar los clientes potenciales. Para hacerlo, use el siguiente fragmento de código de Python:

In [26]: for x in range(len(predicted_y)):
   if (predicted_y[x] == 1):
      print(x, end="\t")

El resultado de ejecutar el código anterior se muestra a continuación:

La salida muestra los índices de todas las filas que son probables candidatos para suscribirse a TD. Ahora puede entregar este resultado al equipo de marketing del banco, quien recogería los datos de contacto de cada cliente en la fila seleccionada y continuaría con su trabajo.

Antes de poner este modelo en producción, debemos verificar la precisión de la predicción.

Verificación de la precisión

Para probar la precisión del modelo, utilice el método de puntuación en el clasificador como se muestra a continuación:

In [27]: print('Accuracy: {:.2f}'.format(classifier.score(X_test, Y_test)))

La salida de pantalla de ejecutar este comando se muestra a continuación:

Accuracy: 0.90

Muestra que la precisión de nuestro modelo es del 90%, lo que se considera muy bueno en la mayoría de las aplicaciones. Por lo tanto, no se requiere ningún ajuste adicional. Ahora, nuestro cliente está listo para ejecutar la próxima campaña, obtener la lista de clientes potenciales y perseguirlos para abrir el TD con una probabilidad alta de éxito.

Como ha visto en el ejemplo anterior, aplicar la regresión logística para el aprendizaje automático no es una tarea difícil. Sin embargo, tiene sus propias limitaciones. La regresión logística no podrá manejar una gran cantidad de características categóricas. En el ejemplo que hemos comentado hasta ahora, redujimos el número de funciones en gran medida.

Sin embargo, si estas características fueran importantes en nuestra predicción, nos hubiéramos visto obligados a incluirlas, pero la regresión logística no nos proporcionaría una buena precisión. La regresión logística también es vulnerable al sobreajuste. No se puede aplicar a un problema no lineal. Se desempeñará mal con variables independientes que no están correlacionadas con el objetivo y están correlacionadas entre sí. Por lo tanto, deberá evaluar cuidadosamente la idoneidad de la regresión logística para el problema que está tratando de resolver.

Hay muchas áreas del aprendizaje automático en las que se especifican otras técnicas. Para nombrar algunos, tenemos algoritmos como k vecinos más cercanos (kNN), Regresión lineal, Máquinas de vectores de soporte (SVM), Árboles de decisión, Bayes ingenuos, etc. Antes de finalizar en un modelo en particular, deberá evaluar la aplicabilidad de estas diversas técnicas al problema que estamos tratando de resolver.

La regresión logística es una técnica estadística de clasificación binaria. En este tutorial, aprendió cómo entrenar la máquina para usar la regresión logística. Al crear modelos de aprendizaje automático, el requisito más importante es la disponibilidad de los datos. Sin datos adecuados y relevantes, no puede simplemente hacer que la máquina aprenda.

Una vez que tenga los datos, su próxima tarea principal es limpiar los datos, eliminar las filas y campos no deseados y seleccionar los campos apropiados para el desarrollo de su modelo. Una vez hecho esto, debe mapear los datos en un formato requerido por el clasificador para su entrenamiento. Por lo tanto, la preparación de datos es una tarea importante en cualquier aplicación de aprendizaje automático. Una vez que esté listo con los datos, puede seleccionar un tipo particular de clasificador.

En este tutorial, aprendió a usar un clasificador de regresión logística proporcionado en el sklearnbiblioteca. Para entrenar al clasificador, usamos aproximadamente el 70% de los datos para entrenar el modelo. Usamos el resto de los datos para realizar pruebas. Probamos la precisión del modelo. Si esto no está dentro de los límites aceptables, volvemos a seleccionar el nuevo conjunto de características.

Una vez más, siga todo el proceso de preparación de datos, entrene el modelo y pruébelo hasta que esté satisfecho con su precisión. Antes de emprender cualquier proyecto de aprendizaje automático, debe aprender y estar expuesto a una amplia variedad de técnicas que se han desarrollado hasta ahora y que se han aplicado con éxito en la industria.