【问题标题】:How does Scikit-Learn's .fit() method pass data to .predict()?Scikit-Learn .fit() 方法如何将数据传递给 .predict()?
【发布时间】:2020-02-21 10:51:20
【问题描述】:

我试图了解sklearn's .fit() 方法和.predict() 方法之间的关系;主要是数据(通常)如何从一个传递到另一个。我还没有找到另一个关于 SO 的问题已经解决了这个问题,但是围绕它跳舞(即here

我使用 BaseEstimator 和 RegressorMixin 类编写了一个自定义估算器,但在我开始通过它运行数据时遇到了几次“NotFittedError”。有人可以引导我完成一个简单的线性回归以及数据如何通过拟合和预测方法传递吗?无需深入数学——我了解回归的工作原理以及拼图的作用。也许我忽略了显而易见的事情并使它变得比应有的更复杂?但是估计方法有点像黑盒子。

【问题讨论】:

  • 你有一个将所有数据保存在里面的对象。
  • 是的,但是如果我正在编写自定义估算器,我如何将从 fit 方法收集的信息转移到 predict 方法?我得到的错误是告诉我模型尚未安装,因此在我的自定义类中这两个方法之间存在断开连接。
  • 如果你有错误然后用代码显示它。
  • 你有对象 - 某个类的实例。并且类具有可在其所有方法中使用的变量。您为此使用self.
  • 你知道 OOP(面向对象编程)以及类是如何工作的吗?没有转移 - 两种方法都可以访问相同的变量。它与数学或机器学习无关。

标签: python machine-learning scikit-learn


【解决方案1】:

让我们看看一个玩具估算器在做LinearRegression

from sklearn.base import TransformerMixin, BaseEstimator
import numpy as np

class ToyEstimator(BaseEstimator):
    def __init__(self):
        pass

    def fit(self, X, y):
        X = np.hstack((X,np.ones((len(X),1))))
        self.W = np.random.randn(X.shape[1])

        self.W = np.dot(np.dot(np.linalg.inv(np.dot(X.T,X)), X.T), y)
        self.coef_ = self.W[:-1]
        self.intercept_ = self.W[-1]
        return self


    def transform(self, X):
        X = np.hstack((X,np.ones((len(X),1))))
        return np.dot(X,self.W)

X = np.random.randn(10,3)
y = X[:,0]*1.11+X[:,1]*2.22+X[:,2]*3.33+4.44

reg = ToyEstimator()
reg.fit(X,y)
y_ = reg.transform(X)
print (reg.coef_, reg.intercept_)

输出:

[1.11 2.22 3.33] 4.4399999999999995

那么上面的代码做了什么?

  1. fit 中,我们使用训练数据拟合\训练权重。这些权重是类的成员变量[这是你在 OOP 中学到的东西]
  2. transform 方法使用存储为成员变量的训练权重对数据进行预测。

所以在调用transform 之前,您需要调用fit,因为transform 使用的是在拟合期间计算的权重。

在 sklearn 模块中,如果您在 fit 之前调用 transform,则会收到 NotFittedError 异常。

【讨论】:

  • .transform() 方法中引用的拟合变量在哪里?
  • @alofgran in transform() 应该是self.W 而不是W,这是fit() 用来保存数据的变量。所以这两种方法都使用相同的变量self.W 将数据从一种方法传输到另一种方法。
【解决方案2】:

NotFittedError 发生在您在训练或使用 .fit() 方法之前尝试使用分类器的 .predict() 方法时。

让我们以来自 scikit learn 的LinearRegression 为例。

>>> import numpy as np
>>> from sklearn.linear_model import LinearRegression
>>> X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])
>>> # y = 1 * x_0 + 2 * x_1 + 3
>>> y = np.dot(X, np.array([1, 2])) + 3
>>> reg = LinearRegression().fit(X, y)
>>> reg.score(X, y)
1.0
>>> reg.coef_
array([1., 2.])
>>> reg.intercept_ 
3.0000...
>>> reg.predict(np.array([[3, 5]]))
array([16.])

所以使用reg = LinearRegression().fit(X, y) 行,您将实例化LinearRegression 类,然后将其拟合到您的数据X 和y 中,其中X 是自变量,y 是您的依赖变量。在该类中训练模型后,线性回归的 beta 系数将保存在类属性 coef_ 中,您可以使用 reg.coef_ 访问它。这就是当你使用.predict() 类方法时类知道预测的方式。该类访问这些系数,然后它只是简单的代数来产生预测。

回到你的错误。如果您没有将模型拟合到您的训练数据,则该类不具备进行预测所需的必要属性。希望这可以消除类内部发生的一些混淆,至少在 fit()predict() 方法如何交互方面。

最终就像上面评论的那样,这可以追溯到面向对象编程的基础知识,所以如果你想进一步了解,我会阅读 Python 如何处理类,因为 scikit 学习模型遵循相同的行为

【讨论】:

  • 也许NotFittedError 的演示会有用?
  • 好的。所以,这两个方法之间的联系是通过 fit 方法的 coef_ 属性。这就是 .predict() 方法所调用的。因此,如果我正在编写一个自定义类,在我的 .predict() 方法中,我是否需要参考我安装的方法的“reg.coef_”?我不认为仅仅调用 reg.predict() 就足够了......
  • @alofgran 这两个方法之间的联系在于它们属于 LinearRegression 类。 coef_ 是 LinearRegression 类的属性,而不是 fit() 方法。类本身就是将所有这些东西联系在一起的东西。因此,这允许 fit 方法在运行时更改 coef_ 中的值,并允许 predict 在运行时访问这些值
  • @MatthewBarlowe,这对我来说很有意义。我现在明白这种区别了。谢谢,但是 coef_ 属性是必须在 predict 方法中引用的,以利用存储在 LinearRegression 类实例中的拟合系数,对吗?
  • @alofgran 我会这样认为,尽管我面前没有它的源代码
猜你喜欢
  • 2021-11-22
  • 1970-01-01
  • 2020-10-20
  • 2021-09-20
  • 2019-05-23
  • 2016-01-11
  • 1970-01-01
  • 2020-01-30
  • 2017-03-16
相关资源
最近更新 更多