深入浅出Python机器学习12——建立算法的管道模型

管道模型的概念及用法
  • 管道模型的基本概念
           前面我们学习了如何使用交叉验证对模型进行评估,以及如何使用网格搜索来找到模型的最优参数。如果我们要用某个数据集进行模型训练的话,很可能进行如下操作:
    深入浅出Python机器学习12——建立算法的管道模型_第1张图片
           选择使用 MLP 多层感知神经网络作为下一步要用的分类器模型(因为 MLP 是典型的需要进行数据预处理的算法模型),用 StandardScaler 作为数据预处理的工具,使用 make_blobs 生成样本数量为 200,分类数为 2,标准差为 5 的数据集。在用 train_test_split 将数据集拆分成训练集和测试集。结果得到训练集中数据样本为 150 个,测试集中样本为 50 个,特征数都是 2 个。
           下面看看未经预处理的训练集和经过预处理的数据差别:
    深入浅出Python机器学习12——建立算法的管道模型_第2张图片
           可以看出, StandardScaler 将训练集的数据变得更加 “ 聚拢 ”,这样有利于我们使用神经网络模型进行拟合。
           下面用网格搜索来确定 MLP 的最优参数:
    深入浅出Python机器学习12——建立算法的管道模型_第3张图片
           为了避免模型提示迭代次数太小,我们把 max_iter 参数设置为 1600。从结果可以看出当 alpha=0.1,有 1 个 100 个节点的隐藏层,即 hidden_layer_sizers 参数为 (100,)时,模型评分最高,为 0.94,下面继续拟合测试集:
    深入浅出Python机器学习12——建立算法的管道模型_第4张图片       可以得到模型得分是 0.9 。
           但是在进行数据预处理的时候,用 StandardScaler 拟合了训练数据集 X_train,而后用这个拟合的 scaler 去分别转换了 X_train 和 X_test,这一步没有问题,可以我们在进行网格搜索的时候,是用了 X_train 来拟合 GridSearchCV。回顾网格搜索的内容,就会发现,这一步中,由于交叉验证是会把数据集分成若干份,然后依次作为训练集和测试集给模型评分,并且找到最高分。
           那么问题来了,这里我们把 X_train_scaled 进行拆分,那么拆出来的每一部分,都是基于 X_train 本身对于 StandardScaler 拟合后再对自身进行转换。相当于我们用交叉验证中生成的测试集拟合了 StandardScaler 后,再用这个 scaler 转换这个测试集自身。
           这样的做法是错误的。我们再交叉验证中,将训练集又拆分成了 training fold 和 validation fold,但用 StandardScaler 进行预处理的时候,是使用 traing_fold 和 validation fold 一起进行拟合。这样一来,交叉验证的得分就是不准确的了。
           在上述中,我们想测试的又 3 × 4 3\times4 3×4,总共 12 个,如果单独做的话,我们要进行 12 此预处理,这样有点麻烦。接下来就是使用管道模型 (Pipeline)来解决这个问题。
    深入浅出Python机器学习12——建立算法的管道模型_第5张图片
           首先导入了 scikit-learn 中的 Pipeline 类,然后在这条流水线这条 “ 流水线 ” 中 “ 安装 ” 了两个 “ 设备 ”,一个是用来进行预处理的 StandardScaler,另一个是最大迭代数为 1600 的 MLP 多层感知神经网络。然后我们用管道模型 pipeline 来拟合训练数据集,并对测试集进行评分。
           从结果可以看出,管道模型在测试集的得分达到了 0.90,和之前的分数好像没有什么差别,这是因为我们生成的数据集中的数据点量级差别并不大,实际生活中的数据得分差距会更加明显。

  • 使用管道模型进行网格搜索

       下面我们看看如何使用 pipeline 进行网格搜索:
深入浅出Python机器学习12——建立算法的管道模型_第6张图片
       在图中,管道模型在交叉验证集中的最高分是 0.94,而 MLP 的最优参数是 alpha 等于 0.1,而 hidden_layer_sizes 的数值为 (100,100)。这个参数下测试集的得分达到了 0.92。
       这里传给 params 的方法发生了一点变化,那就是我们在 hidden_layer_sizes 和 alpha 前面都添加了 mlp_ 这样一个前缀。为什么要这样呢?因为 pipeline 会有多个算法,我们需要让 pipeline 知道这个参数传递给哪一个算法。比如在本例中,我们建立的管道模型 pipeline 有 scaler 也有 mlp,如果我们不用前缀进行指定的话,pipeline 便会搞不清楚究竟是传递给 scaler 还是 mlp,于是程序会报错。
       使用 pipeline,我们改变了交叉验证的方式。在没有使用 pipeline 的时候,GridSearchCV 会把经过 scaler 处理的数据拆分成若干格训练集和验证集。而使用了 pipeline 之后,相当于每次模型会先拆分训练集和验证集,然后单独对训练集和验证集分别进行预处理,再由网格搜素寻找最优参数。这样就避免了我们前面所提到的错误操作。
       注意:GridSearchCV 拆分的训练集和验证集,不是 train_test_split 拆分的训练集和测试集,而是在 train_test_split 拆分的训练集上再进行拆分,所得到的结果。
       如下 pipeline 进行处理的过程:
深入浅出Python机器学习12——建立算法的管道模型_第7张图片
       从结果可以看出,pipeline.steps 把包含在管道模型中的数据预处理 scaler 和多层感知神经网络 MLP 的全部参数返回给我们,这就如同是流水线的工作流程一样。这个结果可以看出,GridSearchCV 进行每一步交叉验证之前, pipeline 都会对训练集和验证集进行 StandardScaler 预处理操作。

使用管道模型对股票涨幅进行回归分析
  • 数据集准备
           如果没有开过户,可从第三方软件来获取股票信息。在软件界面选择 “系统 -> 数据导出 ”,保存为 Excel 格式就 OK 了。
    深入浅出Python机器学习12——建立算法的管道模型_第8张图片
           观察上面的数据集发现有以下几个问题:
    1. 在 “ 细分行业 ” 和 “ 地区 ” 这两列全部都是字符串类型的特征。可以用 get_dummies 把它们转化成整数型数值,但这里我们假设这两个特征对分析结果影响不大,因此直接删除。
    2. 在 “ 未配变量 ” 这一列中,几乎全部都是 “ – ” 符号,表示无效数值,因此这一列也直接删除。
    3. 在其它行和列中,零星散布着一些 “ – ” 符号,这些大部分都是由于当日该股票处于停牌状态,因此相应的数值缺失。所以把这些 “ – ” 符号全部替换为 0 。
    4. 另外还有一些其它的冗余信息,比如导出的数据中,含有数据来源信息,这些也全部删掉。
      在完成上述工作后,将数据集保存在为一个 CSV 文件。
      深入浅出Python机器学习12——建立算法的管道模型_第9张图片

       从结果分析,得到了 3673 支股票的信息,每支股票包含 22 个特征。接下来尝试用 MLP 多层感知神经网络来进行回归分析,看看表现如何。

深入浅出Python机器学习12——建立算法的管道模型_第10张图片
       从结果可以看出,模型的得分一塌糊涂。产生这个得分(-46047502.64)的原因是:MLP 对数据预处理的要求很高,而原始数据集中各个特征的数量级相差甚远,因此用原始数据集进行训练,结果必然很差。

  • 建立包括预处理和 MLP 模型的管道模型

       在 sklearn 中,可以使用 make_pipeline 来便捷地建立管道模型:
深入浅出Python机器学习12——建立算法的管道模型_第11张图片
       对比结果可以发现,使用 Pipeline 建立管道模型和使用 make_pipeline 建立管道模型。这两种方法结果是完全一样的。但是 make_pipeline 要相对简洁一些。不需要在 make_pipeline 中指定每个步骤的名称,直接把每个步骤我们希望用到的功能模块传进去就可以了。
       两种方法建立的管道模型中的步骤,从参数上看,两种方法得到的结果是完全一样的。下面我们看看模型的评分:
深入浅出Python机器学习12——建立算法的管道模型_第12张图片
       和之前直接使用 MLP 多层感知神经网络不同的是,这次用来进行评分的模型是刚刚建立好的管道模型 pipe,也就是说在交叉验证中,每次都会先对数据集进行 StandardScaler 预处理,再拟合 MLP 回归模型。可以看出这次得分 0.81 比先前的得分(-46047502.64)要好很多。

  • 向管道模型添加特征选择步骤

       下面使用 pipeline 管道模型将特征选择的部分也添加进来,这里把 SelectFromModel 这个步骤也添加进了 make_pipeline 中,为了让多次运行的结果能够保持一致,也将随机森林的 random_state 进行指定(这是设置为 random_state=38),当然也可以设置其它的,对结果影响不大。
深入浅出Python机器学习12——建立算法的管道模型_第13张图片
       可以从结果中看到 pipeline 中每个步骤所使用的模型参数。进一步进行交叉验证:
深入浅出Python机器学习12——建立算法的管道模型_第14张图片
       对比之前没有添加特征选择的管道模型,这是得分几乎没变。针对不同的数据集,可以再管道模型中增加更多的步骤,以便提高模型的性能表现。
       同样还可以提取管道模型中每个步骤的属性,例如查看 SelectFromModel 步骤中,模型选择了哪些特征。
深入浅出Python机器学习12——建立算法的管道模型_第15张图片
       从结果可以看出,pipeline 可以把管道模型中特征选择 SelectFromModel 的选择结果返回给我们。这里 SelectFromModel 只选择了 4 个特征,便使得模型的得分比较可观。

使用管道模型进行模型选择和参数调优
  • 使用管道模型进行模型选择

       我们应该如何利用管道模型从若干算法中找到我们数据集的算法。比如我们想知道,对于股票数据集来说,使用随机森林算法好一些,还是使用 MLP 多层感知神经网络好一些,就可以利用管道模型来进行对比。从之前学习知道,MLP 需要对数据进行良好的预处理,而随机森林并不需要这么做。因此,我们要在设置好管道模型的参数字典做如下设置:

深入浅出Python机器学习12——建立算法的管道模型_第16张图片
       这里定义了一个字典的列表 params,作为 pipeline 的参数。在参数中,我们指定对 MLP 模型使用 StandardScaler,而 RandomForest 不使用 StandardScaler,所以 scaler 这一项对应的值是 None。而且从结果中可以看到,经过网格搜索的评估,在 MLP 和随机森林二者之间,MLP 神经网络的表现要更好一些。其模型的预测准确度,也就是 R 2 R^2 R2 分数达到了 0.94。这还是在没有调参的情况下。

  • 使用管道模型寻找更优参数

       可以通过在网格搜索中扩大搜索空间,将需要进行对比的模型参数,也放进管道模型中进行对比。
深入浅出Python机器学习12——建立算法的管道模型_第17张图片
       程序中我们把想要实验的几个参数添加了进去,也包含在了 params 的字典中,一个是 MLP 的隐藏层数量;另一个是随机森林的 n_estimators 数量。
       从结果中发现,当随机森林 n_estimators =100 的时候,随机森林的评分超过了 MLP 模型,达到了 0.95 。当然,如果继续多提供一些参数供管道模型进行选择的话,结果可能还会反转,如增加隐藏层数量或者增加每层结点数量时:
深入浅出Python机器学习12——建立算法的管道模型_第18张图片
       但是没有我们期待的剧情反转,随机森林模型依旧领先。增加了增加隐藏层数量或者增加每层结点数量,依然没能实现反超。这说明对于使用的这个数据集来说,树的数量为 100 时的随机森林模型,确实更加合适一些。
       
       
       
       
       
       
       小编机器学习学的一般,只是日常做做比记加深一下印象,望读者不吝赐教,谢谢!

你可能感兴趣的:(机器学习,深入浅出python机器学习)