- 银行AI项目实战:典型业务场景的AI解决方案与案例实现
- 邵理煜 陈沁 何敏
- 8892字
- 2024-11-01 02:32:47
1.2 开发框架与库
本节主要介绍重要特征选择库、自动机器学习建模框架、贝叶斯优化库等,带领读者初步了解自动机器学习的实现原理及开发框架。
1.2.1 重要特征选择库Feature_selector
特征工程通常是机器学习建模任务的前面环节。特征工程主要解决特征生成与特征选择两大问题,即如何从若干原始特征开始进行特征变换,从而生成建模需要的衍生特征,如何进行特征评价并选择适合建模的特征。在特征选择环节,常见的做法是计算某个特征与模型预测值之间的IV(Information Value,信息价值)。IV衡量的是某个特征对预测值的信息关联程度。特征选择工作可以通过编写基础代码来完成,也可以借用一些机器学习工具或封装的函数库来完成。
Feature_selector是Feature Labs公司的数据科学家William Koehrsen开发的一个特征选择库。该库实现以下5类特征选择:
缺失值占比高的特征(identify_missing函数)。
具有高相关性的共线特征(identify_collinear函数)。
对预测值零重要性的特征(identify_zero_importance函数)。
对模型预测结果只有很小贡献的特征(identify_low_importance函数)。
具有单个值的特征(identify_single_unique函数)。
Feature_selector的开源代码仓库简单、高效,基于GPL-3.0许可开源,详见https://github.com/WillKoehrsen/feature-selector。下面以笔者开发的信用卡客户交易预测模型为例来说明Feature_selector的主要使用过程。
(1)实例化类。通过FeatureSelector()函数来构建特征选择实例,只需要指定训练集特征矩阵和训练集标签向量,即可返回特征选择实例:

(2)分析缺失率。使用fs的成员函数identify_missing()来选择缺失率高于指定阈值的特征。以下代码指定缺失率阈值为60%:

fs的操作结果会记录在字典成员ops中,比如要查看选择的上述缺失率高于60%的特征,只需查看ops中的missing键值即可:

由于特征缺失仅与特征自身有关,与任务类型无关,因此identify_missing()函数既适用于监督学习,也适用于非监督学习。Feature_selector为每类特征选择提供了可视化函数,只需调用对应的plot_XXXX()函数即可。比如要查看特征的缺失情况,可调用fs.plot_missing()函数得到横轴为缺失率、纵轴为特征个数的柱状图。图1-7表示1个特征的缺失率为90%~100%,50个特征的缺失率为0~10%。
(3)分析共线特征。在几何学中,一组点共线是指它们同时在一条线上。在特征工程中,将两个关联性强的特征称为共线特征。使用fs的成员函数identify_collinear()可以找出相关性大于指定阈值的共线特征对。比如找出所有输入特征中相关性大于30%的特征对,所有特征不进行独热编码:

图1-7 Feature_selector的特征缺失率分析

要查看相关性大于30%的共线特征对,只需查询ops成员字段的collinear键值即可:

由于特征相关性仅与特征自身有关,与目标任务无关,因此identify_collinear()方法既适用于监督学习,也适用于无监督学习。使用fs.plot_collinear()函数得到共线特征的可视化结果,通过颜色变化来标注其相关性的强弱。共线特征表示变量之间存在相关性,这会给建模带来干扰,通常删除。Feature_selector的共线特征相关性分析以可视化热图的形式输出,如图1-8所示。

图1-8 Feature_selector的共线特征相关性分析
(4)分析零重要性特征。使用fs的成员函数identify_zero_importance()来得到对预测目标没有贡献的特征,即零重要性特征。Feature_selector训练一个梯度提升机(Gradient Boosting Machine, GBM),由GBM得到每一个特征的重要性分数并进行归一化后,找出重要性分数等于0的特征。为了使得到的重要性分数具有很小的方差,identify_zero_importance内部会对GBM训练多次,取多次训练的平均值,得到最终的重要性分数。同时从数据集中抽取一部分作为验证集,在训练GBM的时候,计算GBM在验证集上的度量值,当满足预设条件时,结束GBM训练。比如对于分类任务,当验证集精度达到预设值后就提前结束训练,总共训练10次,代码如下:

要查看选择的零重要性特征,只需查询ops字典的zero_importance键值即可:

在训练GBM的时候,我们得到了每个特征的重要性分数,将其归一化后就可以绘制重要性条形图。比如我们绘制前51个重要特征(plot_n参数)的归一化条形图,并计算所有特征的累计重要性达到90%时(threshold参数)需要的特征个数:

图1-9是Feature_selector的特征重要性分析可视化输出。值得注意的是,图中横轴的特征重要性分数是归一化后的结果,因此所有特征的重要性分数之和必定等于1。

图1-9 Feature_selector的特征重要性分析
然后Feature_selector会绘制一条虚线,它表示在当前数据集下,所有特征的累计重要性分数达到90%时,需要约25个特征,如图1-10所示。
由于GBM的训练具有一定的随机性,因此每次训练得到的特征重要性分数会存在一定差异。因为训练GBM需要指定目标字段,必须向FeatureSelector()函数传入标签(labels参数),所以identify_zero_importance()只适用于监督学习,不适用于无监督学习。
(5)分析低重要性特征。使用fs的成员函数identify_low_importance()就能获取图1-10中虚线右边的不重要特征。由于它是在GBM基础上执行的,因此也只适用于监督学习。执行以下代码得到低重要性特征列表:


图1-10 Feature_selector的累计特征重要性分析
(6)分析单一取值特征。使用fs的成员函数identify_single_unique()可获取只有单一取值的特征,这种特征对模型训练没有意义,可以直接删除,适用于监督学习和无监督学习。执行以下代码可得到单一值特征列表:

Feature_selector提供了plot_unique()函数来绘制每个特征的单一取值柱状图,即统计出每个特征的单一值个数,然后绘制其频率占比,如图1-11所示。
1.2.2 重要特征选择库Boruta
在机器学习术语中,代价函数与损失函数都是指模型的预测偏差,但损失函数通常作用在单个样本上,而代价函数则作用在整个数据集上,是所有样本损失函数的平均值。通常情况下,我们在机器学习任务中进行特征选择的目标是筛选出使得当前模型代价函数(Cost Function)取值最小的特征集合,即只选择必要的、数量最少的特征。在特征最少的条件下,模型对数据集的拟合达到最优,多余的特征反而是干扰因素,只会增加计算量,却不会提升模型性能。

图1-11 Feature_selector的特征单一值分析
Boruta是一个重要特征选择库,它提供了一个与上述特征选择不同的思路。使用Boruta进行特征选择的目标是筛选出所有与因变量具有相关性的特征集合。有了Boruta,我们就可以选择对因变量预测有直接贡献的特征。Boruta的意义在于可以帮助我们更全面地理解因变量的影响因素,从而更好、更高效地进行特征选择。
Boruta的算法思想是:在原始特征(Real Features)数据集中进行打乱(Shuffle)操作,构造出影子特征(Shadow Features),将原始特征与影子特征拼接起来合成特征矩阵进行训练。训练使用了基于树的分类器(随机森林),在这个分类器中,目标特征被合成特征所替代,所有特征的性能差异用于计算相对重要性。通过循环的方式评价各特征的重要性,在每一轮迭代中,对原始特征和影子特征进行重要性比较。如果原始特征的重要性显著高于影子特征的重要性,则认为该原始特征是重要的;如果原始特征的重要性显著低于影子特征的重要性,则认为该原始特征是不重要的。最后以影子特征的特征重要度(Feature Importance)得分作为参考基线,从原始特征中选出与因变量真正相关的特征集合。算法过程如下。
(1)对特征矩阵X的各个特征取值进行随机Shuffle操作,将构造出的影子特征与原始特征拼接构成新的特征矩阵。
(2)使用新的特征矩阵作为输入,训练可以输出特征重要度模型。
(3)计算原始特征和影子特征的Z_score。其中,Z_score的计算公式为:特征重要度均值/特征重要度标准差。
(4)在影子特征中找出最大的Z_score,记为Zmax,将Z_score大于Zmax的原始特征标记为“重要”,将Z_score显著小于Zmax的原始特征标记为“不重要”,并且从特征集合中永久剔除。
(5)删除所有影子特征。
(6)重复(1)到(5),直到所有特征都被标记为“重要”或“不重要”。
1.2.3 自动机器学习建模框架Flaml
在介绍Flaml框架前,我们先来看看自动机器学习要解决的核心问题——最佳模型搜索。在数据集和建模任务确定的情况下,如何通过算法找到性能最佳模型和最佳超参数?简单说就是在一组候选解中找到最优解。图1-12展示了一条从最高点到最低点的最佳模型搜索路径。

图1-12 最佳模型搜索路径示意
如果我们把不同模型(model)和它们的多个参数(param1, param2, …, paramN)看成两个不同维度的自变量,把模型的成本函数值(cost)或其他性能指标看成因变量,则可以用一个高维超曲面来描述三者的关系。最佳模型搜索就是要从某个起始点开始,不断变换模型维度和参数维度的取值,沿着某个路径(图1-2中深色线条)找到cost的最低点,这个点对应的模型和参数就是最佳模型和最佳超参数。这个搜索过程通常要考虑影响模型性能的4个因素。
(1)采样策略:指模型如何采集数据样本,通常有K折交叉验证和预留两种策略。K折交叉验证是指先将数据集划分为K个大小相似的互斥子集,每次用K-1个子集的并集作为训练集,剩下的一个子集作为测试集,这样就可以获得K组训练/测试集,然后进行K次训练和测试,最终得到这K个测试结果的均值。优点是数据使用比较均匀,模型泛化能力强;缺点是一旦数据集较大,其计算成本较高。预留策略是指将数据集划分为两个互斥的集合,其中一个集合为训练集S,另一个为测试集T,在S上训练出模型后,用T来评估其测试误差,作为对泛化误差的估计。由于每次预留的测试集可能与原数据集存在不同的特征分布,可能影响模型的泛化能力,因此一般要采用若干次随机划分、重复进行实验评估后取平均值作为模型的最终泛化误差。K次随机预留可能导致训练集和测试集有重叠,而K折交叉验证没有重叠,因此预留策略的稳定性可能不如K折交叉验证。但在小数据集的情况下,K折交叉验证与1次预留相比,前者需要更长的时间,这时我们更愿意采用后者来加速模型评估,使得模型搜索从低成本区域快速迭代到较高成本区域,从而提高模型搜索的效率。我们需要根据情况来动态选择这两种采样策略。
(2)学习器:指采用哪种算法或模型,比如XGBoost、LightGBM、随机森林等。
(3)超参数:指定义机器学习模型的各种参数,不同超参数对模型表现有较大影响。
(4)采样样本量:指送入机器学习模型的样本数量。样本量少则可学习的信息少,可能会影响模型的泛化能力;样本量多则计算量大,模型训练速度慢。因此也需要根据实际情况来进行动态选择。
Flaml是微软开发的一个轻量级自动机器学习框架,出自微软的一篇论文“FLAML:A FAST AND LIGHTWEIGHT AUTOML LIBRARY”。Flaml框架的全称是Fast and lightweight AutoML library,因其易使用、可读性强、性能优异等特点,一经开源就火爆社区,目前已被收入微软官方Automated Tunning Library库中,成为微软大力推广的AutoML框架。
在Flaml框架中,最佳模型搜索除考虑模型性能外,还考虑模型训练的时间成本和计算复杂度成本,其工作过程如图1-13所示。

图1-13 Flaml自动模型搜索框架
在Flaml框架中,最佳模型搜索过程由一个控制器决定。最佳模型搜索是一个实例化的搜索算法从一个起始点开始搜索,循环地从自动机器学习层和机器学习层获得反馈,不断调整自动机器学习层的各项数据,使得算法逐渐逼近最佳模型及最佳超参数。自动机器学习层向机器学习层传递学习器、参数、样本量、重采样策略等数据,机器学习层使用传递的数据在训练集上训练指定的机器学习模型,向自动机器学习层回传验证损失和计算成本代价。自动机器学习层的工作机制主要有以下3步。
(1)确定重采样策略:判断数据集大小,如果是小数据集采用K折交叉验证策略,否则采用预留策略。
(2)确定学习器策略:在一组候选学习器(算法或模型)中,从一个初始学习器A开始,先在一个小样本集上完成一轮训练,得到损失值。再切换学习器B,训练后得到损失值。如果B的损失值比A高,则根据B的损失下降速度估计它达到A损失值的时间成本,计算ECI指标。ECI反映了继续试探学习器的性能提升能力和计算成本,ECI越大,性能越难提升,计算成本越高,选择该学习器的概率就越低。在Flaml框架中,学习器的选择概率为1/ECI。注意,随着训练的推进,ECI是动态变化的,因此学习器选择也是动态的。
(3)确定超参数和样本量策略:在采样策略和学习器确定的情况下,选择一组超参数,如果损失值没有下降,就反方向再取一组超参数,再训练。在训练过程中,样本量是逐步增大的。在最开始的搜索中,通过小量样本的训练结果就可以大致判断学习器和参数的好坏,模型搜索就可以迅速地从低计算成本区域向高计算成本区域移动,样本量的增加会提高计算成本,也会逼近最优模型的真实表现,因此样本量从小到大的策略有助于构建快速高效的搜索过程。模型搜索的路径将沿着设定的目标进行(比如验证精度、验证损失等)。值得说明的是,模型的计算成本除了与样本量有关外,也与模型参数密切相关。模型的参数越多、越复杂,计算成本越高。以随机森林为例,100棵树的森林的计算成本代价小于200棵树的森林的计算成本代价。因此,Flaml的搜索策略是先从简单、少量的模型参数开始,逐渐提高参数的复杂程度。
图1-14表示Flaml的搜索路径,值越大的区域颜色越深。图a为损失值热图,图b为计算开销热图。控制器搜索路径依次为1号点、2号点、3号点、4号点、5号点、6号点,图b的路径颜色是从浅入深的,表示算法高效地从低计算成本区域向较高计算成本区域移动,但当搜索到5号点的时候,因其计算成本明显上升一个档次,同时从图a发现5号点的损失值与4号点相比差别不大,这时算法认为继续向计算成本更高区域搜索的意义不大,因此不再沿着4号点到5号点的直线方向搜索,而转向几乎相反的方向搜索,来到6号点。完成6号点的迭代后发现触发了结束条件,即事先设定的搜索时长,于是结束搜索。这个过程就是Flaml提出的“成本节约优化”(Cost-Frugal Optimization, CFO),即从一个低成本的初始点(在搜索空间中通过low_cost_init_value指定)开始,并根据其随机本地搜索策略执行本地更新。利用这种策略,CFO可以快速地向低计算成本区域移动,表现出良好的收敛性。这使得模型一开始很快就在低计算成本区域完成试探,随后迅速转向较高计算成本区域继续搜索。

图1-14 Flaml的搜索路径
Flaml框架还提供了一种新型的全局搜索算法——BlendSearch,它通过兼顾全局搜索来优化局部超参数搜索。BlendSearch是CFO的扩展算法,它在计算成本控制的基础上加入了类似贝叶斯优化的搜索能力。与CFO一样,BlendSearch从一个低计算成本的初始点开始进行模型搜索。与CFO不同的是,BlendSearch不会等到本地搜索完全收敛之后才尝试新的起点。在全局搜索空间包含多个不相交、不连续子空间的情况下,BlendSearch能很好地改善搜索结果。
表1-1是在航空公司数据集上的分类任务的模型搜索结果,可以看到,Flaml一开始选择了LightGBM学习器,这时的样本量只有1万条,模型参数很小,只有4棵树,训练时间也很短。随着搜索的深入,模型复杂度在提升,训练时间和样本量也在提升,验证集损失在降低,并且通过ECI选择了XGBoost,最终搜索的XGBoost模型复杂度竟然有23825棵树,训练时间和样本量提升非常明显,而验证集损失的提升非常有限。这就说明搜索策略仅使用较少的计算代价就找到了较好的模型及其参数,Flaml是非常快速且有效的。
表1-1 Flaml模型搜索参数

(续)

1.2.4 自动机器学习框架AutoGluon
AutoGluon是亚马逊开源的另一款自动机器学习框架,该框架使用集成学习技术构建。与Flaml一样,该框架发布后不久便在社区大火,号称只需三行代码便可自动生成高性能模型,快速实现算法选择、模型训练、模型调参、神经架构搜索等自动化过程。AutoGluon通过NAS自动搜索的Yolo模型性能超越了资深模型调参师手工调的Faster Rcnn模型。亚马逊首席科学家、深度神经网络框架MXNet作者之一李沐表示,该框架开启了机器学习新时代,调得一手好参的时代要过去了。AutoGluon是一个开箱即用的产品,可快速实现表格预测、图像分类、文本分类、目标检测四大任务,可快速构建机器学习及深度学习任务。
在监督学习任务中,机器学习的目标是得到一个稳定且在各方面表现良好的强监督模型,但实际情况是,通常只能得到多个在某些方面性能良好的弱监督模型。我们希望即便某一个弱监督模型得到了错误的预测,通过其他弱监督模型也能将错误纠正过来。这就是集成学习的初衷,它通过并联或串联多个弱监督模型来达到这一目的。在自动机器学习框架中,Flaml是基于超参数搜索的,即在一组候选的超参数集合中找到最佳超参数。AutoGluon则避免了超参数搜索,它同时训练多个单一算法的弱监督模型,通过集成学习方法将这些弱监督模型进行组合,最终得到一个更加健壮、准确的强监督模型。AutoGluon认为,集成学习方法可以在相同时间内尝试更多模型算法,不仅能达到“三个臭皮匠顶一个诸葛亮”的效果,还能在计算效率方面成倍提升。AutoGluon使用的集成学习方法包括堆叠、K折交叉装袋、多层堆叠,如图1-15所示。

图1-15 AutoGluon的集成学习方法
(1)堆叠:在同一份数据上使用不同算法(如KNN、树算法等)训练出多个单一算法模型,将这些模型的输出作为另一个线性模型的输入,即通过加权求和来得到最终输出,线性模型的权重是通过训练得到的。
(2)K折交叉装袋:将数据集切分成K个数据块,每次使用不同的数据块作为训练集和验证集,然后使用不同的初始权重或不同的数据块来训练多个同类算法的模型。对于分类问题,将这些模型的预测结果采用投票的形式来得到最终结果;对于回归问题,以这些模型的预测结果均值作为最终结果。AutoGluon通过指定fit()函数中的num_bag_folds参数来设置K值。
(3)多层堆叠:在同一份数据上训练多个模型,将这些模型的输出合并起来,再做一次堆叠。在上面再训练多个模型,最后用一个线性模型进行输出。这里的每个模型是K个模型的装袋,它对下一层堆叠的输出,是每个装袋模型对应验证集上输出的合并。AutoGluon通过指定fit()函数中的num_stake_levels参数来设置额外增加的堆叠层数,指定num_bag_folds参数来设置K值。
在性能方面,亚马逊使用了50个不同类型的数据集,限制4小时运行时间来对比AutoGluon与常见AutoML框架的计算性能。结果显示,AutoGluon计算了30个数据集,遥遥领先其他框架。这说明其集成学习策略是非常高效的,如图1-16所示。

图1-16 AutoGluon与常见AutoML框架性能对比
1.2.5 贝叶斯优化库Bayesian-optimization
在自动超参数优化方面,传统方法有网格搜索和随机搜索。网格搜索本质上是穷举法,比如模型有A、B、C三个参数,每个参数有10个选择,就穷举1000种可能。随机搜索是随机寻找最优参数。它们的共同问题是计算量大、效率低。如果把模型参数X看成自变量,模型性能(如精度、R2等指标)看成因变量,在同样的数据集和学习任务前提下,自变量的取值决定了因变量的取值,这就形成一个待求解的目标函数。通常情况下,模型参数X是一组向量,我们希望求解合适的X,使得模型性能的取值达到最大。这里存在两个问题:一是我们没有目标函数的数学表达,因此不能判断目标函数能否求导,就不能直接使用梯度法求解;二是这个函数的计算复杂度是未知的,不同的模型参数X对应的计算开销的差异可能非常大,比如随机森林的树数量和树深度参数就大幅影响计算开销,这就导致网格搜索和随机搜索很难实现。可喜的是,作为一种成熟方法,贝叶斯优化提供了新的解决思路。图1-17所示为一个目标函数。

图1-17 模型参数与模型性能曲线
在图1-17上随机找几个初始点,计算x对应的y值,得到图1-18。

图1-18 贝叶斯优化的初始点
所谓随机过程,是在样本空间中进行采样,每次的采样结果是一个过程(如序列、函数等)。用高斯过程(Gaussian Process, GP)来生成拟合这些初始样本点的多个代理函数,每个代理函数数据点上的函数值都是高斯分布,且任意k个数据点对应的函数值的组合都是联合高斯分布。由于高斯分布可以取不同的参数值,因此高斯过程返回的是一组代理函数,每个代理函数按先验概率分布对应不同的概率。这些代理函数的值域分布见图1-20中浅灰色区域部分。再用一个获取函数来决策下一个计算样本在哪个样本点附近,靠近已知最优点(该点的目标函数值较大)的地方叫“利用”(即对已知区域采样),远离已知点的地方叫“探索”(即对未知区域采样)。获取函数按照一定的策略来决定下一个样本点是“利用”还是“探索”。
图1-19展示了贝叶斯优化过程。其中第一张图表示在只采样有限个样本点的情况下,用高斯过程拟合的代理函数分布。其中右边的高斯曲线区域的y值范围较大,表示这部分区域的未知性较高,全局最优解(即最大函数值样本点)在这部分区域的可能性较大;而左边的点比较密集,说明在前期的采样工作中,获取函数使用了较多“利用”策略。第二张图的采样点比较均匀,说明在算法迭代过程中,获取函数均衡使用了“探索”策略。每完成一次新样本计算后,就使用贝叶斯优化更新高斯过程,对代理函数计算新的后验概率,通俗讲就是在更新样本点的情况下,求解什么样的代理函数高斯分布更合理,即更新图中浅灰色区域,形成一组新的代理函数。重复迭代这个过程,直到达到结束条件,这时y值最大样本点对应的x值就是我们要求解的最佳模型参数。

图1-19 贝叶斯优化过程
从这里可以看出,贝叶斯优化的本质是根据代理函数的分布来估计最有采样价值的点,然后使用“利用”或“探索”策略得到新的样本点(即得到新的观察事实),再更新代理函数的y值范围。随着迭代的反复进行,代理函数越来越清晰(即浅灰色区域越来越小),就逐步逼近最佳参数点。值得注意的是,这一计算过程与目标函数的复杂度无关,与目标函数是否可微无关,解决了前面提出的关于求导和计算复杂度的两大问题。贝叶斯优化的核心是通过高斯过程来构造最接近待求解函数的后验概率分布,随着观测样本的增加,后验分布得到改善,算法更加确定参数空间中的哪些区域值得探索,哪些区域不值得探索。图1-20展示了高斯过程,其中下图是上图高斯代理函数的上限轮廓,算法能粗略估计最优点位置(五角星处)。随着采样数的增多,代理函数的后验分布变得清晰,最终逼近最优解。

图1-20 高斯过程
Bayesian-optimization是使用高斯过程进行贝叶斯全局优化的Python实现库。该库完全使用Python编写,提供开箱即用的理念,使用者按以下步骤依次调用封装函数,即可实现贝叶斯优化全过程,使用简单方便,高效而不失优美。该库的使用步骤为:问题定义,探索迭代,参数求解。在问题定义阶段,我们要定义待优化函数及每个参数的探索范围,如果待优化算法为随机森林,其贝叶斯优化的示例步骤代码如下:


这里我们定义了一个待优化函数rf_cv(),它将随机森林的每个参数传入,返回在x、y数据集上的5折交叉验证的平均精度,然后通过Bayesian-optimization提供的BayesianOptimization()函数来定义每个参数的范围,并将待优化函数传入贝叶斯优化框架:

至此,问题定义阶段完成。在探索迭代阶段,使用贝叶斯优化的实例化对象rf_bo的maximize()函数来逼近最大化目标函数值,可使用init_points参数来指定贝叶斯优化的初始随机样本数量,使用n_iter参数来指定经历多少个随机探索步骤:

贝叶斯优化每迭代一次,就将探索到的样本点参数存储在rf_bo对象中,我们可以采用遍历方法来观察每次采样得到的模型参数:

运行上述代码即可得到输出结果。每次采样得到的随机森林的模型参数都已保存,其中max_depth代表树的最大深度,max_features代表最佳分割时需要考虑的特征数目,min_sample_split代表分割内部节点所需要的最小样本数量,n_estimators代表决策树的数量。
如果贝叶斯优化的对象是其他算法,得到的样本参数就是其他算法的参数。在参数求解阶段,直接取出rf_bo对象关于最大目标函数值的样本点参数即可,调用如下代码:

rf_bo.max将返回一个字典,分别是目标函数值target和模型参数,它是7次样本点计算中目标函数值最大的点:


接下来,将最佳参数传到随机森林模型中,就可以直接用这个模型来进行预测了:
