La regressió lineal és un mètode estadístic que intenta modelar
la relació entre un conjunt de variables independents \(X\) (característiques o features)
i una variable dependent \(Y\) (objectiu o target) mitjançant una funció lineal.
Quan només hi ha una variable independent, es parla de regressió lineal simple.
En canvi, quan hi ha més d'una variable independent, es parla de regressió lineal múltiple.
Aquest model lineal es pot expressar com:
\[
Y = w_0 + w_1X_1 + w_2X_2 + \ldots + w_nX_n
\]
on:
\(Y\) és la variable dependent (objectiu o target),
\(X_1, X_2, \ldots, X_n\) són les variables independents (característiques o features),
\(w_0, w_1, w_2, \ldots, w_n\) són els coeficients o pesos del model.
L'objectiu de la regressió lineal és trobar els valors dels coeficients que
millor s'ajusten a les dades.
Una vegada s'ha obtingut el model, pot ser utilitzat per fer prediccions
sobre noves dades.
Exemple de regressió lineal simple
Donades les dades:
\(X\)
\(Y\)
0
5
1
15
3
35
7
75
20
205
La regressió lineal tracta de trobar la recta que millor s'ajusta a les dades.
Les mètriques són mesures que ens permeten avaluar la qualitat d'un model de regressió,
que determinen com de bé s'ajusta el model a les dades i com de precises són les prediccions.
L'error absolut mitjà (Mean Absolute Error o MAE) és la mitjana de les diferències
absolutes entre les prediccions (\(\hat{y}\)) i els valors reals (\(y\)).
La fórmula per calcular l'error absolut mitjà és:
\[
MAE = \frac{1}{n} \sum_{i=1}^{n} |y_i - \hat{y}_i|
\]
Càlcul de l'error absolut mitjà
mae=np.abs(Y-pred_Y).mean()print(f'MAE with pandas: {mae:.2f}')
fromsklearn.metricsimportmean_absolute_errormae=mean_absolute_error(Y,pred_Y)print(f'MAE with sklearn: {mae:.2f}')
MAE: 2.75
Quan més xicotet siga el MAE, millor serà el model.
És fàcil d'interpretar ja que està expressat en les mateixes
que la variable dependent.
L'error quadràtic mitjà (Mean Squared Error o MSE) és la mitjana de les diferències
elevades al quadrat entre les prediccions (\(\hat{y}\)) i els valors reals (\(y\)).
La fórmula per calcular l'error quadràtic mitjà és:
El MSE és més sensible als errors grans que el MAE, ja que eleva al quadrat
les diferències. Això fa que els errors més grans tinguin un pes més gran
en la mesura.
Càlcul de l'error quadràtic mitjà
mse=((Y-pred_Y)**2).mean()print(f'MSE with pandas: {mse:.2f}')
fromsklearn.metricsimportmean_squared_errormse=mean_squared_error(Y,pred_Y)print(f'MSE with sklearn: {mse:.2f}')
El coeficient de determinació (\(R^2\)) és una mesura que indica com de bé
s'ajusta el model als valors reals.
El coeficient de determinació pot prendre valors entre 0 i 1, sent 1 el millor valor
possible. Un valor de 0 indica que el model no s'ajusta als valors reals.
El coeficient de determinació es pot calcular com:
Podem visualitzar el model de regressió lineal amb una gràfica.
importmatplotlib.pyplotaspltimportnumpyasnp# Coeficients i interceptb0=model.intercept_b1,b2=model.coef_# Crear el gràfic 3Dfig=plt.figure(figsize=(10,7))ax=fig.add_subplot(111,projection='3d')# Dades reals: scatter plotax.scatter(X_train['hores_estudiades'],X_train['motivacio'],Y_train,color='green',label='Conjunt d\'entrenament')ax.scatter(X_test['hores_estudiades'],X_test['motivacio'],Y_test,color='blue',label='Conjunt de prova')# Crear una graella per a les variables independentsx1_range=np.linspace(min(X_test['hores_estudiades'].min(),X_train['hores_estudiades'].min()),max(X_test['hores_estudiades'].max(),X_train['hores_estudiades'].max()),10,)x2_range=np.linspace(min(X_test['motivacio'].min(),X_train['motivacio'].min()),max(X_test['motivacio'].max(),X_train['motivacio'].max()),10,)x1_grid,x2_grid=np.meshgrid(x1_range,x2_range)# Predicció dels valors de Y per a la graella (plane de regressió)y_grid=b0+b1*x1_grid+b2*x2_grid# Superfície de la regressióax.plot_surface(x1_grid,x2_grid,y_grid,color='red',alpha=0.5)# Etiquetes dels eixosax.set_xlabel('Hores Estudiades')ax.set_ylabel('Motivació')ax.set_zlabel('Nota Final')# Títol i llegendaax.set_title('Gràfic 3D de la Regressió Lineal')ax.legend()plt.show()
#!/usr/bin/env python# --8<-- [start:dades]importpandasaspdimportnumpyasnpY=pd.Series([50,60,70,80])pred_Y=pd.Series([52,58,68,85])# --8<-- [end:dades]# --8<-- [start:mae_pandas]mae=np.abs(Y-pred_Y).mean()print(f'MAE with pandas: {mae:.2f}')# --8<-- [end:mae_pandas]# --8<-- [start:mae_sklearn]fromsklearn.metricsimportmean_absolute_errormae=mean_absolute_error(Y,pred_Y)print(f'MAE with sklearn: {mae:.2f}')# --8<-- [end:mae_sklearn]# --8<-- [start:mse_pandas]mse=((Y-pred_Y)**2).mean()print(f'MSE with pandas: {mse:.2f}')# --8<-- [end:mse_pandas]# --8<-- [start:mse_sklearn]fromsklearn.metricsimportmean_squared_errormse=mean_squared_error(Y,pred_Y)print(f'MSE with sklearn: {mse:.2f}')# --8<-- [end:mse_sklearn]# --8<-- [start:rmse_pandas]rmse=np.sqrt(((Y-pred_Y)**2).mean())print(f'RMSE with pandas: {rmse:.2f}')# --8<-- [end:rmse_pandas]# --8<-- [start:rmse_sklearn]fromsklearn.metricsimportroot_mean_squared_errorrmse=root_mean_squared_error(Y,pred_Y)print(f'RMSE with sklearn: {rmse:.2f}')# --8<-- [end:rmse_sklearn]# --8<-- [start:r2_pandas]r2=1-((Y-pred_Y)**2).sum()/((Y-Y.mean())**2).sum()print(f'R^2 with pandas: {r2:.2f}')# --8<-- [end:r2_pandas]# --8<-- [start:r2_sklearn]fromsklearn.metricsimportr2_scorer2=r2_score(Y,pred_Y)print(f'R^2 with sklearn: {r2:.2f}')# --8<-- [end:r2_sklearn]
regressio_lineal.py
#!/usr/bin/env python# --8<-- [start:dades]importpandasaspdX_train=pd.DataFrame({'hores_estudiades':[1.57,9.05,7.95,6.96,3.32,4.96,3.62,8.76,1.18],'motivacio':[93.87,74.47,83.88,51.84,64.24,98.59,65.90,67.05,64.49],})Y_train=pd.Series(name="nota",data=[63.25,60.65,71.27,50.62,44.36,73.50,51.59,61.29,50.41])X_test=pd.DataFrame({'hores_estudiades':[9.56,7.59,2.64,6.51,2.26,4.30,1.42,1.88,7.98],'motivacio':[81.82,65.72,81.67,90.37,94.80,55.50,75.54,85.15,61.98],})Y_test=pd.Series(name="nota",data=[71.18,59.50,60.22,67.81,63.62,50.48,46.32,48.76,62.21])# --8<-- [end:dades]# --8<-- [start:creacio_model]fromsklearn.linear_modelimportLinearRegressionmodel=LinearRegression()# --8<-- [end:creacio_model]# --8<-- [start:fit]model.fit(X_train,Y_train)# --8<-- [end:fit]# --8<-- [start:predict]pred_Y_test=model.predict(X_test)# --8<-- [end:predict]# --8<-- [start:params]print(f'Coeficients: {model.coef_}')print(f'Intercept: {model.intercept_}')# --8<-- [end:params]# --8<-- [start:eval]fromsklearn.metricsimport(mean_absolute_error,mean_squared_error,root_mean_squared_error,r2_score,)mae=mean_absolute_error(Y_test,pred_Y_test)mse=mean_squared_error(Y_test,pred_Y_test)rmse=root_mean_squared_error(Y_test,pred_Y_test)r2=r2_score(Y_test,pred_Y_test)print(f'MAE: {mae:.2f}')print(f'MSE: {mse:.2f}')print(f'RMSE: {rmse:.2f}')print(f'R^2: {r2:.2f}')# --8<-- [end:eval]# --8<-- [start:plot]importmatplotlib.pyplotaspltimportnumpyasnp# Coeficients i interceptb0=model.intercept_b1,b2=model.coef_# Crear el gràfic 3Dfig=plt.figure(figsize=(10,7))ax=fig.add_subplot(111,projection='3d')# Dades reals: scatter plotax.scatter(X_train['hores_estudiades'],X_train['motivacio'],Y_train,color='green',label='Conjunt d\'entrenament')ax.scatter(X_test['hores_estudiades'],X_test['motivacio'],Y_test,color='blue',label='Conjunt de prova')# Crear una graella per a les variables independentsx1_range=np.linspace(min(X_test['hores_estudiades'].min(),X_train['hores_estudiades'].min()),max(X_test['hores_estudiades'].max(),X_train['hores_estudiades'].max()),10,)x2_range=np.linspace(min(X_test['motivacio'].min(),X_train['motivacio'].min()),max(X_test['motivacio'].max(),X_train['motivacio'].max()),10,)x1_grid,x2_grid=np.meshgrid(x1_range,x2_range)# Predicció dels valors de Y per a la graella (plane de regressió)y_grid=b0+b1*x1_grid+b2*x2_grid# Superfície de la regressióax.plot_surface(x1_grid,x2_grid,y_grid,color='red',alpha=0.5)# Etiquetes dels eixosax.set_xlabel('Hores Estudiades')ax.set_ylabel('Motivació')ax.set_zlabel('Nota Final')# Títol i llegendaax.set_title('Gràfic 3D de la Regressió Lineal')ax.legend()plt.show()# --8<-- [end:plot]