【问题标题】:Knowledge transfer in regularised linear regression正则化线性回归中的知识转移
【发布时间】:2017-01-27 21:03:37
【问题描述】:

默认情况下,scikit-learn 的所有正则化线性回归技术将模型系数 w 拉向 0,并增加 alpha。是否可以将系数拉向一些预定义的值?在我的应用程序中,我确实有这样的值,这些值是从先前对类似但更大的数据集的分析中获得的。换句话说,我可以transfer the knowledge 从一个模型到另一个模型吗?

documentation of LassoCV 说:

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_pathenet_path 调用)执行的。如果我想改变它,我需要对整个sklearn.linear_model包进行fork、修改和重新编译还是重新实现整个优化例程?

玩具示例

以下代码定义了一个数据集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]) 中的两个系数有先验知识,如何将其合并?

我的最终解决方案,基于@lejlot 的回答

我最终使用Adam,而不是使用香草GD。 这个解决方案只适合给定值alpha 的套索,它不会像LassoCV 那样单独找到值alpha(但很容易在其上添加一层CV)。

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 或大约时,效果才会明显。

【问题讨论】:

    标签: python machine-learning scikit-learn


    【解决方案1】:

    简而言之 - 是的,您需要手动重新编译所有内容。 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) 
    

    【讨论】:

      猜你喜欢
      • 2015-02-13
      • 2012-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-03
      • 2015-11-13
      • 1970-01-01
      • 2018-10-13
      相关资源
      最近更新 更多