Regresión Polinomial – Práctica con Python
A continuación aprenderás cómo implementar el algoritmo de Regresión Polinomial utilizando la librería de Python Scikit Learn, desarrollando un proyecto de Machine Learning. Cada una de las explicaciones dadas acá será paso a paso para que puedas entender con detalle cada uno de los métodos explicados acá y que los puedas implementar en tus propios proyectos.
Empecemos con la explicación del proyecto.
Definición del proyecto
En esta práctica del algoritmo de Regresión Polinomial, se desarrollará un modelo para predecir el precio de las casas en Boston de acuerdo al número de habitaciones que cuenta la vivienda, el tiempo que ha tenido ocupada y la distancia que se encuentra la misma de los centros de trabajos de Boston, siendo varias características que se tomarán en cuenta para diseñar nuestro modelo.
Este es el mismo proyecto que desarrollamos en la práctica de Regresión Lineal, pero esta vez aplicaremos el algoritmo de Regresión Polinomial.
Para este análisis vamos a utilizar el dataset disponible en la librería scikit-learn correspondiente al Boston Housing o las casas de Boston. Si no lo sabías dentro de la librería sckit-learn se dispone de varios conjuntos de datos, muy básicos, con los que puedes practicar tus conocimientos de Machine Learning, no son muchos, pero cubre los principales tipos de algoritmos como regresión y clasificación.
El algoritmo específico que se utilizará será Regresión Polinomial.
Obtener los de datos
El primer paso que daremos será el de importar las librerías que vamos utilizar, en especial las necesarias para importar los datos que utilizaremos.
En este caso vamos a importar de sklearn el datasets, que es donde se guardan todos los conjuntos de datos que dispone esta librería y a su vez importamos de una vez linear_model.
#Se importan la librerias a utilizar
from sklearn import datasets, linear_model
Seguidamente importamos los datos, para ello utilizamos la instrucción datasets.load_boston().
#Importamos los datos de la misma librería de scikit-learn
boston = datasets.load_boston()
Tenemos mucha información dentro de esta variable lo que se nos hace difícil entender la información, por lo tanto, ahora procedemos a entender la data.
Entender los datos
Para entender los datos que estaremos utilizando el proyecto nos vamos a valor de varias instrucciones propias de Python y así verificar la información contenida en el conjunto de datos que acabamos de importar. Para este fin utilizamos la instrucción keys.
#Verifico la información contenida en el dataset
print('Información en el dataset:')
print(boston.keys())
Como puedes observar el conjunto de datos cuenta con la siguiente información: primeramente, la data, seguidamente target que sería la columna con las etiquetas o respuestas, posteriormente tenemos feature_names que serían los nombres de cada una de las columnas de la data y finalmente tenemos DESCR que sería la descripción total del dataset.
Sabiendo ya esto podemos ahora utilizar estos nombres para entender mejor los datos, lo primero que vamos a hacer es utilizar DESCR para ver las características del dataset.
#Verifico las características del dataset
print('Características del dataset:')
print(boston.DESCR)
Como puedes leer en la descripción este dataset cuenta con 506 datos y 13 atributos, la columna 14 es el target y es la media del valor de las viviendas.
Seguidamente tenemos la descripción del significado de cada una de las columnas o atributos de los datos. De igual forma, nos indica un dato importante para nuestro análisis y es que indica que no existe ningún valor perdido, en consecuencia, nuestros datos están completos por lo que no es necesario realizar mucho preprocesamiento a los datos.
Ahora utilizaremos la instrucción shape para determinar la cantidad de datos contamos, aunque este es un paso de más ya que esta información nos la había dado previamente la descripción del dataset, pero de todas formas lo hacemos.
#Verifico la cantidad de datos que hay en los dataset
print('Cantidad de datos:')
print(boston.data.shape)
#Verifico la información de las columnas
print('Nombres columnas:')
print(boston.feature_names)
Procesamiento de los datos
Para este ejemplo vamos a implementar un predictor de Regresión Polinomial. Los datos que se utilizarán para el análisis serán los correspondientes al número de habitaciones que cuenta la vivienda, estos datos se encuentran ubicados en la columna número 6 de nuestro dataset, por lo que debemos definir esta columna a la variable “X”, en este caso vamos a utilizar “X_p” para representar el algoritmo que estamos utilizando, Regresión Polinomial.
#Seleccionamos solamente la columna 6 del dataset
X_p = boston.data[:, np.newaxis, 5]
Seguidamente definimos los datos de “y” o “y_p”, para este ejemplo, los cuales serán igual a la columna de target de nuestro dataset.
#Definimos los datos correspondientes a las etiquetas
y_p = boston.target
Definidas ambas variables podemos graficarlas utilizando la instrucción scatter. Como podemos observar los datos no se encuentran distribuidos de manera lineal sobre en la parte inferior izquierda por lo que perfectamente podemos utilizar el algoritmo de Regresión Polinomial.
#Graficamos los datos correspondientes
plt.scatter(X_p, y_p)
plt.show()
Ahora separamos los datos de entrenamiento y prueba, para ello importamos train_test_split de la librería scikit learn y lo implementamos a nuestros datos “X_p” y “y_p”.
from sklearn.model_selection import train_test_split
#Separo los datos de "train" en entrenamiento y prueba para probar los algoritmos
X_train_p, X_test_p, y_train_p, y_test_p = train_test_split(X_p, y_p, test_size=0.2)
En este punto tenemos los datos “X” y “y” de entrenamiento y prueba.
Desarrollo del algoritmo
Con los datos separados en entrenamiento y prueba ha llegado el momento de construir el modelo de Machine Learning, pero antes de definir el algoritmo y empezar a entrenarlo debemos definir el grado del polinomio, para ello se importa de la librería scikit learn las características polinomiales o PolynomialFeatures, y procedemos a definir el grado.
from sklearn.preprocessing import PolynomialFeatures
En este caso lo definimos igual a 2. Recuerda que en este punto tu puedes definir este número, lo ideal es comenzar con un valor bajo como el 2 y después ir subiendo poco a poco para ver si se mejora lo resultados de la predicción, pero debes tener mucho cuidado porque en ocasiones puedes ajustar de más el modelo ocasionando un sobreajuste u overfitting.
#Se define el grado del polinomio
poli_reg = PolynomialFeatures(degree = 2)
Definido el grado se procede a transformar las características de existentes, en este caso tanto X_train como X_test en características de mayor grado, para ello utilizamos el polinomio definido anteriormente y lo entrenamos a estos datos.
#Se transforma las características existentes en características de mayor grado
X_train_poli = poli_reg.fit_transform(X_train_p)
X_test_poli = poli_reg.fit_transform(X_test_p)
En este punto lo que estamos haciendo es calculando los valores de “X” para cada uno de los elementos dentro de la fórmula, te acuerdas que en la teoría vimos que “X” estaba elevado a la n potencia dependiendo del valor del coeficiente del polinomio, bueno es acá donde se calcula el valor de “X”.
Cómo seleccionamos un polinomio de grado 2, entonces tenemos la fórmula sería esta:
Entonces acá estamos calculando los datos de y , para tenerlos listo para calcular el modelo. Esto lo hacemos tanto para X_train como para X_test.
Realizado esto llegó el momento de definir el algoritmo en nuestro modelo, que en este caso sería LinearRegression, con esta misma instrucción se puede calcular el modelo de Regresión Polinomial.
#Definimos el algoritmo a utilizar
pr = linear_model.LinearRegression()
Definido el algoritmo lo utilizamos para entrenar los datos, recuerda que acá utilizamos los datos que transformamos con las características de mayor grado.
#Entrenamos el modelo
pr.fit(X_train_poli, y_train_p)
Realizado todo esto comparemos los valores obtenidos en nuestra predicción con los valores reales, para ver que tal es el comportamiento de nuestro modelo.
#Realizamos una predicción
Y_pred_pr = pr.predict(X_test_poli)
Análisis de los resultados
Como puedes observar en el recuadro anterior tenemos los datos reales mientras que en este otro están los datos obtenidos de nuestra predicción implementando el modelo. Si observamos con detenimiento estos datos nos podemos dar cuenta que en ciertos momentos los datos reales son muy parecidos con los datos que se han calculados mientras que otros casos los datos son totalmente distintos.
Con esta pequeña comparación podemos determinar que nuestro modelo no es del todo eficiente, pero veámoslo gráficamente para detallar con más cuidado, para ello utilizamos la librería de matplotlib.
#Graficamos los datos junto con el modelo
plt.scatter(X_test_p, y_test_p)
plt.plot(X_test_p, Y_pred_pr, color='red', linewidth=3)
plt.show()
Como podemos observar en la gráfica, la línea roja sería nuestro modelo y los puntos azules son los datos de pruebas con los que lo entrenamos.
Igual que todos los algoritmos de regresión que hemos desarrollado hasta ahora el objetivo de este es que el modelo o la línea abarque el mayor número de muestras y de esta forma disminuir el error que vendría siendo la distancia desde la línea hasta el punto, entonces todos los datos fuera de la línea serían errores.
Recordando este concepto podemos observar que el modelo cubre una buena parte de los datos y tiene un comportamiento correcto muy parecido al de los datos. Por lo tanto, calculemos los datos relacionados a este algoritmo incluyendo la precisión del mismo.
print('Valor de la pendiente o coeficiente "a":')
print(pr.coef_)
print('Valor de la intersección o coeficiente "b":')
print(pr.intercept_)
print('Precisión del modelo:')
print(pr.score(X_train_poli, y_train_p))
Ahora calculemos la precisión del algoritmo para ello empleamos la instrucción “score” el cual devuelve el resultado de la estadística R al cuadrado. El resultado obtenido acá es de 0,563, como ya lo habíamos visto comparando los resultados de “y_predict” y viendo la gráfica podíamos deducir que la precisión no iba a ser muy buena.
Conclusiones
Recuerda que esto no significa que el algoritmo sea malo sino que no es el mejor para este conjunto de datos.
Por todo esto es que es bueno saber exactamente de qué se trata cada uno de los algoritmos de Machine Learning, para que de una vez que veamos los datos puedas deducir qué algoritmo es el más adecuado implementar y de esta forma no perder tiempo en el desarrollo de algoritmos que no vayan a funcionar.
Programa completo
A continuación se encuentra el código completo:
"""
Regresión Polinomial
"""
########## LIBRERÍAS A UTILIZAR ##########
#Se importan la librerias a utilizar
import numpy as np
from sklearn import datasets, linear_model
import matplotlib.pyplot as plt
########## PREPARAR LA DATA ##########
#Importamos los datos de la misma librería de scikit-learn
boston = datasets.load_boston()
print(boston)
print()
########## ENTENDIMIENTO DE LA DATA ##########
#Verifico la información contenida en el dataset
print('Información en el dataset:')
print(boston.keys())
print()
#Verifico las características del dataset
print('Características del dataset:')
print(boston.DESCR)
#Verifico la cantidad de datos que hay en los dataset
print('Cantidad de datos:')
print(boston.data.shape)
print()
#Verifico la información de las columnas
print('Nombres columnas:')
print(boston.feature_names)
########## PREPARAR LA DATA REGRESIÓN POLINOMIAL ##########
#Seleccionamos solamente la columna 6 del dataset
X_p = boston.data[:, np.newaxis, 5]
#Defino los datos correspondientes a las etiquetas
y_p = boston.target
#Graficamos los datos correspondientes
plt.scatter(X_p, y_p)
plt.show()
########## IMPLEMENTACIÓN DE REGRESIÓN POLINOMIAL ##########
from sklearn.model_selection import train_test_split
#Separo los datos de "train" en entrenamiento y prueba para probar los algoritmos
X_train_p, X_test_p, y_train_p, y_test_p = train_test_split(X_p, y_p, test_size=0.2)
from sklearn.preprocessing import PolynomialFeatures
#Se define el grado del polinomio
poli_reg = PolynomialFeatures(degree = 2)
#Se transforma las características existentes en características de mayor grado
X_train_poli = poli_reg.fit_transform(X_train_p)
X_test_poli = poli_reg.fit_transform(X_test_p)
#Defino el algoritmo a utilizar
pr = linear_model.LinearRegression()
#Entreno el modelo
pr.fit(X_train_poli, y_train_p)
#Realizo una predicción
Y_pred_pr = pr.predict(X_test_poli)
#Graficamos los datos junto con el modelo
plt.scatter(X_test_p, y_test_p)
plt.plot(X_test_p, Y_pred_pr, color='red', linewidth=3)
plt.show()
print()
print('DATOS DEL MODELO REGRESIÓN POLINOMIAL')
print()
print('Valor de la pendiente o coeficiente "a":')
print(pr.coef_)
print('Valor de la intersección o coeficiente "b":')
print(pr.intercept_)
print('Precisión del modelo:')
print(pr.score(X_train_poli, y_train_p))
el algoritmo puede hacerse con mas de una variable independiente?
Si, puede utilizarse con más de una variable independiente.
Podrías poner un ejemplo de regresión polinomial con varias variables independientes?
Hola Jesús, gracias por la sugerencia. Pero tu puedes hacerlo por tu cuenta también con este proyecto, cuando definas X en vez de solo seleccionar una sola columna puedes seleccionar varias y de esta forma ya tendrás varias variables independientes. Saludos.
Hola!
Quedé un poco colgado en una parte del código. En la línea 44, X_p = boston.data[:, np.newaxis, 5], por qué usas «np.newaxis»? ¿Para que X_p sea un vector columna?
Gracias!
Hola Gerson, así es. Saludos.
Hola!
Primero de todo felicitarte por este blog, esta muy bien explicado todo.
Luego tengo una duda, hay alguna manera (función del scikit o asi) de saber el grado optimo para tu predecir tus datos?
Gracias de antenamo.
Hola Enrique, muchas gracias por tu comentario. La única forma para saber el grado óptimo es probando, no hay ninguna función en Python que te recomiende un valor. Saludos.
Hola Ligdi,
Gracias por este blog. Como siempre excelente!!
Solo tengo una duda. Me podrías orientar- A medida que agrego más variables al modelo (antigüedad y distancia por ejemplo) noto que la gráfica que se dibuja muestra casi todos los datos a la izquierda. Esto se debe a que no he corregido el código para mostrar un gráfico en 3 dimensiones? Saludos
Hola Ricardo, recuerda que todas las variables no influyen en la variable dependiente y en ocasiones incluirla en el análisis puede ocasionar resultados erróneos, de repente esto sea lo que estás viendo. Saludos.
Hola!
Gracias por generar este código y ayudame a entender un poco mejor. Tengo una duda la cual me pregunto si puedes ayudarme, estoy tratando de generar el mismo código el cual tu desarrollaste pero en lugar de importar los datos yo tengo una lista con los valores de x y otra lista con los valores de y. El problema es que cuando trato de que me grafique la curva ajustada me dice que:
ValueError: Expected 2D array, got 1D array instead:
array=[269 183 345 234 424 423 347 344 294 168 228 241 197 316 361 313 409 213
153 328 267 411 184 244].
Reshape your data either using array.reshape(-1, 1) if your data has a single feature or array.reshape(1, -1) if it contains a single sample.
Y realmente no entediendo muy bien, soy nueva en esto y no entiendo qye me trata de decir con respecto a que necesita un arreglo en 2D y que lo tengo que dar un re ajuse a la lista. ¿Cómo prodría solucionarlo?
Hola Sheccid, para realizar una gráfica necesitas dos columnas (x,y) según el error que te esta dando, estas proporcionando datos de una dimensión 1D, por lo que solamente tendrías x, por lo que te falta la parte de y. Saludos.