当前位置: 首页 > 科技观察

Mango:基于Python环境的贝叶斯优化新方法

时间:2023-03-12 08:40:25 科技观察

Mango:一种基于Python的贝叶斯优化新方法。简介模型超参数(或模型设置)的优化可能是机器学习算法训练中最重要的一步,因为它会找到最小化模型损失函数的最佳参数。此步骤对于构建不太容易过度拟合的通用模型也是必不可少的。优化模型超参数的最著名技术是穷举网格搜索和随机网格搜索。在第一种方法中,搜索空间被定义为跨越每个模型超参数域的网格。通过在网格的每个点上训练模型来获得最佳超参数。尽管网格搜索很容易实现,但它的计算成本会很高,尤其是当要优化的变量数量很大时。另一方面,随机网格搜索是一种更快的优化方法,可以提供更好的结果。在随机网格搜索中,通过仅在网格空间中的随机点样本上训练模型来获得最佳超参数。上图给出了两种网格搜索类型之间的比较。其中,九个点代表参数的选择,左侧和顶部的曲线代表模型精度作为每个搜索维度的函数。此数据取自SalgadoPilario等人的论文。发表于《IEEE工业电子学报》(68,6171–6180,2021)。这两种网格搜索算法长期以来一直被数据科学家广泛用于寻找最佳模型超参数。然而,这些方法通常会找到损失函数远离全局最小值的模型超参数。然而,在2013年,这一历史发生了变化。今年,JamesBergstra和他的合作者发表了一篇论文,他们在论文中探索了贝叶斯优化技术,以寻找图像分类神经网络的最佳超参数,并将结果与??随机网格搜索的结果进行比较。最终结论是贝叶斯方法优于随机网格搜索,请参考下图。显示的是LFW数据集(左)和PubFig83数据集(右)的验证错误。其中,TPE代表“TreeParzenEstimator”,是贝叶斯优化中使用的一种算法。此图取自Bergstra等人发表的论文。在《机器学习研究学报》(28,115–123,2013)。但为什么贝叶斯优化优于任何网格搜索算法?因为这是一种自举方法,所以它会智能搜索模型超参数,而不是通过反复试验来找到它们。在本文中,我们将剖析上述贝叶斯优化方法,并通过一个名为Mango的相对较新的Python包探索该算法的实现。贝叶斯优化在解释Mango可以做什么之前,我们需要了解贝叶斯优化的工作原理。当然,如果你已经对算法有了很好的了解,可以跳过这一部分。总而言之,贝叶斯优化有4个部分:目标函数:这是您想要最小化或最大化的实际函数。例如,它可能是回归问题中的均方根误差(RMSE)或分类问题中的对数损失函数。在机器学习模型的优化中,目标函数取决于模型超参数。这就是为什么目标函数也被称为黑盒函数,因为它的形状是未知的。搜索域或搜索空间:这对应于每个模型超参数具有的可能值。作为用户,您指定模型的搜索空间。例如,随机森林回归模型的搜索域可能是:param_space={'max_depth':range(3,10),'min_samples_split':range(20,2000),'min_samples_leaf':range(2,20),'max_features':["sqrt","log2","auto"],'n_estimators':range(100,500)}贝叶斯优化使用定义的搜索空间对目标函数中评估的点进行采样。代理模型:评估目标函数是昂贵的,所以在实践中我们只在少数几个地方知道目标函数的真实值。但是,我们需要知道其他地方的价值。这就是代理模型的用武之地,它是对目标函数进行建模的工具。替代模型的常见选择是所谓的高斯过程(GP:高斯过程),因为它们能够提供不确定性估计。在贝叶斯优化开始时,代理模型从一个先验函数开始,该先验函数沿搜索空间以均匀的不确定性分布:图中显示了代理模型的先验函数的值。其中,阴影区域代表不确定性,而黑线代表其均值,紫色线代表一维目标函数。此图片来自AporvAgnihotri和NipunBatra于2020年发表的一篇博文探索贝叶斯优化。每次在目标函数中评估搜索空间中的样本点时,代理模型在该点的不确定性变为零。经过多次迭代后,代理模型将类似于目标函数:简单一维目标函数的代理模型然而,贝叶斯优化的目标不是对目标函数建模,而是找到具有尽可能少的迭代超参数的最佳模型.为此,使用了采集功能。获取函数:这个函数是在贝叶斯优化中引入的,用来指导搜索。获取函数用于评估一个点是否需要基于当前代理模型进行评估。一个简单的获取函数就是在代理函数均值最大的点上采样。贝叶斯优化代码中的步骤是:选择一个替代模型来为目标函数建模并定义其先验i=1,2,...,迭代次数:给定目标中的一组评估,使用贝叶斯Yeesian获得后验的方法。使用采集函数(这是一个后验函数)来确定下一个采样点。将新采样的数据添加到观察集中。下图展示了一个简单的一维函数的贝叶斯优化:上图展示了一个一维函数的贝叶斯优化。图片取自ARM研究博客文章《AutoML的可伸缩超参数调整》。事实上,有相当多的Python包在幕后使用贝叶斯优化来获得机器学习模型的最佳超参数。例如:Hyperopt;Optuna;贝叶斯优化;Scikit优化(skopt);GPy选项;pyGPGO和Mango等。这里只是其中的一部分。现在,让我们正式开始对Mango的讨论。芒果:为什么这么特别?近年来,各行业的数据量大幅增加。这对数据科学家来说是一个挑战,他们需要机器学习管道的可扩展性。分布式计算可能会解决这个问题。分布式计算是指一组计算机在相互通信的同时执行共同的任务;这与并行计算不同。在并行计算中,一个任务被分成多个子任务,这些子任务分配给同一计算机系统上的不同处理器。并行计算和分布式计算架构示意图。尽管有相当多的Python库使用贝叶斯优化来优化模型超参数,但它们都不支持在任何分布式计算框架上进行调度。Mango开发人员的动机之一是创建一种优化算法,该算法可以在分布式计算环境中工作,同时保持贝叶斯优化的功能。芒果架构的秘密是什么?使其在分布式计算环境中运行良好?Mango采用模块化设计构建,其中优化器和调度器是解耦的。这种设计允许轻松扩展使用大量数据的机器学习管道。然而,这种架构在优化方法上面临挑战,因为传统的贝叶斯优化算法是连续的;这意味着获取功能仅提供单个下一个点来评估搜索。Mango使用两种方法来并行化贝叶斯优化:一种称为bandits的方法称为batchGaussianprocess,另一种方法称为k-meansclustering。在这篇博客中,我们不会解释批处理高斯过程。关于聚类方法,IBM的一组研究人员在2018年提出使用k-means聚类来扩展贝叶斯优化程序(技术细节参见论文https://arxiv.org/pdf/1806.01159.pdf)。该方法包括从搜索域采样的聚类点,这些点在获取函数中产生高值(见下图)。一开始,这些簇在参数搜索空间中彼此远离。当找到代理函数中的最佳区域时,参数空间中的距离减小。k均值聚类方法横向扩展优化,因为每个聚类都用于作为单独的过程运行贝叶斯优化。这种并行化可以更快地找到最佳模型超参数。Mango使用聚类方法来扩展贝叶斯优化方法。采集函数上的彩色区域是从搜索空间中具有高采集函数值的采样点构建的簇。一开始,聚类彼此分离,但由于代理函数与目标的相似性,它们的距离减小了。(图片摘自ARM研究博文《AutoML的可伸缩超参数调整》)除了能够处理分布式计算框架外,Mango还兼容Scikit-learnAPI。这意味着,您可以将超参数搜索空间定义为Python字典,其中键是模型的参数名称,并且每个术语都可以由scipy.stats中实现的70多个分布中的任何一个定义。所有这些独特的功能使Mango成为希望大规模利用数据驱动解决方案的数据科学家的不错选择。简单示例接下来,让我们通过示例展示Mango如何在优化问题中工作。首先,您需要创建一个Python环境,然后通过以下命令安装Mango:pipinstallarm-mango在这个例子中,我们使用可以直接从Scikit-learn加载的加州住房数据集(有关此链接的更多信息,请访问https://scikit-learn.org/stable/modules/generated/sklearn.datasets.fetch_california_housing.html):从sklearn.datasets导入pandasaspdfromsklearn.datasetstimefrommangoimportTunerhousing=fetch_california_housing()#从输入数据创建数据框#注:target的每个值对应以100000为单位的平均房价features=pd.DataFrame(housing.data,columns=housing.feature_names)target=pd.Series(housing.target,name=housing.target_names[0])这个数据集总共包含20640个样本,每个样本包括8个特征如房屋年龄,平均卧室数等。此外,加州住房数据集还包括以100,000为单位的每个样本的房价。房价分布如下图所示:在插图的左侧面板中,显示了加利福尼亚数据集中房价的空间分布。右侧呈现的是同一变量对应的直方图。请注意,房价的分布有点左撇子。这意味着,目标中需要进行一些预处理。例如,我们可以通过Log或Box-Cox变换将目标的分布转化为正态分布。由于目标方差的减少,这种预处理可以提高模型的预测性能。我们将在超参数优化和建模期间执行此步骤。现在,让我们把数据集分成三部分:训练集、验证集和测试集:0.2,random_state=42)x_train,x_validation,y_train,y_validation=train_test_split(x_train,y_train,test_size=0.2,random_state=42)至此,我们准备使用Mango优化机器学习模型。首先,我们定义Mango从中获取值的搜索空间。在这个例子中,我们使用了一种名为“ExtremeRandomizedTrees”的算法,这是一种与随机森林非常相似的集成方法,不同之处在于最佳分割是随机选择的。该算法通常以略微增加偏差为代价来降低方差。极端随机树的搜索空间可以定义如下:#第一步:定义算法的搜索空间(使用range而不是uniformfunction来保证整数的生成)param_space={'max_depth':range(3,10),'min_samples_split':range(int(0.01*features.shape[0]),int(0.1*features.shape[0])),'min_samples_split':range(int(0.001*features.shape[0]),int(0.01*features.shape[0])),'max_features':["sqrt","log2","auto"]}定义参数空间后,我们指定目标函数。这里我们使用上面创建的训练和验证数据集;但是,如果要运行k折交叉验证策略,则需要在目标函数中自行实现。#Step2:Definetheobjectivefunction#如果你想做交叉验证,在目标中定义交叉验证#在这种情况下,我们使用类似于1-foldcross-validation的东西。defobjective(list_parameters):globalx_train,y_train,x_validation,y_validation结果=[]forhyper_paramsinlist_parameters:model=ExtraTreesRegressor(**hyper_params)model.fit(x_train,np.log1p(y_train))prediction=model.predictx_validation)prediction=np.exp(prediction)-1#得到不在对数范围内的真实值error=np.sqrt(mean_squared_error(y_validation,prediction))results.append(error)returnresults关于上面的代码,有一个几点注意事项:目标函数旨在找到最小化均方根误差(RMSE)的最佳模型参数。在Scikit-learn中,针对回归问题的极端随机树的实现称为ExtraTreesRegressor。请注意,训练集中的房价是对数转换的。因此,验证集上的预测被转换回其原始规模。调整模型超参数所需的最后一步是实例化负责运行Mango的Tuner类:#第三步:通过Tuner运行优化start_time=time.time()tuner=Tuner(param_space,objective,dict(num_iteration=40,initial_random=10))#初始化Tuneroptimisation_results=tuner.minimize()print(f'系列优化需要{(time.time()-start_time)/60.}分钟。')#checkresultprint('bestparameters:',optimization_results['best_params'])print('bestaccuracy(RMSE):',optimization_results['best_objective'])#在测试集上用最好的超参数运行模型best_model=ExtraTreesRegressor(n_jobs=-1,**optimization_results['best_params'])best_model.fit(x_train,np.log1p(y_train))y_pred=np.exp(best_model.predict(x_test))-1#获取实际值print('rmseontest:',np.sqrt(mean_squared_error(y_test,y_pred)))以上代码在配备2.3Ghz四核IntelCorei7处理器的MacBookPro上运行需要4.2分钟。最好的超参数和最好的RMSE是:bestparameters:{'max_depth':9,'max_features':'auto','min_samples_leaf':85,'min_samples_split':729}bestaccuracy(RMSE):0.7418871882901833whenin当训练具有最佳模型参数的训练集上的模型,测试集上的RMSE为:rmseontest:0.7395178741584788免责声明:运行此代码时,您可能会得到不同的结果。让我们简单回顾一下上面代码中使用的类Tuner。这个类有很多配置参数,但在这个例子中我们只尝试了其中两个:num_iteration:这些是Mango用来寻找最优值的迭代总数。initial_random:此变量设置测试的随机样本数。注意:Mango一起返回所有随机样本。这非常有用,尤其是在需要并行运行优化时。注意:本博客中发布的示例仅使用了一个小数据集。然而,在许多实际应用程序中,您可能正在处理需要并行实施Mango的大型数据文件。如果您转到我的GitHub源代码库,您可以找到此处显示的完整代码以及大数据文件的实现。总之,芒果是多才多艺的。您可以在广泛的机器和深度学习模型中使用它,这些模型需要并行实施或分布式计算环境来优化其超参数。因此,我鼓励您访问Mango的GitHub存储库。在那里,您可以找到许多展示Mango在不同计算环境中的使用的项目源代码。总结在这篇博客中,我们介绍了Mango:一个用于大规模贝叶斯优化的Python库。该软件包将使您能够:扩展模型超参数的优化,甚至在分布式计算框架上运行。轻松将scikit-learn模型与Mango集成,以生成强大的机器学习管道。使用scipy.stats中实现的任何概率分布函数来声明您的搜索空间。所有这些特性使Mango成为一个独特的Python库,用于扩展您的数据科学工具包。译者介绍朱宪忠,社区编辑,专家博主,讲师,潍坊某高校计算机教师,自由编程资深人士。原标题:Mango:AnewwaytodoBayesianoptimizationinPython,作者:CarmenAdrianaMartinezBarbosa