Построение слитого штрафа лассо с пакетом cvxpy в Python

Fused Lasso (Tibshirani et al, 2005) поощряет разреженность коэффициентов, а также разреженность их различий.

Это формула для функции потерь и регуляризации: первый член - это потери L2 (mse), второй - это штраф L1 на коэффициенты (регуляризация Лассо), а последний член - это новый термин, введенный в связанной статье.

Как я могу имитировать это с помощью cvxpy пакет - в частности, как я могу реализовать последний термин?

Есть примеры кодов для штрафов Лассо и Ридж по отдельности. У меня есть общее представление о том, как работают коды, но есть некоторые функции, которые я не понимаю, как я должен решить, какой из них использовать. Например, сравним штрафные коды Лассо и Ридж.

# Lasso

import cvxpy as cp
import numpy as np
import matplotlib.pyplot as plt

def loss_fn(X, Y, beta):
    return cp.norm2(cp.matmul(X, beta) - Y)**2

def regularizer(beta):
    return cp.norm1(beta)

def objective_fn(X, Y, beta, lambd):
    return loss_fn(X, Y, beta) + lambd * regularizer(beta)

def mse(X, Y, beta):
    return (1.0 / X.shape[0]) * loss_fn(X, Y, beta).value

# Ridge

import cvxpy as cp
import numpy as np
import matplotlib.pyplot as plt

def loss_fn(X, Y, beta):
    return cp.pnorm(cp.matmul(X, beta) - Y, p=2)**2

def regularizer(beta):
    return cp.pnorm(beta, p=2)**2

def objective_fn(X, Y, beta, lambd):
    return loss_fn(X, Y, beta) + lambd * regularizer(beta)

def mse(X, Y, beta):
    return (1.0 / X.shape[0]) * loss_fn(X, Y, beta).value

Для них обоих мы создаем функцию потерь, но они создаются разными командами?

2 ответа

Разностная матрица не нужна. Вы можете использовать

      cp.norm1(beta[1:] - beta[:-1])

на последний срок.

Насколько я понимаю, у вас возникли проблемы с выражением штрафа за разницу коэффициентов. \sum_k|b_k - b_{k-1}|.

Для этого вам просто нужно определить матрицу векторных разностей. Тогда ты можешь ударитьbetaс ним, давая вам вектор различий. Оттуда вы можете использовать стандартный атом нормы L1cvx.norm1.

def diff_op(shape):
    mat = np.zeros(shape)
    mat[range(2, shape[0]), range(1, shape[1])] = 1
    mat -= np.eye(shape)
    return mat

def difference_pen(beta, epsilon):
    return cvx.norm1(diff_op(beta.shape) @ beta)
Другие вопросы по тегам