Regresión Lineal con Python
¿Qué es la regresión lineal?
La regresión lineal es un algoritmo de aprendizaje supervisado que se utiliza en
Machine Learning y en estadística. En su versión más sencilla, lo que haremos es
“dibujar una recta” que nos indicará la tendencia de un conjunto de datos continuos (si
fueran discretos, utilizaríamos Regresión Logística).
En estadísticas, regresión lineal es una aproximación para modelar la relación entre una
variable escalar dependiente “y” y una o mas variables explicativas nombradas con “X”.
Recordemos rápidamente la fórmula de la recta:
Y = mX + b
Donde Y es el resultado, X es la variable, m la pendiente (o coe�ciente) de la recta y b
la constante o también conocida como el “punto de corte con el eje Y” en la grá�ca
(cuando X=0)
Aqui vemos un ejemplo donde vemos datos recabados sobre los precios de las pizzas en Dinamarca
(los puntos en rojo) y la linea negra es la tendencia. Esa es la línea de regresión que buscamos que el
algoritmo aprenda y calcule sólo.
¿Cómo funciona el algoritmo de regresión
lineal en Machine Learning?
Recordemos que los algoritmos de Machine Learning Supervisados, aprenden por sí
mismos y -en este caso- a obtener automáticamente esa “recta” que buscamos con la
tendencia de predicción. Para hacerlo se mide el error con respecto a los puntos de
entrada y el valor “Y” de salida real. El algoritmo deberá minimizar el coste de una
función de error cuadrático y esos coe�cientes corresponderán con la recta óptima.
Hay diversos métodos para conseguir minimizar el coste. Lo más común es utilizar
una versión vectorial y la llamada Ecuación Normal que nos dará un resultado
directo.
NOTA: cuando hablo de “recta” es en el caso particular de regresión lineal simple. Si hubiera más variables, hay que
generalizar el término.
Hagamos un Ejercicio Práctico
En este ejemplo cargaremos un archivo .csv de entrada obtenido por webscraping
que contiene diversas URLs a artículos sobre Machine Learning de algunos sitios muy
importantes como Techcrunch o KDnuggets y como características de entrada -las
columnas- tendremos:
• : Titulo del Artículo
• : ruta al artículo
• : la cantidad de palabras del artículo,
• : los enlaces externos que contiene,
• : cantidad de comentarios,
• : suma de imágenes (o videos),
• : la cantidad de días transcurridos (al momento de crear el
archivo)
• : nuestra columna de salida que será la “cantidad de veces que se
compartió el artículo”.
A partir de las características de un artículo de machine learning intentaremos predecir,
cuantas veces será compartido en Redes Sociales.
Haremos una primer predicción de regresión lineal simple -con una sola variable
predictora- para poder gra�car en 2 dimensiones (ejes X e Y) y luego un ejemplo
de , en la que utilizaremos 3 dimensiones (X,Y,Z) y
predicciones.
NOTA: el archivo .csv contiene mitad de datos reales, y otra mitad los generé de manera aleatoria, por lo que las
predicciones que obtendremos no serán reales. Intentaré en el futuro hacer webscrapping de los enlaces que me
faltaban y reemplazar los resultados por valores reales.
Requerimientos para hacer el Ejercicio
Para realizar este ejercicio, crearemos una Jupyter notebook con código Python y la
librería SkLearn muy utilizada en Data Science. Recomendamos utilizar la suite de
Anaconda. Puedes leer este artículo donde muestro paso a paso como instalar el
ambiente de desarrollo. Podrás descargar los archivos de entrada csv o visualizar la
notebook online (al �nal del artículo los enlaces).
Predecir cuántas veces será
compartido un artículo de Machine
Learning.
Regresión lineal simple en Python (con 1
variable)
Aqui vamos con nuestra notebook!
Comencemos por importar las librerías que utilizaremos:
1 # Imports necesarios
2 import numpy as np
3 import pandas as pd
4 import seaborn as sb
5 import [Link] as plt
6 %matplotlib inline
7 from mpl_toolkits.mplot3d import Axes3D
8 from matplotlib import cm
9 [Link]['[Link]'] = (16, 9)
10 [Link]('ggplot')
11 from sklearn import linear_model
12 from [Link] import mean_squared_error, r2_score
Leemos el archivo csv y lo cargamos como un dataset de Pandas. Y vemos su tamaño
1 #cargamos los datos de entrada
2 data = pd.read_csv("./articulos_ml.csv")
3 #veamos cuantas dimensiones y registros contiene
4 [Link]
Nos devuelve (161,8)
Veamos esas primeras �las:
1 #son 161 registros con 8 columnas. Veamos los primeros registros
2 [Link]()
Se ven algunos campos con valores NaN (nulos) por ejemplo algunas urls o en
comentarios.
Veamos algunas estadísticas básicas de nuestros datos de entrada:
1 # Ahora veamos algunas estadísticas de nuestros datos
2 [Link]()
Aqui vemos que la media de palabras en los artículos es de 1808. El artículo más
corto tiene 250 palabras y el más extenso 8401. Intentaremos ver con nuestra
relación lineal, si hay una correlación entre la cantidad de palabras del texto y la
cantidad de Shares obtenidos.
Hacemos una visualización en general de los datos de entrada:
1 # Visualizamos rápidamente las caraterísticas de entrada
2 [Link](['Title','url', 'Elapsed days'],1).hist()
3 [Link]()
En estas grá�cas vemos entre qué valores se concentran la mayoría de registros.
Vamos a �ltrar los datos de cantidad de palabras para quedarnos con los registros
con menos de 3500 palabras y también con los que tengan Cantidad de compartidos
menos a 80.000. Lo grati�caremos pintando en azul los puntos con menos de 1808
palabras (la media) y en naranja los que tengan más.
1 # Vamos a RECORTAR los datos en la zona donde se concentran más los puntos
2 # esto es en el eje X: entre 0 y 3.500
3 # y en el eje Y: entre 0 y 80.000
4 filtered_data = data[(data['Word count'] <= 3500) & (data['# Shares'] <= 80000)]
5
6 colores=['orange','blue']
7 tamanios=[30,60]
8
9 f1 = filtered_data['Word count'].values
10 f2 = filtered_data['# Shares'].values
11
12 # Vamos a pintar en colores los puntos por debajo y por encima de la media de Cantidad de Palabras
13 asignar=[]
14 for index, row in filtered_data.iterrows():
15 if(row['Word count']>1808):
16 [Link](colores[0])
17 else:
18 [Link](colores[1])
19
20 [Link](f1, f2, c=asignar, s=tamanios[0])
21 [Link]()
Regresión Lineal con Python y SKLearn
Vamos a crear nuestros datos de entrada por el momento sólo Word Count y como
etiquetas los # Shares. Creamos el objeto LinearRegression y lo hacemos “encajar”
(entrenar) con el método �t(). Finalmente imprimimos los coe�cientes y puntajes
obtenidos.
1 # Asignamos nuestra variable de entrada X para entrenamiento y las etiquetas Y.
2 dataX =filtered_data[["Word count"]]
3 X_train = [Link](dataX)
4 y_train = filtered_data['# Shares'].values
5
6 # Creamos el objeto de Regresión Linear
7 regr = linear_model.LinearRegression()
8
Ejemplo Regresión Lineal Python | Aprende Machine Learning [Link]
9 # Entrenamos nuestro modelo
10 [Link](X_train, y_train)
11
12 # Hacemos las predicciones que en definitiva una línea (en este caso, al ser 2D)
13 y_pred = [Link](X_train)
14
15 # Veamos los coeficienetes obtenidos, En nuestro caso, serán la Tangente
16 print('Coefficients: \n', regr.coef_)
17 # Este es el valor donde corta el eje Y (en X=0)
18 print('Independent term: \n', regr.intercept_)
19 # Error Cuadrado Medio
20 print("Mean squared error: %.2f" % mean_squared_error(y_train, y_pred))
21 # Puntaje de Varianza. El mejor puntaje es un 1.0
22 print('Variance score: %.2f' % r2_score(y_train, y_pred))
<
Coefficients: [5.69765366]
Independent term: 11200.303223074163
Mean squared error: 372888728.34
Variance score: 0.06
De la ecuación de la recta y = mX + b nuestra pendiente “m” es el coe�ciente 5,69 y el
término independiente “b” es 11200. Tenemos un Error Cuadrático medio enorme…
por lo que en realidad este modelo no será muy bueno Pero estamos
aprendiendo a usarlo, que es lo que nos importa ahora Esto también se ve
re�ejado en el puntaje de Varianza que debería ser cercano a 1.0.
Visualicemos la Recta
Veamos la recta que obtuvimos:
Predicción en regresión lineal simple
Vamos a intentar probar nuestro algoritmo, suponiendo que quisiéramos predecir
cuántos “compartir” obtendrá un articulo sobre ML de 2000 palabras
1 #Vamos a comprobar:
2 # Quiero predecir cuántos "Shares" voy a obtener por un artículo con 2.000 palabras,
3 # según nuestro modelo, hacemos:
4 y_Dosmil = [Link]([[2000]])
5 print(int(y_Dosmil))
Nos devuelve una predicción de 22595 “Shares” para un artículo de 2000 palabras (
ojalá fuera posible!!!).
Regresión Lineal Múltiple en Python
(o “Regresión con Múltiples Variables”)
Vamos a extender el ejercicio utilizando más de una variable de entrada para el
modelo. Esto le da al algoritmo de Machine Learning, pues de esta
manera podremos obtener predicciones más complejas.
Nuestra “ecuación de la Recta”, ahora pasa a ser:
Y = b + m1 X1 + m2 X2 + … + m(n) X(n)
y deja de ser una recta)
, pero recordar que para mejores predicciones podemos utilizar más de 2 entradas y
prescindir del gra�co.
Nuestra primer variable seguirá siendo la y la segunda variable
será : la cantidad de enlaces, comentarios y
cantidad de imágenes. Vamos a programar!
1 #Vamos a intentar mejorar el Modelo, con una dimensión más:
2 # Para poder graficar en 3D, haremos una variable nueva que será la suma de los enlaces, comentarios e i
3 suma = (filtered_data["# of Links"] + filtered_data['# of comments'].fillna(0) + filtered_data['# Images
4
5 dataX2 = [Link]()
6 dataX2["Word count"] = filtered_data["Word count"]
7 dataX2["suma"] = suma
8 XY_train = [Link](dataX2)
9 z_train = filtered_data['# Shares'].values
Nota: hubiera sido mejor aplicar PCA para reducción de
dimensiones, manteniendo la información más importante de
todas , pero eso lo veremos en otros cortes :v
Ya tenemos nuestras 2 variables de entrada en XY_train y
.
Creamos un nuevo objeto de Regresión lineal con SKLearn pero esta vez tendrá las
dos dimensiones que entrenar: las que contiene XY_train. Al igual que antes,
imprimimos los coe�cientes y puntajes obtenidos:
1 # Creamos un nuevo objeto de Regresión Lineal
2 regr2 = linear_model.LinearRegression()
3
4 # Entrenamos el modelo, esta vez, con 2 dimensiones
5 # obtendremos 2 coeficientes, para graficar un plano
6 [Link](XY_train, z_train)
7
8 # Hacemos la predicción con la que tendremos puntos sobre el plano hallado
9 z_pred = [Link](XY_train)
10
11 # Los coeficientes
12 print('Coefficients: \n', regr2.coef_)
13 # Error cuadrático medio
14 print("Mean squared error: %.2f" % mean_squared_error(z_train, z_pred))
15 # Evaluamos el puntaje de varianza (siendo 1.0 el mejor posible)
16 print('Variance score: %.2f' % r2_score(z_train, z_pred))
<
p style=”padding-left: 30px;”>Coefficients: [ 6.63216324 -483.40753769]
Mean squared error: 352122816.48
Variance score: 0.11
Como vemos, obtenemos 2 coe�cientes (cada uno correspondiente a nuestras 2
variables predictivas), pues ahora lo que gra�camos no será una linea si no,
.
El error obtenido sigue siendo grande, aunque algo mejor que el anterior y el puntaje
de Varianza mejora casi el doble del anterior (aunque sigue siendo muy malo, muy
lejos del 1).
Visualizar un plano en 3 Dimensiones en
Python
Gra�caremos nuestros puntos de las características de entrada en color azul y los
puntos proyectados en el plano en rojo. Recordemos que en esta grá�ca, el eje Z
corresponde a la “altura” y representa la cantidad de Shares que obtendremos.
1 fig = [Link]()
2 ax = Axes3D(fig)
3
4 # Creamos una malla, sobre la cual graficaremos el plano
5 xx, yy = [Link]([Link](0, 3500, num=10), [Link](0, 60, num=10))
6
7 # calculamos los valores del plano para los puntos x e y
8 nuevoX = (regr2.coef_[0] * xx)
9 nuevoY = (regr2.coef_[1] * yy)
10
11 # calculamos los correspondientes valores para z. Debemos sumar el punto de intercepción
12 z = (nuevoX + nuevoY + regr2.intercept_)
13
14 # Graficamos el plano
15 ax.plot_surface(xx, yy, z, alpha=0.2, cmap='hot')
16
17 # Graficamos en azul los puntos en 3D
18 [Link](XY_train[:, 0], XY_train[:, 1], z_train, c='blue',s=30)
19
20 # Graficamos en rojo, los puntos que
21 [Link](XY_train[:, 0], XY_train[:, 1], z_pred, c='red',s=40)
22
23 # con esto situamos la "camara" con la que visualizamos
24 ax.view_init(elev=30., azim=65)
25
26 ax.set_xlabel('Cantidad de Palabras')
27 ax.set_ylabel('Cantidad de Enlaces,Comentarios e Imagenes')
28 ax.set_zlabel('Compartido en Redes')
29 ax.set_title('Regresión Lineal con Múltiples Variables')
Podemos rotar el grá�co para apreciar el plano desde diversos ángulos modi�cando
el valor del parámetro en view_init con números de 0 a 360.
Predicción con el modelo de Mútiples
Variables
Veamos ahora, que predicción tendremos para un artículo de 2000 palabras, con 10
enlaces, 4 comentarios y 6 imágenes.
1 # Si quiero predecir cuántos "Shares" voy a obtener por un artículo con:
2 # 2000 palabras y con enlaces: 10, comentarios: 4, imagenes: 6
3 # según nuestro modelo, hacemos:
4
5 z_Dosmil = [Link]([[2000, 10+4+6]])
6 print(int(z_Dosmil))
Esta predicción nos da 20518 y probablemente sea un poco mejor que nuestra
predicción anterior con 1 variables.
Conclusion y Mejora de nuestro modelo
Hemos visto cómo utilizar SKLearn en Python para crear modelos de Regresión Lineal
con 1 o múltiples variables. En nuestro ejercicio no tuvimos una gran con�anza en las
predicciónes. Por ejemplo en nuestro primer modelo, con 2000 palabras nos predice
que podemos tener 22595 pero el margen de error haciendo raíz del error cuartico
medio es más menos 19310. Es decir que escribiendo un artículo de 2000 palabras lo
mismo tenemos 3285 Shares que 41905. En este caso usamos este modelo para
aprender a usarlo y habrá que ver en otros casos en los que sí nos brinde
predicciones acertadas.
Para mejorar nuestro modelo, deberíamos utilizar más dimensiones y encontrar
datos de entrada mejores. : también es posible, que no exista ninguna
relación nunca entre nuestras variables de entrada y el éxito en Shares del artículo…
con lo cual… nunca podremos predecir con certeza esta salida. Esto fue un
experimento!