def solve_sqrt_lasso_skinny(X, Y, weights=None, initial=None, quadratic=None, solve_args={}): """ Solve the square-root LASSO optimization problem: $$ \text{minimize}_{\beta} \|y-X\beta\|_2 + D |\beta|, $$ where $D$ is the diagonal matrix with weights on its diagonal. Parameters ---------- y : np.float((n,)) The target, in the model $y = X\beta$ X : np.float((n, p)) The data, in the model $y = X\beta$ weights : np.float Coefficients of the L-1 penalty in optimization problem, note that different coordinates can have different coefficients. initial : np.float(p) Initial point for optimization. solve_args : dict Arguments passed to regreg solver. quadratic : `regreg.identity_quadratic` A quadratic term added to objective function. """ X = rr.astransform(X) n, p = X.output_shape[0], X.input_shape[0] if weights is None: lam = choose_lambda(X) weights = lam * np.ones((p, )) weight_dict = dict(zip(np.arange(p), 2 * weights)) penalty = rr.mixed_lasso(range(p) + [rr.NONNEGATIVE], lagrange=1., weights=weight_dict) loss = sqlasso_objective_skinny(X, Y) problem = rr.simple_problem(loss, penalty) problem.coefs[-1] = np.linalg.norm(Y) if initial is not None: problem.coefs[:-1] = initial soln = problem.solve(quadratic, **solve_args) _loss = sqlasso_objective(X, Y) return soln[:-1], _loss
def test_path_group_lasso(): ''' this test looks at the paths of three different parameterizations of the same problem ''' n = 100 X = np.random.standard_normal((n, 10)) U = np.random.standard_normal((n, 2)) Y = np.random.standard_normal(100) betaX = np.array([3, 4, 5, 0, 0] + [0] * 5) betaU = np.array([10, -5]) Y += (np.dot(X, betaX) + np.dot(U, betaU)) * 5 Xn = rr.normalize(np.hstack([np.ones((100, 1)), X]), inplace=True, center=True, scale=True, intercept_column=0).normalized_array() lasso = mixed_lasso.mixed_lasso_path.gaussian(Xn[:, 1:], Y, penalty_structure=[0] * 7 + [1] * 3, nstep=10) sol = lasso.main(inner_tol=1.e-12, verbose=True) beta = np.array(sol['beta'].todense()) sols = [] sols_sep = [] for l in sol['lagrange']: loss = rr.glm.gaussian(Xn, Y) penalty = rr.mixed_lasso([mixed_lasso.UNPENALIZED] + [0] * 7 + [1] * 3, lagrange=l) # matrix contains an intercept... problem = rr.simple_problem(loss, penalty) sols.append(problem.solve(tol=1.e-12).copy()) sep = rr.separable((11, ), [ rr.l2norm((7, ), np.sqrt(7) * l), rr.l2norm((3, ), np.sqrt(3) * l) ], [np.arange(1, 8), np.arange(8, 11)]) sep_problem = rr.simple_problem(loss, sep) sols_sep.append(sep_problem.solve(tol=1.e-12).copy()) sols = np.array(sols).T sols_sep = np.array(sols_sep).T nt.assert_true( np.linalg.norm(beta - sols) / (1 + np.linalg.norm(beta)) <= 1.e-4) nt.assert_true( np.linalg.norm(beta - sols_sep) / (1 + np.linalg.norm(beta)) <= 1.e-4)
def solve_sqrt_lasso_skinny(X, Y, weights=None, initial=None, quadratic=None, solve_args={}): """ Solve the square-root LASSO optimization problem: $$ \text{minimize}_{\beta} \|y-X\beta\|_2 + D |\beta|, $$ where $D$ is the diagonal matrix with weights on its diagonal. Parameters ---------- y : np.float((n,)) The target, in the model $y = X\beta$ X : np.float((n, p)) The data, in the model $y = X\beta$ weights : np.float Coefficients of the L-1 penalty in optimization problem, note that different coordinates can have different coefficients. initial : np.float(p) Initial point for optimization. solve_args : dict Arguments passed to regreg solver. quadratic : `regreg.identity_quadratic` A quadratic term added to objective function. """ n, p = X.shape if weights is None: lam = choose_lambda(X) weights = lam * np.ones((p,)) weight_dict = dict(zip(np.arange(p), 2 * weights)) penalty = rr.mixed_lasso(range(p) + [rr.NONNEGATIVE], lagrange=1., weights=weight_dict) loss = sqlasso_objective_skinny(X, Y) problem = rr.simple_problem(loss, penalty) problem.coefs[-1] = np.linalg.norm(Y) if initial is not None: problem.coefs[:-1] = initial soln = problem.solve(quadratic, **solve_args) _loss = sqlasso_objective(X, Y) return soln[:-1], _loss
def test_path_group_lasso(): """ this test looks at the paths of three different parameterizations of the same problem """ n = 100 X = np.random.standard_normal((n, 10)) U = np.random.standard_normal((n, 2)) Y = np.random.standard_normal(100) betaX = np.array([3, 4, 5, 0, 0] + [0] * 5) betaU = np.array([10, -5]) Y += (np.dot(X, betaX) + np.dot(U, betaU)) * 5 Xn = rr.normalize( np.hstack([np.ones((100, 1)), X]), inplace=True, center=True, scale=True, intercept_column=0 ).normalized_array() lasso = rr.lasso.squared_error(Xn[:, 1:], Y, penalty_structure=[0] * 7 + [1] * 3, nstep=10) sol = lasso.main(inner_tol=1.0e-12, verbose=True) beta = np.array(sol["beta"].todense()) sols = [] sols_sep = [] for l in sol["lagrange"]: loss = rr.squared_error(Xn, Y, coef=1.0 / n) penalty = rr.mixed_lasso([rr.UNPENALIZED] + [0] * 7 + [1] * 3, lagrange=l) # matrix contains an intercept... problem = rr.simple_problem(loss, penalty) sols.append(problem.solve(tol=1.0e-12).copy()) sep = rr.separable( (11,), [rr.l2norm((7,), np.sqrt(7) * l), rr.l2norm((3,), np.sqrt(3) * l)], [np.arange(1, 8), np.arange(8, 11)], ) sep_problem = rr.simple_problem(loss, sep) sols_sep.append(sep_problem.solve(tol=1.0e-12).copy()) sols = np.array(sols).T sols_sep = np.array(sols_sep).T nt.assert_true(np.linalg.norm(beta - sols) / (1 + np.linalg.norm(beta)) <= 1.0e-4) nt.assert_true(np.linalg.norm(beta - sols_sep) / (1 + np.linalg.norm(beta)) <= 1.0e-4)