默认情况下,scikit-learn的所有正则化线性回归技术都将模型系数w
拉向0,增加alpha
。是否有可能将系数拉向某些预定值?在我的应用程序中,我确实有这样的值,这些值是从先前对类似但更大的数据集的分析中获得的。换句话说,我可以transfer the knowledge从一个模型到另一个模型吗?
Lasso的优化目标是:
(1 / (2 * n_samples)) * ||y - Xw||^2_2 + alpha * ||w||_1
理论上,通过将上述内容更改为
,可以很容易地合并先前获得的系数w0
(1 / (2 * n_samples)) * ||y - Xw||^2_2 + alpha * ||w - w0||_1
问题在于,实际优化是由Cython函数enet_coordinate_descent
(通过lasso_path
和enet_path
调用)执行的。如果我想更改它,我是否需要分叉,修改和重新编译整个sklearn.linear_model
包或重新实现整个优化例程?
以下代码定义了一个数据集X
,其中包含4个要素和匹配的响应向量y
。
import numpy as np
from sklearn.linear_model import LassoCV
n = 50
x1 = np.random.normal(10, 8, n)
x2 = np.random.normal(8, 6, n)
X = np.column_stack([x1, x1 ** 2, x2, x2 ** 2])
y = .8 * x1 + .2 * x2 + .7 * x2**2 + np.random.normal(0, 3, n)
cv = LassoCV(cv=10).fit(X, y)
结果系数和alpha
是
>>> print(cv.coef_)
[ 0.46262115 0.01245427 0. 0.70642803]
>>> print(cv.alpha_)
7.63613474003
如果我们事先了解了两个系数w0 = np.array([.8, 0, .2, 0])
,那么如何将其合并?
我最终使用Adam而不是使用vanilla GD。
此解决方案只适用于给定值alpha
的套索,它没有像alpha
那样找到值LassoCV
(但它很容易添加一层简历就在它之上。)
from autograd import numpy as np
from autograd import grad
from autograd.optimizers import adam
def fit_lasso(X, y, alpha=0, W0=None):
if W0 is None:
W0 = np.zeros(X.shape[1])
def l1_loss(W, i):
# i is only used for compatibility with adam
return np.mean((np.dot(X, W) - y) ** 2) + alpha * np.sum(np.abs(W - W0))
gradient = grad(l1_loss)
def print_w(w, i, g):
if (i + 1) % 250 is 0:
print("After %i step: w = %s" % (i + 1, np.array2string(w.T)))
W_init = np.random.normal(size=(X.shape[1], 1))
W = adam(gradient, W_init, step_size=.1, num_iters=1000, callback=print_w)
return W
n = 50
x1 = np.random.normal(10, 8, n)
x2 = np.random.normal(8, 6, n)
X = np.column_stack([x1, x1 ** 2, x2, x2 ** 2])
y = .8 * x1 + .2 * x2 + .7 * x2 ** 2 + np.random.normal(0, 3, n)
fit_lasso(X, y, alpha=30)
fit_lasso(X, y, alpha=30, W0=np.array([.8, 0, .2, 0]))
After 250 step: w = [[ 0.886 0.131 0.005 0.291]]
After 500 step: w = [[ 0.886 0.131 0.003 0.291]]
After 750 step: w = [[ 0.886 0.131 0.013 0.291]]
After 1000 step: w = [[ 0.887 0.131 0.013 0.292]]
After 250 step: w = [[ 0.868 0.129 0.728 0.247]]
After 500 step: w = [[ 0.803 0.132 0.717 0.249]]
After 750 step: w = [[ 0.801 0.132 0.714 0.249]]
After 1000 step: w = [[ 0.801 0.132 0.714 0.249]]
此示例的结果非常相似,但您至少可以说明指定W0
会阻止模型杀死第三个系数。
只有使用alpha
>时效果才会显现。 20左右。
答案 0 :(得分:5)
简而言之 - 是的,您需要通过重新编译所有内容来手动完成。 Scikit-learn不是可自定义 ML模型的库。它提供简单,典型的模型和易于使用的界面。如果你想定制你应该寻找像tensorflow,keras等或至少 - autograd。事实上,对于autograd,这非常简单,因为您可以使用numpy编写代码并使用autograd来计算渐变。
X = ... your data
y = ... your targets
W0 = ... target weights
alpha = ... pulling strength
lr = ... learning rate (step size of gradient descent)
from autograd import numpy as np
from autograd import grad
def your_loss(W):
return np.mean((np.dot(X, W) - y)**2) + alpha * np.sum(np.abs(W - W0))
g = grad(your_loss)
W = np.random.normal(size=(X.shape[1], 1))
for i in range(100):
W = W - lr * g(W)
print(W)