Построение слитого штрафа лассо с пакетом 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)