首頁  >  文章  >  科技週邊  >  Mango:基於Python環境的貝葉斯最佳化新方法

Mango:基於Python環境的貝葉斯最佳化新方法

WBOY
WBOY轉載
2023-04-08 12:44:211345瀏覽

譯者| 朱先忠

審校| 孫淑娟

引言

模型超參數(或模型設定)的最佳化可能是訓練機器學習演算法中最重要的一步,因為它可以找到最小化模型損失函數的最佳參數。這一步驟對於建立不易過擬合的泛化模型也是不可或缺的。

優化模型超參數的最著名技術是窮舉網格搜尋和隨機網格搜尋。在第一種方法中,搜尋空間被定義為跨越每個模型超參數的域的網格。透過在網格的每個點上訓練模型來獲得最優超參數。儘管網格搜尋非常容易實現,但它在計算上變得昂貴,尤其是當要優化的變數數量很大時。另一方面,隨機網格搜尋是一種更快的最佳化方法,可以提供更好的結果。在隨機網格搜尋中,透過僅在網格空間的隨機點樣本上訓練模型來獲得最佳超參數。

Mango:基於Python環境的貝葉斯最佳化新方法

上圖給出了兩個網格搜尋類型之間的比較。其中,九個點表示參數的選擇,左側和頂部的曲線表示作為每個搜尋維度的函數的模型精度。資料摘自Salgado Pilario等人發表在《IEEE工業電子學報》上的論文(68,6171–6180,2021)。

長期以來,兩種網格搜尋演算法都被資料科學家廣泛用於尋找最優模型超參數。然而,這些方法通常會找到損失函數遠離全域最小值的模型超參數。

然而,到了2013年,這段歷史發生了變化。這一年,James Bergstra和他的合作者發表了一篇論文,其中探索了貝葉斯優化技術,以便找到圖像分類神經網路的最佳超參數,他們將結果與隨機網格搜尋的結果進行了比較。最後的結論是,貝葉斯方法優於隨機網格搜索,請參考下圖。

Mango:基於Python環境的貝葉斯最佳化新方法

圖中展示的是LFW資料集(左)和PubFig83資料集(右)上的驗證錯誤。其中,TPE,即“Tree Parzen Estimator”,它是貝葉斯優化中使用的演算法。圖摘自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:Gaussian Processes),因為它能夠提供不確定性估計。

在貝葉斯最佳化開始時,代理模型從先驗函數開始,該先驗函數沿著搜尋空間以均勻的不確定性分佈:

Mango:基於Python環境的貝葉斯最佳化新方法

圖中展示了代理模型的先驗函數取值情況。其中,陰影區域代表不確定性,而黑線代表其平均值,紫色線表示一維目標函數。此圖片摘自2020年一篇探索貝葉斯優化的部落格文章,作者是Aporv Agnihotri和Nipun Batra。

每次在目標函數中評估搜尋空間中的樣本點時,該點處代理模型的不確定性變為零。經過多次迭代後,代理模型將類似於目標函數:

Mango:基於Python環境的貝葉斯最佳化新方法

簡單一維目標函數的代理模型

然而,貝葉斯優化的目標不是對目標函數建模,而是以盡可能少的迭代次數找到最佳模型超參數。為此,需要使用一種採集(acquisition)函數。

  • 擷取函數:此函數是在貝葉斯最佳化中引入的,用於指導搜尋。採集函數用於評估是否需要基於當前代理模型對點進行評估。一個簡單的採集函數是對代理函數的平均值最大化的點進行取樣。

貝葉斯最佳化程式碼的步驟是:

選擇用於建模目標函數的代理模型,並定義其先驗for i = 1, 2, ..., 迭代次數:

  • 給定目標中的一組評估,使用貝葉斯方法以獲得後驗。
  • 使用一個採集函數(這是一個後驗函數)來決定下一個取樣點。
  • 將新取樣的資料加入觀測集。

下圖顯示了簡單一維函數的貝葉斯最佳化:

Mango:基於Python環境的貝葉斯最佳化新方法

上圖給出了一維函數的貝葉斯優化。圖片摘自ARM research的部落格文章《AutoML的可伸縮超參數調整》

其實,有不少Python軟體套件都在幕後使用貝葉斯優化來獲得機器學習模型的最佳超參數。例如:Hyperopt;Optuna;Bayesian optimization;Scikit-optimize (skopt);GPyOpt;pyGPGO和Mango,等等。這裡僅列舉了其中的一部分。

現在,讓我們正式開始Mango的探討。

Mango:為什麼這麼特別?

近年來,各產業數據量大幅成長。這對資料科學家來說是一個挑戰,這需要他們的機器學習管道具有可擴展性。分散式計算可能會解決這個問題。

分散式計算指的是一組計算機,它們在相互通訊的同時執行共同的任務;這與平行計算不同。在平行運算中,任務被分割為多個子任務,這些子任務被指派給同一電腦系統上的不同處理器。

Mango:基於Python環境的貝葉斯最佳化新方法

並行計算與分散式運算架構示意圖。

儘管有相當多的Python函式庫使用貝葉斯最佳化來最佳化模型超參數,但它們都不支援任何分散式計算框架上的調度。 Mango開發者的動機之一是,創建一種能夠在分散式運算環境中工作的最佳化演算法,同時保持貝葉斯最佳化的能力。

Mango體系結構的秘密是什麼?使其在分散式運算環境中運作良好? Mango採用模組化設計構建,其中優化器與調度器是解耦設計的。這種設計允許輕鬆擴展使用大量數據的機器學習管道。然而,這種架構在最佳化方法中面臨挑戰,因為傳統的貝葉斯最佳化演算法是連續的;這意味著,採集函數僅提供單一下一個點來評估搜尋。

Mango使用兩種方法來並行化貝葉斯最佳化:一種是稱為批高斯過程的方法bandits,另一種方法是k-means聚類。在本部落格中,我們將不解釋批量高斯過程。

關於聚類方法,IBM的一組研究人員於2018年提出了使用k-means聚類來橫向擴展貝葉斯優化過程(有關技術細節,請參閱論文https://arxiv. org/pdf/1806.01159.pdf)。此方法包括從搜尋域中採樣的聚類點,這些點在採集函數中產生高值(參見下圖)。在開始時,這些聚類在參數搜尋空間中彼此遠離。當發現代理函數中的最佳區域時,參數空間中的距離會減少。 k-means聚類方法水平擴展優化,因為每個聚類用於作為單獨的過程運行貝葉斯優化。這種並行化導致更快找到最優模型超參數。

Mango:基於Python環境的貝葉斯最佳化新方法

Mango使用聚类方法来扩展贝叶斯优化方法。采集函数上的彩色区域是由搜索空间中具有高采集函数值的采样点构建的聚类。开始时,聚类彼此分离,但由于代理函数与目标相似,它们的距离缩短。(图片摘自ARM research的博客文章《AutoML的可伸缩超参数调整》)

除了能够处理分布式计算框架之外,Mango还与Scikit-learn API兼容。这意味着,您可以将超参数搜索空间定义为Python字典,其中的键是模型的参数名,每个项都可以用scipy.stats中实现的70多个分布中的任何一个来定义。所有这些独特的特性使Mango成为希望大规模利用数据驱动解决方案的数据科学家的好选择。

简单示例

接下来,让我们通过一个实例展示Mango是如何在优化问题中工作的。首先,您需要创建一个Python环境,然后通过以下命令安装Mango:

pip install arm-mango

在本例中,我们使用可直接从Scikit-learn加载的加州住房数据集(有关此链接的更多信息请参考https://scikit-learn.org/stable/modules/generated/sklearn.datasets.fetch_california_housing.html):

import pandas as pd
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.ensemble import ExtraTreesRegressor
from sklearn.metrics import mean_squared_error
import numpy as np
import time
from mango import Tuner

housing = fetch_california_housing()

# 从输入数据创建数据帧
# 注:目标的每个值对应于以100000为单位的平均房屋价值
features = pd.DataFrame(housing.data, columns=housing.feature_names)
target = pd.Series(housing.target, name=housing.target_names[0])

该数据集共包含20640个样本。每个样本包括房屋年龄、平均卧室数量等8个特征。此外,加州住房数据集还包括每个样本的房价,单位为100000。房价分布如下图所示:

Mango:基於Python環境的貝葉斯最佳化新方法

在图示的左面板中,显示了加利福尼亚数据集中房价的空间分布。右边给出的是相应于同一变量的直方图。

请注意,房价的分布有点偏左。这意味着,在目标中需要一些预处理。例如,我们可以通过Log或Box-Cox变换将目标的分布转换为正态形状。由于目标方差的减小,这种预处理可以提高模型的预测性能。我们将在超参数优化和建模期间执行此步骤。现在,让我们将数据集拆分成训练集、验证集和测试集三部分:

# 将数据集拆分成训练集、验证集和测试集
x_train, x_test, y_train, y_test = train_test_split(features, target, test_size=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从中获取值的搜索空间。在本例中,我们使用了一种称为“极端随机树(Extreme Randomized Trees)”的算法,这是一种与随机森林非常相似的集成方法,不同之处在于选择最佳分割的方式是随机的。该算法通常以偏差略微增加为代价来减少方差。

极端随机化树的搜索空间可以按如下方式定义:

# 第一步:定义算法的搜索空间(使用range而不是uniform函数来确保生成整数)
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_leaf': range(int(0.001*features.shape[0]), int(0.01*features.shape[0])),
'max_features': ["sqrt", "log2", "auto"]
}

定义参数空间后,我们再指定目标函数。在这里,我们使用上面创建的训练和验证数据集;但是,如果您想运行k倍交叉验证策略,则需要在目标函数中由您自己来实现它。

# 第二步:定义目标函数
# 如果要进行交叉验证,则在目标中定义交叉验证
#在这种情况下,我们使用类似于1倍交叉验证的方法。
def objective(list_parameters):
global x_train, y_train, x_validation, y_validation

results = []
for hyper_params in list_parameters:
model = ExtraTreesRegressor(**hyper_params)
model.fit(x_train, np.log1p(y_train))
prediction = model.predict(x_validation)
prediction = np.exp(prediction) - 1# to get the real value not in log scale
error = np.sqrt(mean_squared_error(y_validation, prediction))
results.append(error)
return results

关于上述代码,有几点需要注意:

  • 目标函数旨在找到使均方根误差(RMSE)最小化的最佳模型参数。
  • 在Scikit-learn中,回归问题的极端随机化树的实现称为ExtraTreesRegressor。
  • 请注意,训练集中的房价要经过对数变换。因此,验证集上的预测被转换回其原始规模。

优化模型超参数所需的最后一步是实例化类Tuner,它负责运行Mango:

#第三步:通过Tuner运行优化
start_time = time.time()
tuner = Tuner(param_space, objective, dict(num_iteration=40, initial_random=10))#初始化Tuner
optimisation_results = tuner.minimize()
print(f'The optimisation in series takes {(time.time()-start_time)/60.} minutes.')

#检查结果
print('best parameters:', optimisation_results['best_params'])
print('best accuracy (RMSE):', optimisation_results['best_objective'])

# 使用测试集上的最佳超参数运行模型
best_model = ExtraTreesRegressor(n_jobs=-1, **optimisation_results['best_params'])
best_model.fit(x_train, np.log1p(y_train))
y_pred = np.exp(best_model.predict(x_test)) - 1# 获取实际值
print('rmse on test:', np.sqrt(mean_squared_error(y_test, y_pred)))

上述代码在MacBook Pro(处理器为2.3 Ghz四核英特尔酷睿i7)上运行了4.2分钟。

最佳超参数和最佳RMSE分别为:

best parameters: {‘max_depth’: 9, ‘max_features’: ‘auto’, ‘min_samples_leaf’: 85, ‘min_samples_split’: 729}
best accuracy (RMSE): 0.7418871882901833

当在具有最佳模型参数的训练集上训练模型时,测试集上的RMSE为:

rmse on test: 0.7395178741584788

免责声明:运行此代码时可能会得到不同的结果。

让我们简要回顾一下上面代码中使用的类Tuner。此类有许多配置参数,但在本例中,我们只尝试了其中两个:

  • num_iteration:这些是Mango用于找到最佳值的迭代总数。
  • initial_random:该变量设置测试的随机样本数。注意:Mango将所有随机样本一起返回。这非常有用,尤其是在优化需要并行运行的情况下。

注意:本博客中发布的示例仅使用了一个小数据集。然而,在许多实际应用程序中,您可能会处理需要并行实现Mango的大型数据文件。如果您转到我的​​GitHub源码仓库​​,您可以找到此处显示的完整代码以及大型数据文件的实现。

總之,Mango用途廣泛。您可以在廣泛的機器和深度學習模型中使用它,這些模型需要並行實作或分散式運算環境來最佳化其超參數。因此,我鼓勵您訪問Mango的GitHub存儲庫。在那裡,您可以找到許多工程原始碼,展示Mango在不同運算環境中的使用。

總結

在本部落格中,我們認識了Mango:一個Python庫,用於進行大規模貝葉斯優化。此軟體包將使您能夠:

  • 擴展模型超參數的最佳化,甚至可以在分散式運算框架上運行。
  • 輕鬆將scikit-learn模型與Mango集成,產生強大的機器學習管道。
  • 使用scipy.stats中實現的任何機率分佈函數,用於聲明你的搜尋空間。

所有這些特性使Mango成為一個獨特的擴展您的資料科學工具包的Python庫。

譯者介紹

朱先忠,51CTO社群編輯,51CTO專家部落格、講師,濰坊一所大學電腦教師,自由程式設計界老兵一枚。

原文標題:#Mango: A new way to do Bayesian optimization in Python#Mango: A new way to do Bayesian optimization in Python#,作者:Carmen Adriana Martinez Barbosa

###

以上是Mango:基於Python環境的貝葉斯最佳化新方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:51cto.com。如有侵權,請聯絡admin@php.cn刪除