Para explorar cómo la LASSO
de regresión obras, escribí un pequeño trozo de código que se debe optimizar LASSO
de regresión escogiendo el mejor parámetro alfa.
No puedo entender por qué el LASSO
de regresión me está dando tan inestable resultados para el parámetro alfa después de la validación cruzada.
Aquí está mi código de Python:
from sklearn.linear_model import Lasso
from sklearn.cross_validation import KFold
from matplotlib import pyplot as plt
# generate some sparse data to play with
import numpy as np
import pandas as pd
from scipy.stats import norm
from scipy.stats import uniform
### generate your own data here
n = 1000
x1x2corr = 1.1
x1x3corr = 1.0
x1 = range(n) + norm.rvs(0, 1, n) + 50
x2 = map(lambda aval: aval*x1x2corr, x1) + norm.rvs(0, 2, n) + 500
y = x1 + x2 #+ norm.rvs(0,10, n)
Xdf = pd.DataFrame()
Xdf['x1'] = x1
Xdf['x2'] = x2
X = Xdf.as_matrix()
# Split data in train set and test set
n_samples = X.shape[0]
X_train, y_train = X[:n_samples / 2], y[:n_samples / 2]
X_test, y_test = X[n_samples / 2:], y[n_samples / 2:]
kf = KFold(X_train.shape[0], n_folds = 10, )
alphas = np.logspace(-16, 8, num = 1000, base = 2)
e_alphas = list()
e_alphas_r = list() # holds average r2 error
for alpha in alphas:
lasso = Lasso(alpha=alpha, tol=0.004)
err = list()
err_2 = list()
for tr_idx, tt_idx in kf:
X_tr, X_tt = X_train[tr_idx], X_test[tt_idx]
y_tr, y_tt = y_train[tr_idx], y_test[tt_idx]
lasso.fit(X_tr, y_tr)
y_hat = lasso.predict(X_tt)
# returns the coefficient of determination (R^2 value)
err_2.append(lasso.score(X_tt, y_tt))
# returns MSE
err.append(np.average((y_hat - y_tt)**2))
e_alphas.append(np.average(err))
e_alphas_r.append(np.average(err_2))
## print out the alpha that gives the minimum error
print 'the minimum value of error is ', e_alphas[e_alphas.index(min(e_alphas))]
print ' the minimizer is ', alphas[e_alphas.index(min(e_alphas))]
## <<< plotting alphas against error >>>
plt.figsize = (15, 15)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(alphas, e_alphas, 'b-')
ax.plot(alphas, e_alphas_r, 'g--')
ax.set_ylim(min(e_alphas),max(e_alphas))
ax.set_xlim(min(alphas),max(alphas))
ax.set_xlabel("alpha")
plt.show()
Si ejecuta este código en repetidas ocasiones, se da totalmente diferentes resultados para alpha:
>>>
the minimum value of error is 3.99254192539
the minimizer is 1.52587890625e-05
>>> ================================ RESTART ================================
>>>
the minimum value of error is 4.07412455842
the minimizer is 6.45622425334
>>> ================================ RESTART ================================
>>>
the minimum value of error is 4.25898253597
the minimizer is 1.52587890625e-05
>>> ================================ RESTART ================================
>>>
the minimum value of error is 3.79392968781
the minimizer is 28.8971008254
>>>
¿Por qué es el valor de alfa no converge correctamente? Sé que mis datos es sintético, pero la distribución es la misma. También, la variación es muy pequeña en x1
y x2
.
lo que podría estar causando este tan inestables?
Lo mismo escrito en R da resultados diferentes - siempre devuelve el valor más alto posible para el alfa como el "optimal_alpha".
También escribí esto en R, lo que me da un poco diferente de respuesta, que no sé por qué?
library(glmnet)
library(lars)
library(pracma)
set.seed(1)
k = 2 # number of features selected
n = 1000
x1x2corr = 1.1
x1 = seq(n) + rnorm(n, 0, 1) + 50
x2 = x1*x1x2corr + rnorm(n, 0, 2) + 500
y = x1 + x2
filter_out_label <- function(col) {col!="y"}
alphas = logspace(-5, 6, 100)
for (alpha in alphas){
k = 10
optimal_alpha = NULL
folds <- cut(seq(1, nrow(df)), breaks=k, labels=FALSE)
total_mse = 0
min_mse = 10000000
for(i in 1:k){
# Segement your data by fold using the which() function
testIndexes <- which(folds==i, arr.ind=TRUE)
testData <- df[testIndexes, ]
trainData <- df[-testIndexes, ]
fit <- lars(as.matrix(trainData[Filter(filter_out_label, names(df))]),
trainData$y,
type="lasso")
# predict
y_preds <- predict(fit, as.matrix(testData[Filter(filter_out_label, names(df))]),
s=alpha, type="fit", mode="lambda")$fit # default mode="step"
y_true = testData$y
residuals = (y_true - y_preds)
mse=sum(residuals^2)
total_mse = total_mse + mse
}
if (total_mse < min_mse){
min_mse = total_mse
optimal_alpha = alpha
}
}
print(paste("the optimal alpha is ", optimal_alpha))
La salida de la R código anterior es:
> source('~.....')
[1] "the optimal alpha is 1e+06"
De hecho, no importa lo que me puse para la línea "alphas = logspace(-5, 6, 100)
", siempre vuelvo el valor más alto de alfa.
Supongo que en realidad hay 2 diferentes preguntas aquí :
¿Por qué es el valor de alfa de forma inestable, para la versión escrita en Python?
¿Por qué la versión escrita en R me da un resultado diferente? (Me doy cuenta de que el
logspace
función es diferente deR
apython
, pero la versión escrita enR
siempre me da el mayor valor dealpha
, para el óptimo valor de alfa, mientras que la versión de python no).
Sería bueno saber estas cosas...