sklearn——转换器(Transformer)与预估器(estimator)

news/2024/7/9 9:06:03 标签: sklearn, transformer

sklearnTransformerestimator_0">sklearn——转换器(Transformer)与预估器(estimator)

文章目录

  • sklearn——转换器(Transformer)与预估器(estimator)
    • 转换器 Transformer
      • fit 与 fit_transform 与 transform
        • 值得注意的是
      • 扒拉了下源码(这里可以跳过,看上面结论就够了)
    • 预估器 Estimator

在我之前接触的sklearn中,有 SimpleImputerOrdinalEncoderOneHotEncoder,他们的共同点是都用于对数据特征预处理。

在对他们的使用中都无法避免遇到:fit_transformtransform。初时,还没有充分了解的我只是记住了这一特征,最后了解到 sklearnTransformerestimator的概念,认为有必要整合一下。

转换器 Transformer

由于在进行模型fit之前,需要先对数据集进行预处理,这里包括对空值的处理、对object变量的预处理。

可以看作需要对数据集进行一个转换,则这个时候就需要用上Transformer了,本质上SimpleImputerOrdinalEncoderOneHotEncoder 都属于 Transformer。

例如,原数据 X_train 经过一个SimpleImputer 后,得到了经过空值插补的新数据集 X_train_new

fit 与 fit_transform 与 transform

SimpleImputer 为例,若需要均值插补,那么在插补之前首先需要知道空值对应列的均值是多少。

fit 是先计算矩阵空值(缺失值)对应列的相关值大小,如均值、中位数、频率最高的数。

transform 则在根据fit 计算的值对输入的数据集进行变换。

故,在对一个新的数据集处理之前,需要先fit 一次,得到相关值,在transform 进行转换。但一般情况下,我们会直接使用 fit_transform

fit_transform 内部是先对数据集进行 fit,在顺势对其调用transform

>>>import numpy as np
>>>from sklearn.impute import SimpleImputer
>>>imp = SimpleImputer(missing_values=np.nan, strategy='mean')
>>>imp.fit([[1, 8], [np.nan, 4], [7, 6]])
SimpleImputer()
>>>X
array([[nan,  2.],
 [ 6., nan],
 [ 7., nan]])
>>>print(imp.transform(X))
[[4. 2.]
 [6. 6.]
 [7. 6.]]
>>> print(imp.fit_transform(X))
[[6.5 2. ]
 [6.  2. ]
 [7.  2. ]]

第10行是根据提前输入的数据进行fit, 再根据fit 保存的均值,来对X进行 transform。输入的数组第一列平均值为 (1 + 7)/2 = 4 ,第二列的均值是 (8 + 4 + 6)/3 = 6,即除数是非空值的个数。 得到均值后再直接插入X的空值部分,不考虑 X 的数据。

第14行,对 X 直接进行fit_transform 即对X 先 fit ,再对X 进行 transform ,道理同上。

值得注意的是

在对数据集中, 训练集和验证机进行转换的时候,只需要对训练集调用fit即可,对于验证机直接调用transform(),因为为数据集的一致性,对验证集的转换最好同训练集一致。 (例如对训练集进行OrdinalEncoder 编码, 若对验证机也调用 fit_transform,很有可能训练集验证集中,对于同一个 object值的编码不同,比如对训练集中的球的颜色红色编码为 3 ,验证集中却对其编码为 6)

扒拉了下源码(这里可以跳过,看上面结论就够了)

翻了下源码,SimpleImputerOrdinalEncoderOneHotEncoder都有基类class _BaseEncoder(TransformerMixin, BaseEstimator) ,虽然它也有基类TransformerMixin,但是这个代码我没看大明白, 只能看出return self.fit(X, **fit_params).transform(X), 先 fit 了一次,再直接调用了一次 transform

所以简单来说 fit_transform 即 先调用了一次 fit 再调用了一次 transform

class TransformerMixin:
    """Mixin class for all transformers in scikit-learn."""

    def fit_transform(self, X, y=None, **fit_params):
        """
        Fit to data, then transform it.
        拟合数据并转换它
        Fits transformer to `X` and `y` with optional parameters `fit_params`
        and returns a transformed version of `X`.
        Parameters
        ----------
        X : array-like of shape (n_samples, n_features)
            Input samples.
        y :  array-like of shape (n_samples,) or (n_samples, n_outputs), \
                default=None
            Target values (None for unsupervised transformations).
        **fit_params : dict
            Additional fit parameters.
        Returns
        -------
        X_new : ndarray array of shape (n_samples, n_features_new)
            Transformed array.
        """
        # non-optimized default implementation; override when a better
        # method is possible for a given clustering algorithm
        if y is None:
            # fit method of arity 1 (unsupervised transformation)
            return self.fit(X, **fit_params).transform(X)
        else:
            # fit method of arity 2 (supervised transformation)
            return self.fit(X, y, **fit_params).transform(X)

OneHotEncoder 为例,直接看它的,fit 和 transform, 会发现他们都调用了基类_BaseEncoder的 _fit() 和 transform()。

    def _fit(self, X, handle_unknown="error", force_all_finite=True):
        self._check_n_features(X, reset=True)
        self._check_feature_names(X, reset=True)
        X_list, n_samples, n_features = self._check_X(
            X, force_all_finite=force_all_finite
        )
        self.n_features_in_ = n_features

        if self.categories != "auto":
            if len(self.categories) != n_features:
                raise ValueError(
                    "Shape mismatch: if categories is an array,"
                    " it has to be of shape (n_features,)."
                )

        self.categories_ = []

        for i in range(n_features):
            Xi = X_list[i]
            if self.categories == "auto":
                cats = _unique(Xi)
            else:
                cats = np.array(self.categories[i], dtype=Xi.dtype)
                if Xi.dtype.kind not in "OUS":
                    sorted_cats = np.sort(cats)
                    error_msg = (
                        "Unsorted categories are not supported for numerical categories"
                    )
                    # if there are nans, nan should be the last element
                    stop_idx = -1 if np.isnan(sorted_cats[-1]) else None
                    if np.any(sorted_cats[:stop_idx] != cats[:stop_idx]) or (
                        np.isnan(sorted_cats[-1]) and not np.isnan(sorted_cats[-1])
                    ):
                        raise ValueError(error_msg)

                if handle_unknown == "error":
                    diff = _check_unknown(Xi, cats)
                    if diff:
                        msg = (
                            "Found unknown categories {0} in column {1}"
                            " during fit".format(diff, i)
                        )
                        raise ValueError(msg)
            self.categories_.append(cats)

    def _transform(
        self, X, handle_unknown="error", force_all_finite=True, warn_on_unknown=False
    ):
        self._check_feature_names(X, reset=False)
        self._check_n_features(X, reset=False)
        X_list, n_samples, n_features = self._check_X(
            X, force_all_finite=force_all_finite
        )

        X_int = np.zeros((n_samples, n_features), dtype=int)
        X_mask = np.ones((n_samples, n_features), dtype=bool)

        columns_with_unknown = []
        for i in range(n_features):
            Xi = X_list[i]
            diff, valid_mask = _check_unknown(Xi, self.categories_[i], return_mask=True)

            if not np.all(valid_mask):
                if handle_unknown == "error":
                    msg = (
                        "Found unknown categories {0} in column {1}"
                        " during transform".format(diff, i)
                    )
                    raise ValueError(msg)
                else:
                    if warn_on_unknown:
                        columns_with_unknown.append(i)
                    # Set the problematic rows to an acceptable value and
                    # continue `The rows are marked `X_mask` and will be
                    # removed later.
                    X_mask[:, i] = valid_mask
                    # cast Xi into the largest string type necessary
                    # to handle different lengths of numpy strings
                    if (
                        self.categories_[i].dtype.kind in ("U", "S")
                        and self.categories_[i].itemsize > Xi.itemsize
                    ):
                        Xi = Xi.astype(self.categories_[i].dtype)
                    elif self.categories_[i].dtype.kind == "O" and Xi.dtype.kind == "U":
                        # categories are objects and Xi are numpy strings.
                        # Cast Xi to an object dtype to prevent truncation
                        # when setting invalid values.
                        Xi = Xi.astype("O")
                    else:
                        Xi = Xi.copy()

                    Xi[~valid_mask] = self.categories_[i][0]
            # We use check_unknown=False, since _check_unknown was
            # already called above.
            X_int[:, i] = _encode(Xi, uniques=self.categories_[i], check_unknown=False)
        if columns_with_unknown:
            warnings.warn(
                "Found unknown categories in columns "
                f"{columns_with_unknown} during transform. These "
                "unknown categories will be encoded as all zeros",
                UserWarning,
            )

大致读了以下,说实话没有看太明白,但是很容易看出,_fit 和 _transform 在主要的循环部分都多次用到,self.categories_ 这个变量,而这个变量来自于sef._fit() 。 即transform 会直接使用 fit 中存储好的预设值。

预估器 Estimator

sklearn 中带有的各种算法模型。无论分类器或者回归都属于此类。

常见基础的如决策树、随机森林。

# 决策树
from sklearn.tree import DecisionTreeRegressor		// 用于回归问题
from sklearn.tree import DecisionTreeClassifier		// 用于分类问题
# 随机胜率
from sklearn.ensemble import RandomForestRegressor
# XGBoost
from xgboost import XGBRegressor

这些预估器在使用上大同小异,以决策树为例。

  • 先实例化一个 esitimator
  • 再对他进行 fit 拟合,注意这里的 fit 是 esitimator 自带的 fit。
  • 再调用 predict 进行预测、预估。
from sklearn.tree import DecisionTreeRegressor		// 用于回归问题
from sklearn.tree import DecisionTreeClassifier		// 用于分类问题

melbourne_model = DecisionTreeRegressor(random_state = 1)

#Fit model
melbourne_model.fit(X,y)

melbourne_model.predict(X.head())   // 进行模型预测

各模型的比较和详细解释不在这里赘述。

谨记,ML的基础永远是数学基础。


http://www.niftyadmin.cn/n/1329170.html

相关文章

<机器学习中的梯度下降>-随机梯度下降(SGD)以及mini-batch \batch Gradient Descent

<机器学习中的梯度下降>-随机梯度下降&#xff08;SGD&#xff09;以及mini-batch \batch Gradient Descent 梯度下降是机器学习中的基石&#xff0c;我们可以利用梯度下降算法&#xff0c;对损失函数(loss function)求最值&#xff0c;来得到一个对于系统模型最好的参数…

联合综述《Deep Learning》阅读笔记

Deep Learning 阅读笔记 文章介绍 作者&#xff1a; 作者&#xff1a;Yann LeCun、Yoshua Bengio 、Geoffrey Hinton。 三人被称为深度学习三巨头&#xff0c;共获2018年图灵奖。 2015年为纪念人工智能提出60周年&#xff0c;《Nature》杂志专门开辟了一个“人工智能 机器…

感知器算法及python实现

这边建议异步到第二版感知器算法及其python 实现 V2.0&#xff0c;训练速度更快&#xff0c;数据集更直观。 第一版写的还是太过粗糙。 感知器算法及python实现 通俗来讲&#xff0c;感知器算法可以完成如下这类线性可分的二分类分类任务。即找出一条超平面&#xff0c;将两类…

ResNet 论文阅读笔记

ResNet 论文阅读笔记 #机器学习/深度学习 文章介绍 论文地址&#xff1a;https://arxiv.org/pdf/1512.03385.pdf 原文题目&#xff1a;Deep Residual Learning for Image Recognition 作者&#xff1a; Kaiming He 团队 &#xff08;微软亚洲研究院&#xff09; 该文是2016年…

感知器算法及其python 实现 V2.0

感知器算法及其python 实现2.0 #机器学习/学习算法 先直接上效果图&#xff08;验证集上&#xff09; 这是我第二次重新写。之前第一次写的&#xff0c;说实话很多毛病&#xff08;能跑、能训练&#xff0c;但训练效果和训练速度都很慢&#xff0c;我猜测原因是我 pandas 和…

图像缩放--双线性内插法及其python实现(图文代码)

双线性内插法 #数字图像处理 我将最近学数字图像处理&#xff0c;写的一些代码放到了github 中保存&#xff0c;有机会一起学习。有错误和需要补充的地方欢迎评论。 理论简介 双线性插值是图像内插缩放的一种方法。 简单来说&#xff0c;双线性插值即对于目标像素进行两个方…

图像增强 -- 直方图均衡化及其python实现

直方图均衡化及其python实现 #数字图像处理 文章目录直方图均衡化及其python实现展示效果理论简介什么是直方图均衡化流程图&#xff1a;代码&#xff1a;这里贴一下 我最近数字图像学习阶段写的代码 – github 仓库。有机会一起学习。 展示效果 先上一下均衡化的效果&#…

机器学习:决策树 -- 学习笔记

参考文章 决策树算法原理(上) - 刘建平Pinard - 博客园决策树算法原理(下) - 刘建平Pinard - 博客园李航《统计学习方法》第二版 决策树算法 决策树学习算法包含&#xff1a; 特征选择决策树生成决策树的剪枝 下面会分别对三个部分进行一定的总结&#xff0c;参考资料主要…