LASSO回归结果在Matlab和Python中有所不同

时间:2014-09-03 15:46:14

标签: python matlab numpy machine-learning mathematical-optimization

我现在正在尝试学习用于LASSO回归的ADMM算法(Boyd 2010)。

我在page上找到了一个很好的例子。

matlab代码显示为here

我尝试将其转换为python语言,以便我可以更好地理解。

以下是代码:

import scipy.io as io
import scipy.sparse as sp
import scipy.linalg as la
import numpy as np

def l1_norm(x):
    return np.sum(np.abs(x))

def l2_norm(x):
    return np.dot(x.ravel().T, x.ravel())

def fast_threshold(x, threshold):
    return np.multiply(np.sign(x), np.fmax(abs(x) - threshold, 0))

def lasso_admm(X, A, gamma):
    c = X.shape[1]
    r = A.shape[1]

    C = io.loadmat("C.mat")["C"]

    L = np.zeros(X.shape)

    rho = 1e-4
    maxIter = 200
    I = sp.eye(r)
    maxRho = 5

    cost = []

    for n in range(maxIter):
        B = la.solve(np.dot(A.T, A) + rho * I, np.dot(A.T, X) + rho * C - L)

        C = fast_threshold(B + L / rho, gamma / rho)

        L = L + rho * (B - C);  

        rho = min(maxRho, rho * 1.1); 

        cost.append(0.5 * l2_norm(X - np.dot(A, B)) + gamma * l1_norm(B))

    cost = np.array(cost).ravel()

    return B, cost

data = io.loadmat("lasso.mat")
A = data["A"]
X = data["X"]    
B, cost = lasso_admm(X, A, gamma)

我发现损失函数在100次迭代后没有收敛。矩阵B并不倾向于稀疏,另一方面,matlab代码在不同的情况下工作。

我已经检查了不同的输入数据并与Matlab输出进行了比较,但我仍然无法获得提示。

有人可以试一试吗?

提前谢谢。

1 个答案:

答案 0 :(得分:1)

我的直觉是,为什么这不符合您的期望是la.solve()电话。 la.solve()假设矩阵是满秩并且是独立的(即可逆)。当你在MATLAB中使用\时,MATLAB所做的是如果矩阵是满秩,则找到精确的逆。但是,如果矩阵不是这种方式(即超定或欠定),则系统的解决方案通过最小二乘法来解决。我建议您修改该通话,以便您使用lstsq代替solve。因此,只需将la.solve()来电替换为:

sol = la.lstsq(np.dot(A.T, A) + rho * I, np.dot(A.T, X) + rho * C - L)
B = sol[0]

请注意,除了解决方案之外,lstsq还会在4元素元组中返回一大堆输出。系统的解决方案是这个元组的第一个元素,这就是我B = sol[0]的原因。还返回的是残差的总和(第二个元素),等级(第三个元素)和你在求解时试图反转的矩阵的奇异值(第四个元素)。


我注意到了一些特点:

  • 可能或不重要的一件事是随机生成数字。 MATLAB和Python NumPy以不同的方式生成随机数,因此这可能会也可能不会影响您的解决方案。
  • 在MATLAB中,Simon Lucey的代码将L初始化为零矩阵,使L = zeros(size(X));。但是,在Python代码中,您将L初始化为:L = np.zeros(C.shape);。您正在使用不同的变量来确定L的形状。显然, 如果存在尺寸不匹配,代码将无法工作,但这是另一回事。不确定这是否会影响您的解决方案。

到目前为止,我还没有找到任何与众不同的东西,所以请尝试修复并告诉我。