2012-10-05 18 views
11

Estoy usando LaasoCV de sklearn para seleccionar el mejor modelo seleccionado mediante validación cruzada. Descubrí que la validación cruzada arroja resultados diferentes si utilizo sklearn o la caja de herramientas estadísticas de matlab.¿Por qué LASSO en sklearn (python) y el paquete de estadísticas matlab son diferentes?

que utilizan matlab y replicar el ejemplo dado en http://www.mathworks.se/help/stats/lasso-and-elastic-net.html para conseguir una figura como esta

enter image description here

Entonces guardan los datos matlab, e intentaron reproducir la figura con laaso_path de sklearn, me consiguió

enter image description here

Aunque hay algunas similitudes entre estas dos figuras, también hay ciertas diferencias. Por lo que entiendo el parámetro lambda en matlab y alpha en sklearn son iguales, sin embargo en esta figura parece que hay algunas diferencias. ¿Puede alguien señalar cuál es la correcta o me falta algo? Además, el coeficiente obtenido también es diferente (que es mi principal preocupación).

Código Matlab:

rng(3,'twister') % for reproducibility 
X = zeros(200,5); 
for ii = 1:5 
     X(:,ii) = exprnd(ii,200,1); 
end 
r = [0;2;0;-3;0]; 
Y = X*r + randn(200,1)*.1; 

save randomData.mat % To be used in python code 

[b fitinfo] = lasso(X,Y,'cv',10); 
lassoPlot(b,fitinfo,'plottype','lambda','xscale','log'); 

disp('Lambda with min MSE') 
fitinfo.LambdaMinMSE 
disp('Lambda with 1SE') 
fitinfo.Lambda1SE 
disp('Quality of Fit') 
lambdaindex = fitinfo.Index1SE; 
fitinfo.MSE(lambdaindex) 
disp('Number of non zero predictos') 
fitinfo.DF(lambdaindex) 
disp('Coefficient of fit at that lambda') 
b(:,lambdaindex) 

Código Python:

import scipy.io 
import numpy as np 
import pylab as pl 
from sklearn.linear_model import lasso_path, LassoCV 

data=scipy.io.loadmat('randomData.mat') 
X=data['X'] 
Y=data['Y'].flatten() 

model = LassoCV(cv=10,max_iter=1000).fit(X, Y) 
print 'alpha', model.alpha_ 
print 'coef', model.coef_ 

eps = 1e-2 # the smaller it is the longer is the path 
models = lasso_path(X, Y, eps=eps) 
alphas_lasso = np.array([model.alpha for model in models]) 
coefs_lasso = np.array([model.coef_ for model in models]) 

pl.figure(1) 
ax = pl.gca() 
ax.set_color_cycle(2 * ['b', 'r', 'g', 'c', 'k']) 
l1 = pl.semilogx(alphas_lasso,coefs_lasso) 
pl.gca().invert_xaxis() 
pl.xlabel('alpha') 
pl.show() 
+0

yo sólo puedo decir que recuerdo resultados similares cuando se trabaja en datos reales. Los resultados de Matlab fueron diferentes y significativamente mejores. Aunque no exploré muy profundamente de qué se deriva este problema. – Bitwise

Respuesta

2

es posible que alpha = lambda/n_samples
donde n_samples = X.shape[0] en scikit-learn

otra observación es que su camino no es muy lineal como podría/debería ser. Considere reducir el tol y aumentar max_iter.

esperanza esto ayuda

+0

Supongo que el problema es más que normalización. Probé el de arriba y todavía tengo curvas diferentes. Además, los coeficientes obtenidos por validación cruzada son muy diferentes. – imsc

+0

Esto todavía se parece a un problema de parametrización: las 2 curvas se ven similares pero se desplazan en el eje X. Un reescalado en alfa en scikit-learn tomado en el espacio de registro puede causar esto. La parametrización utilizada en scikit-learn se proporciona en la [documentación] (http://scikit-learn.org/stable/modules/linear_model.html#lasso). También puede generar más datos de la misma distribución y calcular una puntuación de regresión (por ejemplo, el coeficiente de determinación r^2 o RMSE) y comprobar que el valor óptimo de alfa se encuentra cerca del valor cruzado validado de alfa. – ogrisel

+0

@imsc ¿has probado con 'alpha = lambda/(2 * X.shape [0])'? – ogrisel

-1

Aunque no soy capaz de averiguar lo que está causando el problema, existe una dirección lógica en el que continuar.

Estos son los hechos:

  • Mathworks ha seleccionado un ejemplo y decidió incluirlo en su documentación
  • su código de MATLAB produce exactamente el resultado que el ejemplo.
  • La alternativa no coincide con el resultado, y ha proporcionado resultados imprecisos en el pasado

Ésta es mi suposición:

  • La posibilidad de que MathWorks han optado por poner un ejemplo incorrecto en su documentación es despreciable en comparación con la posibilidad de que una reproducción de este ejemplo de una manera alternativa no dé el resultado correcto.

La conclusión lógica: su implementación de este ejemplo es confiable y la otra no. Esto podría ser un problema en el código, o tal vez en cómo lo usa, pero de cualquier forma la única conclusión lógica sería que debe continuar con Matlab para seleccionar su modelo.

+0

Este es un argumento muy débil para publicitar una tecnología sobre otra. sklearn también proporciona ejemplos. ¿Sería reproducible por el código de matlab? En realidad, LASSO es más como una clase de solucionador que un algoritmo definido con precisión. Por lo tanto, es más probable que el algoritmo difiera ligeramente. Afirmar que scikit-learn no es confiable basado en tus argumentos es bastante duro. –

+0

No quería dar a entender esto, he reformulado mi respuesta ligeramente para ser más claro. –

+0

Gracias por la respuesta. 'scikit-learn' es de hecho un módulo bien implementado. Sin embargo, todavía faltan la documentación y los ejemplos que causan el problema anterior. Podría resolver el problema mediante una normalización adecuada. – imsc

2

No tengo matlab, pero tenga cuidado de que el valor obtenido con la validación cruzada pueda ser inestable. Esto se debe a que está influenciado por la forma en que subdivide las muestras.

Incluso si ejecuta 2 veces la validación cruzada en python, puede obtener 2 resultados diferentes. considere este ejemplo:

kf=sklearn.cross_validation.KFold(len(y),n_folds=10,shuffle=True) 
cv=sklearn.linear_model.LassoCV(cv=kf,normalize=True).fit(x,y) 
print cv.alpha_ 
kf=sklearn.cross_validation.KFold(len(y),n_folds=10,shuffle=True) 
cv=sklearn.linear_model.LassoCV(cv=kf,normalize=True).fit(x,y) 
print cv.alpha_ 

0.00645093258722 
0.00691712356467 
0

Sé que esto es un hilo viejo, pero:

En realidad estoy trabajando en tuberías a partir de LassoCVglmnet (en I), y me encontré con que LassoCV doesn' t lo hace demasiado bien con la normalización de la matriz X primero (incluso si especifica el parámetro normalize = True).

Intente normalizar primero la matriz X cuando use LassoCV.

Si se trata de un objeto de pandas,

(X - X.mean())/X.std() 

Parece también es necesario para múltiples alfa por 2

Cuestiones relacionadas