Herramientas de usuario

Herramientas del sitio


clase:ia:saa:1eval:sml_regresion

07 - SML: Regresión

Datos:

import numpy as np
import matplotlib.pyplot as plt

X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)

Distribución:

fig, axes = plt.subplots(figsize=(9,6))
axes = fig.add_subplot()
plt.axis([0 ,2, 0, 14])
axes.scatter(X,y)

Entrenar el model: método fit() de la librería sklearn

from sklearn.linear_model import LinearRegression

model = LinearRegression()
model.fit(X, y)

print('Constante: ', model.intercept_)
print('Pendiente:', model.coef_)

Constante:  [4.6263185]
Pendiente: [[2.46782729]]

Predicciones: método predict()

y_predict = model.predict(X)

fig, axes = plt.subplots(figsize=(9,6))
axes = fig.add_subplot()
plt.axis([0 ,2, 0, 14])
axes.plot(X, y_predict, color="r")
axes.scatter(X,y)

Predicciones para nuevos valores:

new_values = [[1.95], [1.23], [2.34]]

new_predicts = model.predict(new_values)

print(new_predicts)

[[ 9.43858173]
 [ 7.66174608]
 [10.40103437]]

Separar entrenamiento y test

import pandas as pd

from sklearn.datasets import load_iris

iris = load_iris()

data=pd.DataFrame({
    'sepal length':iris.data[:,0],
    'sepal width':iris.data[:,1],
    'petal length':iris.data[:,2],
    'petal width':iris.data[:,3],
    'species':iris.target
})
data.head()

	sepal length	sepal width	petal length	petal width	species
0	         5.1	        3.5	         1.4	        0.2	      0
1	         4.9	        3.0	         1.4	        0.2	      0
2	         4.7	        3.2	         1.3	        0.2	      0
3	         4.6	        3.1	         1.5	        0.2	      0
4	         5.0	        3.6	         1.4	        0.2	      0

data.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150 entries, 0 to 149
Data columns (total 5 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   sepal length  150 non-null    float64
 1   sepal width   150 non-null    float64
 2   petal length  150 non-null    float64
 3   petal width   150 non-null    float64
 4   species       150 non-null    int64  
dtypes: float64(4), int64(1)
memory usage: 6.0 KB

Separar labels

X = data[['sepal length', 'sepal width', 'petal length', 'petal width']]  
y = data['species']

	sepal length	sepal width	petal length	petal width
0	         5.1	        3.5	         1.4	        0.2
1	         4.9	        3.0	         1.4	        0.2
2	         4.7	        3.2	         1.3	        0.2
3	         4.6	        3.1	         1.5	        0.2
4	         5.0	        3.6	         1.4	        0.2

y.head()

0    0
1    0
2    0
3    0
4    0
Name: species, dtype: int64

Separar datos entrenamiento/test

print(data['species'].unique())
X_train = data[0:100]
print(X_train['species'].unique())

[0 1 2]
[0 1]

El dataset Iris tiene 150 datos de flores de 3 especies. El problema es que están ordenados por especie (50 primeros datos de la especie 1, 50 siguientes de la especie 2 y los últimos 50 de la especie 3). Si cogemos los 100 primeros datos como entrenamiento, nuestro modelo sólo verá las 2 primeras especies.

Al separar los datos, tenemos que asegurarnos que las muestras sean representativas.

Podemos utilizar el método train_test_split() de la librería sklearn:

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
print(y_train.unique())

[0 2 1]

X_train.head()


        sepal length	sepal width	petal length	petal width
28	         5.2	        3.4	         1.4	        0.2
6	         4.6	        3.4	         1.4	        0.3
59	         5.2	        2.7	         3.9	        1.4
57	         4.9	        2.4	         3.3	        1.0
135	         7.7	        3.0	         6.1	        2.3

Métricas

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(99)

X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)

fig, axes = plt.subplots(figsize=(9,6))
axes = fig.add_subplot()
plt.axis([0 ,2, 0, 14])
axes.scatter(X,y)

from sklearn.linear_model import LinearRegression

model = LinearRegression()
model.fit(X, y)

y_predict = model.predict(X)

fig, axes = plt.subplots(figsize=(9,6))
axes = fig.add_subplot()
plt.axis([0 ,2, 0, 14])
axes.plot(X, y_predict, color="r")
axes.scatter(X,y)

Métricas con sklearn

from sklearn import metrics

MAE = metrics.mean_absolute_error(y, y_predict)
MSE = metrics.mean_squared_error(y, y_predict)
RMSE = metrics.mean_squared_error(y, y_predict, squared=False)
R = metrics.r2_score(y, y_predict)

print("MAE:", MAE)
print("MSE:", MSE)
print("RMSE:", RMSE)
print("R:", R)

MAE: 0.7393683940499426
MSE: 0.8449242930864277
RMSE: 0.9191976354878355
R: 0.7143641795373913

Gráficos de residuos

# Gráficos de residuos 1

residuos = y - y_predict

fig, axes = plt.subplots(figsize=(15,6))
axes = fig.add_subplot()
plt.axis([0 ,2, -4, 4])
axes.axhline(y = 0, linestyle = '--', color = 'red', lw=2)
axes.scatter(X, residuos)
axes.set_title('Residuos del modelo', fontsize = 10, fontweight = "bold")
axes.set_xlabel('X')
axes.set_ylabel('Residuo')

plt.show()

# Gráficos de residuos 2

fig, axes = plt.subplots(figsize=(15,6))
axes = fig.add_subplot()
plt.axis([y.min(),y.max(), y_predict.min(), y_predict.max()])
axes.plot([y.min(), y.max()], [y_predict.min(), y_predict.max()],linestyle = '--', color = 'red', lw=2)
axes.scatter(y, y_predict)
axes.set_title('Predicción vs Real', fontsize = 10, fontweight = "bold")
axes.set_xlabel('Real')
axes.set_ylabel('Predicción')

plt.show()

Regresión polinomial

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression

Creamos los datos con y = -100 - 5x + 5 x² + 0.1 x³ + ruido

def true_fun(X):
    return -100 - 5 * X + 5 * np.power(X, 2) + 0.1 * np.power(X, 3)

np.random.seed(0)

n_samples = 100

X_np = np.random.uniform(-50,50, n_samples)
y_np = true_fun(X_np) + np.random.randn(n_samples) * 1000

Creamos un dataframe de pandas para poder separar datos de entrenamiento/test de forma sencilla:

df = pd.DataFrame({'X':X_np, 'y':y_np})
df.head()

	X	        y
0	4.881350	-1158.787607
1	21.518937	4005.020826
2	10.276338	950.817651
3	4.488318	-1548.918554
4	-7.634520	1673.355793

Distribución:

fig, axes = plt.subplots(figsize=(9,6))
axes = fig.add_subplot()
axes.scatter(df.X,df.y)

Separamos los datos:

X = df[['X']]
y = df[['y']]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

Distribución de los datos de entrenamiento:

Para implementar regresión polinomial usamos la función PolynomialFeatures() de la librería sklearn.

from sklearn.preprocessing import PolynomialFeatures

pf = PolynomialFeatures(degree = 3)    # usaremos polinomios de grado 3
X_train_poly = pf.fit_transform(X_train)  # transformamos la entrada en polinómica
# instruimos a la regresión lineal que aprenda de los datos (ahora polinómicos)
model2 = LinearRegression()
model2.fit(X_train_poly, y_train) 

print('w = ' + str(model2.coef_) + ', b = ' + str(model2.intercept_))
y_train_predict = model2.predict(X_train_poly)

w = [[  0.         -13.77472612   4.82789218   0.1051025 ]], b = [330.46146111]

El modelo ajusta la línea de regresión con:

y = 330.46 - 13.78x + 4.82x² + 0.1x³

# Ordenamos los datos para que la línea del gŕafico nos salga bien
lists = sorted(zip(*[X_train.values, y_train_predict]))
new_x, new_y = list(zip(*lists))

fig, axes = plt.subplots(figsize=(9,6))
axes = fig.add_subplot()
axes.plot(new_x, new_y, color="r")
axes.scatter(X_train, y_train)

Ejercicios

Ejercicio 1

heights.zip

Con el dataset anterior (altura de padres e hijos):

  • Crear un dataframe de Pandas con la información del dataset
  • Mostrar la información del dataset y el gráfico que relacione ambos datos
  • Separar el dataframe en 4 grupos: característica de entrenamiento (altura de los padres), característica de test (30% de las filas), etiqueta de entrenamiento (altura de los hijos), etiqueta de test
  • Mostrar el número de registros de cada grupo (entrenamiento y test)
  • Entrenar un modelo de regresión lineal con sklearn y mostrar los coeficientes (constante y pendiente)
  • Mostrar un gráfico con los puntos y la recta de regresión
  • Mostrar las métricas de los datos de entrenamiento
  • Calcular las predicciones de los datos de test y mostrar los valores de las diferentes métricas

Ejercicio 2

ejercicio41.zip

Con el dataset anterior:

  • Muestra un gráfico con la distribución de los datos
  • Separa los datos en entrenamiento/test
  • Muestra un gráfico con los datos de entrenamiento para asegurarte que sigue la misma distribución que los datos completos
  • Intenta ajustar la línea de regresión a los datos. Prueba con 1, 4, 10, 20, 30 y 50 grados de la ecuación. Muestra el MSE de cada una de ellas y un gráfico donde se muestre la distribución de los datos y la línea de regresión calculada
clase/ia/saa/1eval/sml_regresion.txt · Última modificación: 2023/11/06 13:09 por cesguiro