Hyperopt 参数优化

翻译自https://districtdatalabs.silvrback.com/parameter-tuning-with-hyperopt
Parameter Tuning with Hyperopt –Kris Wright

概述

Hyperopt可以帮助快速进行机器学习模型参数调试。通常情况下有两种类型的参数调试方法,网格搜索(grid search)和随机搜索(random search)。网格搜索速度慢但是适用于需要随整个参数空间进行搜索的情况;随机搜索速度很快但是容易遗漏一些重要信息。幸运的是,我们有第三个选择:贝叶斯优化(Bayesian optimization)。这里我们关注贝叶斯优化在Python中的实现:Hyperopt模块。

使用贝叶斯优化进行参数调试允许我们获得给定模型的最优参数,如,逻辑回归( logistic regression),因此我们可以进行最优模型选择。通常情况下,机器学习工程师或数据科学家会对一些模型进行一些形式的手动参数调试(如网格搜索或随机搜索),如决策树(decision tree)、支持向量机(support vector machine)、k最近邻(k nearest neighbors)-然后比较准确度得分(accuracy score)进而选择性能表现最好的一组参数给模型使用。这种方法可能会产生次优模型(sub-optimal models)。数据科学家可能会给决策树选择一组最优参数,但是对SVM却不是最优的,这就意味着模型比较是有缺陷的。KNN每次都可以打败SVM,如果SVM的参数选择很差的话。贝叶斯优化允许数据科学家找到所有模型的最优参数,然后比较所有使用了最佳参数的模型。这样的话,在模型选择中,就可以比较最优的决策树和最优的支持向量机。只有这样才能保证我们选择和使用了实际最好的模型。

本文涉及的主题包括:
- 评估函数(Objective functions)
- 搜索空间(Search spaces)
- 存储评价试验(Storing evaluation trials)
- 可视化(Visualization)
- 鸢尾花数据集实例(Full example on a classic dataset: Iris)

目标函数(Objective Functions - A Motivating Example)

假设有一个定义在摸个范围内的函数,你想要使这个函数最小化,也就是说,你想要找到一个输入值,使得函数的输出结果是最小的。如下面的例子,找到一个x,使得线性函数y(x)=x取得最小值。

from hyperopt import fmin, tpe, hp
best = fmin(
    fn=lambda x: x,
    space=hp.uniform('x', 0, 1),
    algo=tpe.suggest,
    max_evals=100)
print best

下面进行分解说明。
函数fmin首先要接收一个函数fn来最小化,这里我们指定fn为一个匿名函数lambda x: x,实际上这个函数可以是任何有效的带有返回值的函数(valid value-returning function),如回归中的平均绝对误差(mean absolute error)。
第二个参数space指定了搜索空间(search space),在这个例子中为在0到1范围之间的数字。hp.uniform是一个内置的( built-in)hyperopt函数,包括三个参数:name:x,范围的上界和下届:0和1。
参数algo接收一个搜索算法(serach algorithm),这个例子中tpe代表tree of Parzen estimators。这个话题超出了这个博客文章的范围,更多关于tpe的内容请参考这里。algo参数也可以设置成hyperopt.random,但我们在此不做介绍,因为这是众所周知的搜索策略。

最后,我们指定fmin函数执行的最大次数max_evals。fmin函数返回一个python字典。函数输出的一个例子:{‘x’: 0.000269455723739237}。
下面是一张函数图像,红色的点是我们要找的x的位置。
y=x

另一个例子(More Complicated Examples)

这里有个更复杂的目标函数:lambda x: (x-1)**2,这次我们试着最小化一个二次方程 y(x)=(x1)2 y ( x ) = ( x − 1 ) 2 。因此,我们将搜索空间更改为包括我们已经知道的最优值x=1以及加上两侧的一些次优范围:hp.uniform(‘x’, -2, 2)。
我们可以得到:

best = fmin(
    fn=lambda x: (x-1)**2,
    space=hp.uniform('x', -2, 2),
    algo=tpe.suggest,
    max_evals=100)
print best

输出为:

{'x': 0.997369045274755}

函数如下图:
y=(x-1)^2
除了最小化目标函数,也许我们想使函数值最大化。这种情况下我们只需要返回函数的负值,如函数y(x) = -(x**2):
y=-x^2
如何解决这个问题呢?我们只需要将目标函数改为lambda x: (x**2),求y(x) = -(x**2)得最小值即为求y(x) = -(x**2)的最大值。
同理对于刚开始的线性函数的例子,我们将求最小化改为求最大化,将将目标函数改为lambda x: -x即可。
下面是一个有用许多(给定无穷范围的无穷多个)局部最小值得函数,也可以求最大值。
y=sin(x)/x

搜索空间(Search spaces)

Hyperopt模块包含了一些方便的函数(handy functions)来指定输入参数的范围。我们已经见过hp.uniform。最初,这些是随机搜索空间,但是随着hyperopt的学习(随着从目标函数获得更多的feedback),它会对初始搜索空间的不同部分进行调整和采样,并认为这些部分会给它提供最有意义的反馈。
以下函数将在本文使用:

  • hp.choice(label, options) ,其中options为 python list 或tuple
  • hp.normal(label, mu, sigma) ,其中mu 和 sigma 分别为均值和标准差
  • hp.uniform(label, low, high),其中low和 high分别为范围的上界和下界

其他还有hp.normal, hp.lognormal, hp.quniform,因为本文不会使用就没有写,可自行了解。
下面定义搜索空间:

import hyperopt.pyll.stochastic

space = {
    'x': hp.uniform('x', 0, 1),
    'y': hp.normal('y', 0, 1),
    'name': hp.choice('name', ['alice', 'bob']),
}

print hyperopt.pyll.stochastic.sample(space)

例子输出:

{'y': -1.4012610048810574, 'x': 0.7258615424906184, 'name': 'alice'}

获取信息和试验(Capturing Info with Trials)

如果能看到hyperopt黑盒里到底发生了什么,那就太好了。Trials对象允许我们这样做。我们只需要再导入几个项目

from hyperopt import fmin, tpe, hp, STATUS_OK, Trials

fspace = {
    'x': hp.uniform('x', -5, 5)
}

def f(params):
    x = params['x']
    val = x**2
    return {'loss': val, 'status': STATUS_OK}

trials = Trials()
best = fmin(fn=f, space=fspace, algo=tpe.suggest, max_evals=50, trials=trials)

print 'best:', best

print 'trials:'
for trial in trials.trials[:2]:
    print trial

STATUS_OK 和 Trials是新导入的模块,Trials允许我们存储每一时间步长(time step)所存储的信息。然后我们可以输出这些函数在给定时间步长上对给定参数的求值。
输出:

best: {'x': 0.014420181637303776}
trials:
{'refresh_time': None, 'book_time': None, 'misc': {'tid': 0, 'idxs': {'x': [0]}, 'cmd': ('domain_attachment', 'FMinIter_Domain'), 'vals': {'x': [1.9646918559786162]}, 'workdir': None}, 'state': 2, 'tid': 0, 'exp_key': None, 'version': 0, 'result': {'status': 'ok', 'loss': 3.8600140889486996}, 'owner': None, 'spec': None}
{'refresh_time': None, 'book_time': None, 'misc': {'tid': 1, 'idxs': {'x': [1]}, 'cmd': ('domain_attachment', 'FMinIter_Domain'), 'vals': {'x': [-3.9393509404526728]}, 'workdir': None}, 'state': 2, 'tid': 1, 'exp_key': None, 'version': 0, 'result': {'status': 'ok', 'loss': 15.518485832045357}, 'owner': None, 'spec': None}

Trials对象将数据存储为BSON对象,类似于JSON对象一样。BSON来自pymongo模块,着这里我们不讨论细节,但是对于hyperopt有一些高级选项需要使用MongoDB进行分布式计算,因此导入pymongo。
回到上面的输出,’tid’表示时间id,也就是时间步长,范围0到max_evals-1,每次迭代加1;’x’在’vals’键中,也就是每次迭代参数存储的地方;’loss’在’result’键中,是每次迭代目标函数的值。

可视化(Visualization)

这里介绍两种类型可视化,val vs. time和loss vs. val。
首先val vs. time。下面是trials.trials数据描述可视化的代码和样本输出。

f, ax = plt.subplots(1)
xs = [t['tid'] for t in trials.trials]
ys = [t['misc']['vals']['x'] for t in trials.trials]
ax.set_xlim(xs[0]-10, xs[-1]+10)
ax.scatter(xs, ys, s=20, linewidth=0.01, alpha=0.75)
ax.set_title('$x$ $vs$ $t$ ', fontsize=18)
ax.set_xlabel('$t$', fontsize=16)
ax.set_ylabel('$x$', fontsize=16)

输出如下(假设我们将max_evals设置为1000):
val vs. time
我们可以看到,最初算法从整个范围中均匀取值,但是随着时间的增加以及对于参数在目标函数上效果的学习,算法搜索范围越来越集中到最可能取得最优值的范围-0附近。它仍然探索整个解决方案空间,但不太频繁。

loss vs. val的可视化:

f, ax = plt.subplots(1)
xs = [t['misc']['vals']['x'] for t in trials.trials]
ys = [t['result']['loss'] for t in trials.trials]
ax.scatter(xs, ys, s=20, linewidth=0.01, alpha=0.75)
ax.set_title('$val$ $vs$ $x$ ', fontsize=18)
ax.set_xlabel('$x$', fontsize=16)
ax.set_ylabel('$val$', fontsize=16)

loss vs. val
这就是我们期望的,因为函数y(x) = x**2是确定性的。
最后,让我们尝试一个更复杂的示例,使用更多的随机性和更多的参数。

鸢尾花数据集(The Iris Dataset)

在本节中,我们将介绍在经典数据集Iris上使用hyperopt进行参数调优的4个完整示例。我们将介绍k近邻(KNN)、支持向量机(SVM)、决策树和随机森林。注意,由于我们试图最大化交叉验证的准确性(下面代码中的acc),我们必须为hyperopt对这个值进行取负数,因为hyperopt只知道如何最小化函数。最小化函数f等于最大化函数f的复数。
对于这项任务,我们将使用经典的Iris数据集,并进行一些有监督的机器学习。有4个输入特性和3个输出类。这些数据被标记为属于0类、1类或2类,它们映射到不同种类的鸢尾花。输入有4列:萼片长度(sepal length)、萼片宽度(sepal width)、花瓣长度(petal length)和花瓣宽度(pedal width)。输入单位是厘米。我们将使用这4个特性来学习预测三个输出类之一的模型。由于数据是由sklearn提供的,因此它有一个很好的DESCR属性,提供了关于数据集的详细信息。

print iris.feature_names # input names
print iris.target_names # output names
print iris.DESCR # everything else

让我们通过可视化特性和类来更好地了解数据,使用下面的代码。如果还没有安装seaborn,请不要忘记安装pip install seaborn。

import seaborn as sns
sns.set(style="whitegrid", palette="husl")

iris = sns.load_dataset("iris")
print iris.head()

iris = pd.melt(iris, "species", var_name="measurement")
print iris.head()

f, ax = plt.subplots(1, figsize=(15,10))
sns.stripplot(x="measurement", y="value", hue="species", data=iris, jitter=True, edgecolor="white", ax=ax)

如图:
iris

K最近邻(K-Nearest Neighbors)

我们现在使用hyperopt找到k近邻(KNN)机器学习模型的最佳参数。KNN模型根据训练数据集中k个最近的数据点的多数类,将测试集中的数据点进行分类。
关于这个算法的更多信息可以在这里找到。下面的代码包含了我们已经讨论过的所有内容。

from sklearn import datasets
iris = datasets.load_iris()
X = iris.data
y = iris.target

def hyperopt_train_test(params):
    clf = KNeighborsClassifier(**params)
    return cross_val_score(clf, X, y).mean()

space4knn = {
    'n_neighbors': hp.choice('n_neighbors', range(1,100))
}

def f(params):
    acc = hyperopt_train_test(params)
    return {'loss': -acc, 'status': STATUS_OK}

trials = Trials()
best = fmin(f, space4knn, algo=tpe.suggest, max_evals=100, trials=trials)
print 'best:'
print best

现在我们来看看输出图。y轴是交叉验证得分,x轴是k-最近邻中的k值。下面是代码及其图像:

f, ax = plt.subplots(1)#, figsize=(10,10))
xs = [t['misc']['vals']['n_neighbors'] for t in trials.trials]
ys = [-t['result']['loss'] for t in trials.trials]
ax.scatter(xs, ys, s=20, linewidth=0.01, alpha=0.5)
ax.set_title('Iris Dataset - KNN', fontsize=18)
ax.set_xlabel('n_neighbors', fontsize=12)
ax.set_ylabel('cross validation accuracy', fontsize=12)

knn
当k大于63时,准确率急剧下降。这是由于数据集中每个类的数量。这三个类中的每个类只有50个实例。因此,让我们通过将’n_neighbors’的值限制为较小的值进行深入研究。

from sklearn import datasets
iris = datasets.load_iris()
X = iris.data
y = iris.target

def hyperopt_train_test(params):
    clf = KNeighborsClassifier(**params)
    return cross_val_score(clf, X, y).mean()

space4knn = {
    'n_neighbors': hp.choice('n_neighbors', range(1,50))
}

def f(params):
    acc = hyperopt_train_test(params)
    return {'loss': -acc, 'status': STATUS_OK}

trials = Trials()
best = fmin(f, space4knn, algo=tpe.suggest, max_evals=100, trials=trials)
print 'best:'
print best

下面是当我们运行相同的可视化代码时得到的结果:
knn-2
现在我们可以清楚地看到k在k = 4处有一个最佳值。

上面的模型不做任何预处理。让我们对我们的特性进行规范化和缩放看看这是否有帮助。使用这段代码:

# now with scaling as an option
from sklearn import datasets
iris = datasets.load_iris()
X = iris.data
y = iris.target

def hyperopt_train_test(params):
    X_ = X[:]

    if 'normalize' in params:
        if params['normalize'] == 1:
            X_ = normalize(X_)
            del params['normalize']

    if 'scale' in params:
        if params['scale'] == 1:
            X_ = scale(X_)
            del params['scale']

    clf = KNeighborsClassifier(**params)
    return cross_val_score(clf, X_, y).mean()

space4knn = {
    'n_neighbors': hp.choice('n_neighbors', range(1,50)),
    'scale': hp.choice('scale', [0, 1]),
    'normalize': hp.choice('normalize', [0, 1])
}

def f(params):
    acc = hyperopt_train_test(params)
    return {'loss': -acc, 'status': STATUS_OK}

trials = Trials()
best = fmin(f, space4knn, algo=tpe.suggest, max_evals=100, trials=trials)
print 'best:'
print best

像这样画出参数:

parameters = ['n_neighbors', 'scale', 'normalize']
cols = len(parameters)
f, axes = plt.subplots(nrows=1, ncols=cols, figsize=(15,5))
cmap = plt.cm.jet
for i, val in enumerate(parameters):
    xs = np.array([t['misc']['vals'][val] for t in trials.trials]).ravel()
    ys = [-t['result']['loss'] for t in trials.trials]
    xs, ys = zip(\*sorted(zip(xs, ys)))
    ys = np.array(ys)
    axes[i].scatter(xs, ys, s=20, linewidth=0.01, alpha=0.75, c=cmap(float(i)/len(parameters)))
    axes[i].set_title(val)

knn-3
我们发现,数据的缩放和/或规范化并不能提高预测的准确性。k的最佳值为4,准确率为98.6%。

这对于一个简单模型KNN的参数调优非常有用。让我们看看支持向量机(SVM)能做些什么。

支持向量机 (SVM)

由于这是一个分类任务,我们将使用sklearn的SVC类。这是代码:

iris = datasets.load_iris()
X = iris.data
y = iris.target

def hyperopt_train_test(params):
    X_ = X[:]

    if 'normalize' in params:
        if params['normalize'] == 1:
            X_ = normalize(X_)
            del params['normalize']

    if 'scale' in params:
        if params['scale'] == 1:
            X_ = scale(X_)
            del params['scale']

    clf = SVC(**params)
    return cross_val_score(clf, X_, y).mean()

space4svm = {
    'C': hp.uniform('C', 0, 20),
    'kernel': hp.choice('kernel', ['linear', 'sigmoid', 'poly', 'rbf']),
    'gamma': hp.uniform('gamma', 0, 20),
    'scale': hp.choice('scale', [0, 1]),
    'normalize': hp.choice('normalize', [0, 1])
}

def f(params):
    acc = hyperopt_train_test(params)
    return {'loss': -acc, 'status': STATUS_OK}

trials = Trials()
best = fmin(f, space4svm, algo=tpe.suggest, max_evals=100, trials=trials)
print 'best:'
print best

parameters = ['C', 'kernel', 'gamma', 'scale', 'normalize']
cols = len(parameters)
f, axes = plt.subplots(nrows=1, ncols=cols, figsize=(20,5))
cmap = plt.cm.jet
for i, val in enumerate(parameters):
    xs = np.array([t['misc']['vals'][val] for t in trials.trials]).ravel()
    ys = [-t['result']['loss'] for t in trials.trials]
    xs, ys = zip(\*sorted(zip(xs, ys)))
    axes[i].scatter(xs, ys, s=20, linewidth=0.01, alpha=0.25, c=cmap(float(i)/len(parameters)))
    axes[i].set_title(val)
    axes[i].set_ylim([0.9, 1.0])

下面是我们得到的:
svm
同样,缩放和规范化也没有帮助。核函数的首选为最佳(linear),最佳C值为1.4168540399911616,最佳伽玛值为15.04230279483486。该参数集的分类准确率达到99.3%。

决策树(Decision Trees)

我们将只尝试对决策树的几个参数进行优化。这是代码。

iris = datasets.load_iris()
X_original = iris.data
y_original = iris.target

def hyperopt_train_test(params):
    X_ = X[:]
    if 'normalize' in params:
        if params['normalize'] == 1:
            X_ = normalize(X_)
            del params['normalize']

    if 'scale' in params:
        if params['scale'] == 1:
            X_ = scale(X_)
            del params['scale']
    clf = DecisionTreeClassifier(**params)
    return cross_val_score(clf, X, y).mean()

space4dt = {
    'max_depth': hp.choice('max_depth', range(1,20)),
    'max_features': hp.choice('max_features', range(1,5)),
    'criterion': hp.choice('criterion', ["gini", "entropy"]),
    'scale': hp.choice('scale', [0, 1]),
    'normalize': hp.choice('normalize', [0, 1])
}

def f(params):
acc = hyperopt_train_test(params)
return {'loss': -acc, 'status': STATUS_OK}

trials = Trials()
best = fmin(f, space4dt, algo=tpe.suggest, max_evals=300, trials=trials)
print 'best:'
print best

输出如下,准确率为97.3%:

{'max_features': 1, 'normalize': 0, 'scale': 0, 'criterion': 0, 'max_depth': 17}

如图我们可以看到,在不同的尺度值、标准化值和标准值下,性能几乎没有差别。

parameters = ['max_depth', 'max_features', 'criterion', 'scale', 'normalize'] # decision tree
cols = len(parameters)
f, axes = plt.subplots(nrows=1, ncols=cols, figsize=(20,5))
cmap = plt.cm.jet
for i, val in enumerate(parameters):
    xs = np.array([t['misc']['vals'][val] for t in trials.trials]).ravel()
    ys = [-t['result']['loss'] for t in trials.trials]
    xs, ys = zip(\*sorted(zip(xs, ys)))
    ys = np.array(ys)
    axes[i].scatter(xs, ys, s=20, linewidth=0.01, alpha=0.5, c=cmap(float(i)/len(parameters)))
    axes[i].set_title(val)
    #axes[i].set_ylim([0.9,1.0])

dt

随机森林(Random Forests)

让我们看看集成分类器Random Forest发生了什么,它只是一组针对不同大小的数据分区训练的决策树,每个分区对一个输出类进行投票,并选择多数派类作为预测。

iris = datasets.load_iris()
X_original = iris.data
y_original = iris.target

def hyperopt_train_test(params):
    X_ = X[:]
    if 'normalize' in params:
        if params['normalize'] == 1:
            X_ = normalize(X_)
            del params['normalize']

    if 'scale' in params:
        if params['scale'] == 1:
            X_ = scale(X_)
            del params['scale']
    clf = RandomForestClassifier(**params)
    return cross_val_score(clf, X, y).mean()

space4rf = {
    'max_depth': hp.choice('max_depth', range(1,20)),
    'max_features': hp.choice('max_features', range(1,5)),
    'n_estimators': hp.choice('n_estimators', range(1,20)),
    'criterion': hp.choice('criterion', ["gini", "entropy"]),
    'scale': hp.choice('scale', [0, 1]),
    'normalize': hp.choice('normalize', [0, 1])
}

best = 0
def f(params):
    global best
    acc = hyperopt_train_test(params)
    if acc > best:
    best = acc
    print 'new best:', best, params
    return {'loss': -acc, 'status': STATUS_OK}

trials = Trials()
best = fmin(f, space4rf, algo=tpe.suggest, max_evals=300, trials=trials)
print 'best:'
print best

同样,我们只得到97.3%的准确率,和决策树一样。

下面是绘制参数的代码:

parameters = ['n_estimators', 'max_depth', 'max_features', 'criterion', 'scale', 'normalize']
f, axes = plt.subplots(nrows=2, ncols=3, figsize=(15,10))
cmap = plt.cm.jet
for i, val in enumerate(parameters):
    print i, val
    xs = np.array([t['misc']['vals'][val] for t in trials.trials]).ravel()
    ys = [-t['result']['loss'] for t in trials.trials]
    xs, ys = zip(\*sorted(zip(xs, ys)))
    ys = np.array(ys)
    axes[i/3,i%3].scatter(xs, ys, s=20, linewidth=0.01, alpha=0.5, c=cmap(float(i)/len(parameters)))
    axes[i/3,i%3].set_title(val)
    #axes[i/3,i%3].set_ylim([0.9,1.0])

rf

所有模型(All Together Now)

虽然自动调优一个模型的参数(例如SVM或KNN)既有趣又有指导意义,但更有用的是一次调优所有的参数并得到一个总体上最好的模型。这使我们能够同时比较所有的参数和所有的模型,这给了我们最好的模型。这是代码。

digits = datasets.load_digits()
X = digits.data
y = digits.target
print X.shape, y.shape

def hyperopt_train_test(params):
    t = params['type']
    del params['type']
    if t == 'naive_bayes':
        clf = BernoulliNB(**params)
    elif t == 'svm':
        clf = SVC(**params)
    elif t == 'dtree':
        clf = DecisionTreeClassifier(**params)
    elif t == 'knn':
        clf = KNeighborsClassifier(**params)
    else:
        return 0
    return cross_val_score(clf, X, y).mean()

space = hp.choice('classifier_type', [
    {
        'type': 'naive_bayes',
        'alpha': hp.uniform('alpha', 0.0, 2.0)
    },
    {
        'type': 'svm',
        'C': hp.uniform('C', 0, 10.0),
        'kernel': hp.choice('kernel', ['linear', 'rbf']),
        'gamma': hp.uniform('gamma', 0, 20.0)
    },
    {
        'type': 'randomforest',
        'max_depth': hp.choice('max_depth', range(1,20)),
        'max_features': hp.choice('max_features', range(1,5)),
        'n_estimators': hp.choice('n_estimators', range(1,20)),
        'criterion': hp.choice('criterion', ["gini", "entropy"]),
        'scale': hp.choice('scale', [0, 1]),
        'normalize': hp.choice('normalize', [0, 1])
    },
    {
        'type': 'knn',
        'n_neighbors': hp.choice('knn_n_neighbors', range(1,50))
    }
])

count = 0
best = 0
def f(params):
    global best, count
    count += 1
    acc = hyperopt_train_test(params.copy())
    if acc > best:
        print 'new best:', acc, 'using', params['type']
        best = acc
    if count % 50 == 0:
        print 'iters:', count, ', acc:', acc, 'using', params
    return {'loss': -acc, 'status': STATUS_OK}

trials = Trials()
best = fmin(f, space, algo=tpe.suggest, max_evals=1500, trials=trials)
print 'best:'
print best

这段代码需要一段时间才能运行,因为我们增加了计算次数:max_evals=1500。当发现新的最佳精度时,还会增加输出以更新。奇怪的是,为什么使用这种方法没有找到我们在上面找到的最佳模型:SVM的kernel=linear,C=1.416,和gamma=15.042。

总结

我们已经介绍了一些简单的例子,比如最小化确定性线性函数,以及一些复杂的例子,比如调整随机森林参数。hyperopt的文档在这里。另一个关于hyperopt的好博客是FastML的。hyperopt作者撰写的SciPy会议论文是Hyperopt: A Python Library for Optimizing the Hyperparameters of Machine Learning Algorithms,附带一个视频教程。对工程细节的一种更科学的处理方法是Making a Science of Model Search
这篇文章中的技术可以应用于除机器学习之外的许多领域,例如在epsilon的epsilon-greedy multi-armed bandit调优参数,或传递给图形生成器的参数,以形成具有某些特性的合成网络。稍后我们将对此进行更多的讨论。

  • 19
    点赞
  • 121
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Hyperopt是一个Python库,用于使用贝叶斯优化算法来调整机器学习模型的超参数。下面是Hyperopt在调整XGBoost超参数时的步骤: 1. 定义参数空间:首先需要定义需要调整的超参数以及其取值范围。例如,可以使用Uniform分布来定义连续型参数的取值范围,使用qUniform分布来定义整数型参数的取值范围。 2. 定义评估函数:评估函数是用来计算模型的性能指标的,例如准确率、AUC等。在每次迭代中,Hyperopt会根据当前超参数的取值调用评估函数来计算模型的性能指标。 3. 定义搜索算法:Hyperopt支持多种搜索算法,例如随机搜索、贝叶斯优化等。在这里,我们选择使用贝叶斯优化算法。 4. 运行优化器:定义好参数空间、评估函数和搜索算法后,就可以运行Hyperopt优化器来寻找最优超参数组合了。在每次迭代中,Hyperopt会根据当前的超参数取值计算模型的性能指标,并根据贝叶斯优化算法来更新超参数的取值,直到达到预设的最大迭代次数或收敛为止。 下面是一个使用Hyperopt优化XGBoost超参数的示例代码: ```python from hyperopt import fmin, tpe, hp from sklearn.datasets import load_boston from sklearn.metrics import mean_squared_error from sklearn.model_selection import train_test_split import xgboost as xgb # 加载数据集 data = load_boston() X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.2, random_state=42) # 定义参数空间 space = { 'max_depth': hp.quniform('max_depth', 3, 10, 1), 'learning_rate': hp.loguniform('learning_rate', -5, 0), 'n_estimators': hp.quniform('n_estimators', 50, 200, 1), 'min_child_weight': hp.quniform('min_child_weight', 1, 10, 1), 'subsample': hp.uniform('subsample', 0.5, 1), 'gamma': hp.uniform('gamma', 0, 1), 'colsample_bytree': hp.uniform('colsample_bytree', 0.5, 1), 'reg_alpha': hp.uniform('reg_alpha', 0, 1), 'reg_lambda': hp.uniform('reg_lambda', 0, 1), } # 定义评估函数 def objective(params): model = xgb.XGBRegressor(**params) model.fit(X_train, y_train) y_pred = model.predict(X_test) mse = mean_squared_error(y_test, y_pred) return mse # 定义搜索算法 algo = tpe.suggest # 运行优化器 best = fmin(fn=objective, space=space, algo=algo, max_evals=100) print(best) ``` 在这个示例中,我们使用Hyperopt库来优化XGBoost回归模型的超参数。我们首先加载了Boston房价数据集,并将其分成训练集和测试集。然后,我们定义了需要调整的超参数以及其取值范围,并定义了评估函数。最后,我们选择使用tpe.suggest算法来搜索最优超参数,并将最优超参数打印出来。 需要注意的是,由于贝叶斯优化算法是一种启发式算法,因此在每次运行时得到的最优超参数可能会有所不同。因此,为了确保得到的结果是稳定的,通常需要运行多次优化器并取平均值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值