如何在不拟合的情况下实例化具有已知系数的 Scikit-Learn 线性模型

Posted

技术标签:

【中文标题】如何在不拟合的情况下实例化具有已知系数的 Scikit-Learn 线性模型【英文标题】:How to instantiate a Scikit-Learn linear model with known coefficients without fitting it 【发布时间】:2020-08-12 22:39:26 【问题描述】:

背景

作为实验的一部分,我正在测试各种保存的模型,但其中一个模型来自我编写的算法,而不是来自 sklearn 模型拟合。

但是,我的自定义模型仍然是线性模型,因此我想实例化一个 LinearModel 实例并将 coef_intercept_ 属性设置为我的自定义拟合算法中的值,以便我可以将其用于预测。

到目前为止我尝试了什么:

from sklearn.linear_model import LinearRegression

my_intercepts = np.ones(2)
my_coefficients = np.random.randn(2, 3)

new_model = LinearRegression()
new_model.intercept_ = my_intercepts
new_model.coef_ = my_coefficients

它似乎可以用于预测:

X_test = np.random.randn(5, 3)

new_model.predict(X_test)

它通过了这个测试:

from sklearn.utils.validation import check_is_fitted

check_is_fitted(new_model)

问题

这个方法好吗?感觉就像是 hack,我怀疑有一种“正确”的方法可以做到这一点。

【问题讨论】:

不确定是否有任何“正确”的方法可以做到这一点,从某种意义上说,我非常怀疑这种用法在构建 scikit-learn 的人的脑海中是否存在,但因为它通过了测试并且没有给出.predict 的错误,我看不到任何问题。 【参考方案1】:

虽然问题中的简单技术有效,但危险在于您稍后可能会调用对象的 fit 方法并覆盖您的系数。

如果模型仅用于预测,则更“正确”的方法是从 sklearn 的类继承并重载 fit 方法,如下所示:

class LinearPredictionModel(LinearRegression):
    """
    This model is for prediction only.  It has no fit method.
    You can initialize it with fixed values for coefficients 
    and intercepts.  

    Parameters
    ----------
    coef, intercept : arrays
        See attribute descriptions below.

    Attributes
    ----------
    coef_ : array of shape (n_features, ) or (n_targets, n_features)
        Coefficients of the linear model.  If there are multiple targets
        (y 2D), this is a 2D array of shape (n_targets, n_features), 
        whereas if there is only one target, this is a 1D array of 
        length n_features.
    intercept_ : float or array of shape of (n_targets,)
        Independent term in the linear model.
    """

    def __init__(self, coef=None, intercept=None):
        if coef is not None:
            coef = np.array(coef)
            if intercept is None:
                intercept = np.zeros(coef.shape[0])
            else:
                intercept = np.array(intercept)
            assert coef.shape[0] == intercept.shape[0]
        else:
            if intercept is not None:
                raise ValueError("Provide coef only or both coef and intercept")
        self.intercept_ = intercept
        self.coef_ = coef

    def fit(self, X, y):
        """This model does not have a fit method."""
        raise NotImplementedError("model is only for prediction")

然后,实例化模型如下:

new_model = LinearPredictionModel(coef=my_coefficients, intercept=my_intercepts)

我认为唯一“正确”的方法是让我在 fit 方法中使用我的自定义算法完全实现一个新类。但是对于在 scikit-learn 环境中测试系数的简单需求,这种方法似乎可以正常工作。

【讨论】:

【参考方案2】:

这种方法非常适用于原始方法(例如线性回归),但是您如何针对更复杂的模型(例如套索或弹性网络或...)进行调整。似乎可以像这样修改线性回归器,但套索回归器仍然会抛出错误(不适合的投诉:As in this question, which is indicated as a duplicate of the above.

【讨论】:

好点。我没有研究其他类型的模型。 In the documentation 它说 check_is_fitted 方法通过“验证拟合属性的存在(以尾随下划线结尾)”来工作。所以大概你需要确保为每个必需的属性设置一个值。 @Bill 这很有趣。我自己也会调查的。如果它可以告诉我缺少哪些属性,那将对我有很大帮助。

以上是关于如何在不拟合的情况下实例化具有已知系数的 Scikit-Learn 线性模型的主要内容,如果未能解决你的问题,请参考以下文章

WCF反序列化如何在不调用构造函数的情况下实例化对象?

如何在不实例化整个 Laravel 的情况下加载 Laravel 模型?

如何在不使用 Nib 的情况下实例化和调用 UIView 子类

如何在不使用数据库的情况下重新实例化动态 ASP.NET 用户控件?

拟合(转)

如何在不使用父 App.vue 的情况下在 Laravel 中实例化 vue 3 应用程序?