精华内容
下载资源
问答
  • 2017-06-20 21:12:41
    

    
    

    1.简介

    Hyperopt是一个Python库,结合MongoDB可以进行分布式调参,快速找到相对较优的参数。安装的时候需要指定dev版本才能使用模拟退火调参,也支持暴力调参、随机调参等策略。

    2.Win7安装

    • 软件
    • 安装
      • MongoDB一路默认安装即可
      • Hyperopt先进行解压,然后通过命令 python setup.py install

    3.Linux服务器安装

    • 软件

      • Hyperopt 同上
      • mongodb 地址 如果读者用的是Ubuntu或者其他版本可以在官网上下载,然后下面的命令注意改下文件名。MongoDB官网

      • 注:在运行下面的示例时,我这边报错了(no moudle named networkx),不一定都会遇到,如果遇到了,可以通过pip install networkx解决即可

    • 安装

      • Hyperopt安装同上
      • MongoDB先解压,然后在目录下输入如下命令(PS:似乎直接用pip install pymongo也可以)
      • (cd bin && { for F in ../mongodb-linux-x86_64-3.2.7/bin/* ; do echo "linking $F" ; ln -s $F ; done }


    4.简单使用

    http://blog.csdn.net/a819825294/article/details/51775418


    5.更多官方文档链接




    • 24
    • 25


    更多相关内容
  • Hyperopt: Distributed Hyperparameter Optimization Hyperopt is a Python library for serial and parallel optimization over awkward search spaces, which may include real-valued, discrete, and ...
  • Hyperopt入门

    万次阅读 多人点赞 2018-12-05 15:51:51
    当我们创建好模型后,还要调整各个模型的参数,才找到最好的匹配。即使模型还可以,如果它的参数设置不匹配,同样无法输出好的结果。... 而Hyperopt是一种通过贝叶斯优化来调整参数的工具,该方法较快的速...

    当我们创建好模型后,还要调整各个模型的参数,才找到最好的匹配。即使模型还可以,如果它的参数设置不匹配,同样无法输出好的结果。 常用的调参方式有Grid search 和 Random search ,Grid search 是全空间扫描,所以比较慢,Random search 虽然快,但可能错失空间上的一些重要的点,精度不够。 而Hyperopt是一种通过贝叶斯优化来调整参数的工具,该方法较快的速度,并有较好的效果。此外,Hyperopt结合MongoDB可以进行分布式调参,快速找到相对较优的参数。安装的时候需要指定dev版本才能使用模拟退火调参,也支持暴力调参、随机调参等策略。

    (贝叶斯优化,又叫序贯模型优化(Sequential model-based optimization,SMBO),是最有效的函数优化方法之一。与共轭梯度下降法等标准优化策略相比,SMBO的优势有:利用平滑性而无需计算梯度;可处理实数、离散值、条件变量等;可处理大量变量并行优化。)

    Let's go!!!

    1 安装

    pip install hyperopt

    安装hyperopt时也会安装 networkx,如果在调用时出现 TypeError: 'generator' object is not subscriptable 报错,可以将其换成1.11版本。

    pip uninstall networkx
    pip install networkx==1.11

    2 重点知识

    2.1 fmin

    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
    

    输出结果为:{'x': 0.0006154621520631152}

    函数fmin首先接受一个函数来最小化,记为fn,在这里用一个函数lambda x: x来指定。该函数可以是任何有效的值返回函数,例如回归中的平均绝对误差。

    下一个参数指定搜索空间,在本例中,它是0到1之间的连续数字范围,由hp.uniform('x', 0, 1)指定。hp.uniform是一个内置的hyperopt函数,它有三个参数:名称x,范围的下限和上限01

    algo参数指定搜索算法,本例中tpe表示 tree of Parzen estimators。该主题超出了本文的范围,但有数学背景的读者可以细读这篇文章。algo参数也可以设置为hyperopt.random,但是这里我们没有涉及,因为它是众所周知的搜索策略。

    最后,我们指定fmin函数将执行的最大评估次数max_evals。这个fmin函数将返回一个python字典。

    当我们调整max_evals=1000时,输出结果为:{'x': 3.7023587264309516e-06},可以发现结果更接近于0。

    为了更好的理解,可以看下面这个更复杂一些的例子。

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

    输出结果为:{'x': 1.007633842139922}

    2.2 space

    对于变量的变化范围与取值概率,有以下几类。

     看个例子,

    from hyperopt import hp
    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.3901709472842074, 'x': 0.4335747017293238, 'name': 'bob'}

    2.3 通过 Trials 捕获信息

    Trials用来记录每次eval的时候,具体使用了什么参数以及相关的返回值。这时候,fn的返回值变为dict,除了loss,还有一个status。Trials对象将数据存储为一个BSON对象,可以利用MongoDB做分布式运算。

    from hyperopt import fmin, tpe, hp, STATUS_OK, Trials
    from matplotlib import pyplot as plt
    
    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的返回,会统计它的loss值,而对于STATUS_FAIL的返回,则会忽略。

    输出结果如下,

    best: {'x': -0.0025882455372094326}
    trials:
    {'refresh_time': datetime.datetime(2018, 12, 5, 3, 5, 43, 152000), 'book_time': datetime.datetime(2018, 12, 5, 3, 5, 43, 152000), 'misc': {'tid': 0, 'idxs': {'x': [0]}, 'cmd': ('domain_attachment', 'FMinIter_Domain'), 'vals': {'x': [-2.511797855178682]}, 'workdir': None}, 'state': 2, 'tid': 0, 'exp_key': None, 'version': 0, 'result': {'status': 'ok', 'loss': 6.309128465280228}, 'owner': None, 'spec': None}
    {'refresh_time': datetime.datetime(2018, 12, 5, 3, 5, 43, 153000), 'book_time': datetime.datetime(2018, 12, 5, 3, 5, 43, 153000), 'misc': {'tid': 1, 'idxs': {'x': [1]}, 'cmd': ('domain_attachment', 'FMinIter_Domain'), 'vals': {'x': [3.43836093884876]}, 'workdir': None}, 'state': 2, 'tid': 1, 'exp_key': None, 'version': 0, 'result': {'status': 'ok', 'loss': 11.822325945800927}, 'owner': None, 'spec': None}

    可以通过这里面的值,把一些变量与loss的点绘图,来看匹配度。或者tid与变量绘图,看它搜索的位置收敛(非数学意义上的收敛)情况。 
    trials有这几种:

    • trials.trials - a list of dictionaries representing everything about the search
    • trials.results - a list of dictionaries returned by ‘objective’ during the search
    • trials.losses() - a list of losses (float for each ‘ok’ trial)
    • trials.statuses() - a list of status strings
      我们可以将上述trials进行可视化,值 vs. 时间与损失 vs. 值。
      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)

    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)
    

    3 Hyperopt应用

    3.1 K近邻

    需要注意的是,由于我们试图最大化交叉验证的准确率,而hyperopt只知道如何最小化函数,所以必须对准确率取负。最小化函数f与最大化f的负数是相等的。

    from sklearn.datasets import load_iris
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.cross_validation import cross_val_score
    from hyperopt import hp,STATUS_OK,Trials,fmin,tpe
    from matplotlib import pyplot as plt
    
    iris=load_iris()
    X=iris.data
    y=iris.target
    
    def hyperopt_train(params):
        clf=KNeighborsClassifier(**params)
        return cross_val_score(clf,X,y).mean()
        
    space_knn={'n_neighbors':hp.choice('n_neighbors',range(1,100))}
    
    def f(parmas):
        acc=hyperopt_train(parmas)
        return {'loss':-acc,'status':STATUS_OK}
    
    trials=Trials()
    best=fmin(f,space_knn,algo=tpe.suggest,max_evals=100,trials=trials)
    print 'best',best    

    输出结果为:best {'n_neighbors': 4}

    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)
    

    k 大于63后,准确率急剧下降。这是因为数据集中每个类的数量。这三个类中每个类只有50个实例。所以让我们将'n_neighbors'的值限制为较小的值来进一步探索。 

    'n_neighbors': hp.choice('n_neighbors', range(1,50))

     重新运行后,得到的图像如下,

     现在我们可以清楚地看到k的最佳值为4

    3.2 支持向量机(SVM)

    由于这是一个分类任务,我们将使用sklearnSVC类。代码如下

    from sklearn.datasets import load_iris
    from sklearn.cross_validation import cross_val_score
    from hyperopt import hp,STATUS_OK,Trials,fmin,tpe
    from matplotlib import pyplot as plt
    from sklearn.svm import SVC 
    import numpy as np
    
    iris=load_iris()
    X=iris.data
    y=iris.target
    
    def hyperopt_train_test(params):
        clf =SVC(**params)
        return cross_val_score(clf, X, y).mean()
    
    space_svm = {
        'C': hp.uniform('C', 0, 20),
        'kernel': hp.choice('kernel', ['linear', 'sigmoid', 'poly', 'rbf']),
        'gamma': hp.uniform('gamma', 0, 20),
    }
    
    def f(params):
        acc = hyperopt_train_test(params)
        return {'loss': -acc, 'status': STATUS_OK}
    
    trials = Trials()
    best = fmin(f, space_svm, algo=tpe.suggest, max_evals=100, trials=trials)
    print 'best:',best
    
    parameters = ['C', 'kernel', 'gamma']
    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]
        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])

    输出结果为:best:{'kernel': 3, 'C': 3.6332677642526985, 'gamma': 2.0192849151350796} 

    3.3 决策树

    我们将尝试只优化决策树的一些参数。代码如下。

    from sklearn.datasets import load_iris
    from sklearn.cross_validation import cross_val_score
    from hyperopt import hp,STATUS_OK,Trials,fmin,tpe
    from matplotlib import pyplot as plt
    from sklearn.tree import DecisionTreeClassifier
    import numpy as np
    
    iris=load_iris()
    X=iris.data
    y=iris.target
    
    def hyperopt_train_test(params):
        clf = DecisionTreeClassifier(**params)
        return cross_val_score(clf, X, y).mean()
    
    space_dt = {
        'max_depth': hp.choice('max_depth', range(1,20)),
        'max_features': hp.choice('max_features', range(1,5)),
        'criterion': hp.choice('criterion', ["gini", "entropy"]),
    }
    
    def f(params):
        acc = hyperopt_train_test(params)
        return {'loss': -acc, 'status': STATUS_OK}
    
    trials = Trials()
    best = fmin(f, space_dt, algo=tpe.suggest, max_evals=300, trials=trials)
    print 'best:',best
    
    parameters = ['max_depth', 'max_features', 'criterion'] # 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]
        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])

    输出结果为:best:{'max_features': 1, 'criterion': 1, 'max_depth': 13}

    3.4 随机森林

    让我们来看看集成分类器随机森林发生了什么,随机森林只是在不同分区数据上训练的决策树集合,每个分区都对输出类进行投票,并将绝大多数类的选择为预测。

    from sklearn.datasets import load_iris
    from sklearn.cross_validation import cross_val_score
    from hyperopt import hp,STATUS_OK,Trials,fmin,tpe
    from matplotlib import pyplot as plt
    from sklearn.ensemble import RandomForestClassifier
    import numpy as np
    
    iris=load_iris()
    X=iris.data
    y=iris.target
    
    def hyperopt_train_test(params):
        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"]),
    }
    
    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:',best
    
    parameters = ['n_estimators', 'max_depth', 'max_features', 'criterion']
    f, axes = plt.subplots(nrows=1,ncols=4, figsize=(20,5))
    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]
        ys = np.array(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)

    输出结果为:best: {'max_features': 3, 'n_estimators': 11, 'criterion': 1, 'max_depth': 2}

     4 多模型调优

    从众多模型和众多参数中找到最优模型及其参数

    from sklearn.datasets import load_iris
    from sklearn.cross_validation import cross_val_score
    from hyperopt import hp,STATUS_OK,Trials,fmin,tpe
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.naive_bayes import BernoulliNB
    from sklearn.svm import SVC
    
    iris=load_iris()
    X=iris.data
    y=iris.target
    
    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])
        },
        {
            '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:',best
    

    输出结果为:best:{'kernel': 0, 'C': 1.4211568317201784, 'classifier_type': 1, 'gamma': 8.74017707300719} 

    5 参考

    展开全文
  • hyperopt是一个Python库,主要使用①随机搜索算法②模拟退火算法③TPE算法来对某个算法模型的最佳参数进行智能搜索,它的全称是Hyperparameter Optimization。本文将介绍一种快速有效的方法用于实现机器学习模型的调...

    hyperopt是一个Python库,主要使用

    ①随机搜索算法
    ②模拟退火算法
    ③TPE算法
    来对某个算法模型的最佳参数进行智能搜索,它的全称是Hyperparameter Optimization。

    本文将介绍一种快速有效的方法用于实现机器学习模型的调参。有两种常用的调参方法:网格搜索和随机搜索。每一种都有自己的优点和缺点。网格搜索速度慢,但在搜索整个搜索空间方面效果很好,而随机搜索很快,但可能会错过搜索空间中的重要点。幸运的是,还有第三种选择:贝叶斯优化。本文我们将重点介绍贝叶斯优化的一个实现,一个名为hyperopt的 Python 模块。

    使用贝叶斯优化进行调参可以让我们获得给定模型的最佳参数,例如逻辑回归模型。这也使我们能够执行最佳的模型选择。通常机器学习工程师或数据科学家将为少数模型(如决策树,支持向量机和 K 近邻)执行某种形式(网格搜索或随机搜索)的手动调参,然后比较准确率并选择最佳的一个来使用。该方法可能比较的是次优模型。也许数据科学家找到了决策树的最优参数,但却错过了 SVM 的最优参数。

    这意味着他们的模型比较是有缺陷的。如果 SVM 参数调整得很差,K 近邻可能每次都会击败 SVM。贝叶斯优化允许数据科学家找到所有模型的最佳参数,并因此比较最佳模型。这会得到更好的模型选择,因为你比较的是最佳的 k 近邻和最佳的决策树。只有这样你才能非常自信地进行模型选择,确保选择并使用的是实际最佳的模型。

    本文涵盖的主题有:

    1. 目标函数

    2. 搜索空间

    3. 存储评估试验

    4. 可视化

    5. 应用案例

    要使用下面的代码,你必须安装hyperoptpymongo

    什么是Hyperopt

    Hyperopt是一个强大的python库,用于超参数优化,由jamesbergstra开发。Hyperopt使用贝叶斯优化的形式进行参数调整,允许你为给定模型获得最佳参数。它可以在大范围内优化具有数百个参数的模型。

    Hyperopt的特性

    Hyperopt包含4个重要的特性,你需要知道,以便运行你的第一个优化。

    搜索空间

    hyperopt有不同的函数来指定输入参数的范围,这些是随机搜索空间。选择最常用的搜索选项:

    • hp.choice(label, options)-这可用于分类参数,它返回其中一个选项,它应该是一个列表或元组。示例:hp.choice(“criterion”, [“gini”,”entropy”,])

    • hp.randint(label, upper)-可用于整数参数,它返回范围(0,upper)内的随机整数。示例:hp.randint(“max_features”,50)

    • hp.uniform(label, low, high)-它返回一个介于low和high之间的值。示例:hp.uniform(“max_leaf_nodes”,1,10)

    你可以使用的其他选项包括:

    • hp.normal(label, mu, sigma)-这将返回一个实际值,该值服从均值为mu和标准差为sigma的正态分布

    • hp.qnormal(label, mu, sigma, q)-返回一个类似round(normal(mu, sigma) / q) * q的值

    • hp.lognormal(label, mu, sigma)-返回exp(normal(mu, sigma))

    • hp.qlognormal(label, mu, sigma, q) -返回一个类似round(exp(normal(mu, sigma)) / q) * q的值

    注:每个可优化的随机表达式都有一个标签(例如n_estimators)作为第一个参数。这些标签用于在优化过程中将参数选择返回给调用者。

    目标函数

    这是一个最小化函数,它从搜索空间接收超参数值作为输入并返回损失。这意味着在优化过程中,我们使用选定的超参数值训练模型并预测目标特征,然后评估预测误差并将其返回给优化器。优化器将决定要检查哪些值并再次迭代。你将在一个实际例子中学习如何创建一个目标函数。

    一个简单的例子

    假设你有一个定义在某个范围内的函数,并且想把它最小化。也就是说,你想找到产生最低输出值的输入值。下面的简单例子找到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,在这里用一个匿名函数lambda x: x来指定。该函数可以是任何有效的值返回函数,例如回归中的平均绝对误差。

    下一个参数指定搜索空间,在本例中,它是0到1之间的连续数字范围,由hp.uniform('x', 0, 1)指定。hp.uniform是一个内置的hyperopt函数,它有三个参数:名称x,范围的下限和上限01

    algo参数指定搜索算法,本例中tpe表示 tree of Parzen estimators。该主题超出了本文的范围,但有数学背景的读者可以细读这篇[1]文章。algo参数也可以设置为hyperopt.random,但是这里我们没有涉及,因为它是众所周知的搜索策略。但在未来的文章中我们可能会涉及。

    最后,我们指定fmin函数将执行的最大评估次数max_evals。这个fmin函数将返回一个python字典。

    上述函数的一个输出示例是{'x': 0.000269455723739237}

    以下是该函数的图。红点是我们试图找到的点。

    a0df7abd7f0f7e476110f9513e31c750.png

    更复杂的例子

    这有一个更复杂的目标函数:lambda x: (x-1)**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}

    这是函数图。

    4bbbf48333df04a5c7bd2b747cc6763d.png

    有时也许我们想要最大化目标函数,而不是最小化它。为此,我们只需要返回函数的负数。例如,我们有函数y(x) = -(x**2)

    6cabccd689d267c499259959dd6f98f5.png

    我们如何解决这个问题?我们采用目标函数lambda x: -(x**2)并返回负值,只需给出lambda x: -1*-(x**2)或者lambda x: (x**2)即可。

    这里有一个和例子1类似,但我们不是最小化,而是试图最大化。

    ac1abe7a7bf1509cfd807a7106f044ee.png

    这里有许多(无限多且无限范围)局部最小值的函数,我们也试图将其最大化:

    5bc7e786c16ca336f3c28e3326839c3d.png

    搜索空间

    hyperopt模块包含一些方便的函数来指定输入参数的范围。我们已经见过hp.uniform。最初,这些是随机搜索空间,但随着hyperopt更多的学习(因为它从目标函数获得更多反馈),通过它认为提供给它最有意义的反馈,会调整并采样初始搜索空间的不同部分。

    以下内容将在本文中使用:

    1. hp.choice(label, options) 其中options应是 python 列表或元组。

    2. hp.normal(label, mu, sigma) 其中musigma分别是均值和标准差。

    3. hp.uniform(label, low, high) 其中lowhigh是范围的下限和上限。

    其他也是可用的,例如hp.normalhp.lognormalhp.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'}

    尝试运行几次并查看不同的样本。

    通过 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_OKTrials是新导入的。Trials对象允许我们在每个时间步存储信息。然后我们可以将它们打印出来,并在给定的时间步查看给定参数的函数评估值。

    这是上面代码的一个输出示例:

    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模块。我们不会在这里讨论细节,这是对于需要使用MongoDB进行分布式计算的hyperopt的高级选项,因此需要导入pymongo。回到上面的输出。tid是时间 id,即时间步,其值从0到max_evals-1。它随着迭代次数递增。'x'是键'vals'的值,其中存储的是每次迭代参数的值。'loss'是键'result'的值,其给出了该次迭代目标函数的值。

    我们用另一种方式来看看。

    可视化

    我们将在这里讨论两种类型的可视化:值 vs. 时间与损失 vs. 值。首先是值 vs. 时间。以下是绘制上述Trial.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,输出应该如下所示。

    a83efd4cbad0f85218a4f13aa6cf8d36.png

    我们可以看到,最初算法从整个范围中均匀地选择值,但随着时间的推移以及参数对目标函数的影响了解越来越多,该算法越来越聚焦于它认为会取得最大收益的区域-一个接近零的范围。它仍然探索整个解空间,但频率有所下降。

    现在让我们看看损失 vs. 值的图。

    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)
    b0e0e16204ee85f486d6f7d97413e712.png

    它给了我们所期望的,因为函数y(x)=x**2是确定的。

    总结一下,让我们尝试一个更复杂的例子,伴随更多的随机性和更多的参数。

    hyperopt调参案例

    在本节中,我们将介绍4个使用hyperopt在经典数据集 Iris 上调参的完整示例。我们将涵盖 K 近邻(KNN),支持向量机(SVM),决策树和随机森林。需要注意的是,由于我们试图最大化交叉验证的准确率(acc请参见下面的代码),而hyperopt只知道如何最小化函数,所以必须对准确率取负。最小化函数f与最大化f的负数是相等的。

    对于这项任务,我们将使用经典的Iris数据集,并进行一些有监督的机器学习。数据集有有4个输入特征和3个输出类别。数据被标记为属于类别0,1或2,其映射到不同种类的鸢尾花。输入有4列:萼片长度,萼片宽度,花瓣长度和花瓣宽度。输入的单位是厘米。我们将使用这4个特征来学习模型,预测三种输出类别之一。因为数据由sklearn提供,它有一个很好的DESCR属性,可以提供有关数据集的详细信息。尝试以下代码以获得更多细节信息。

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

    我们通过使用下面的代码可视化特征和类来更好地了解数据。如果你还没安装别忘了先执行pip install searborn

    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)

    这是图表:

    8e5846fc6599aca1ed2e27e354dfb865.png

    K 近邻

    我们现在将使用hyperopt来找到 K近邻(KNN)机器学习模型的最佳参数。KNN 模型是基于训练数据集中 k 个最近数据点的大多数类别对来自测试集的数据点进行分类。关于这个算法的更多信息可以参考这里。算法文档:机器学习 | 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 近邻个数。下面是代码和它的图像:

    f, ax = plt.subplots(1)#, figsize=(10,10))
    xs = [t['misc']['vals']['n'] 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)
    623bc3a2ff09d7cba6764a3049126851.png

    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)

    这是我们运行相同的可视化代码得到的结果:

    18c3978b4bae105146fc4014b8897c05.png

    现在我们可以清楚地看到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)
    5b9f1495af52d0eef2c4e9d11947ae0c.png

    我们看到缩放和/或归一化数据并不会提高预测准确率。k的最佳值仍然为4,这得到98.6%的准确率。

    所以这对于简单模型 KNN 调参很有用。让我们看看用支持向量机(SVM)能做什么。

    支持向量机(SVM)

    由于这是一个分类任务,我们将使用sklearnSVC类。算法文档:
    1、支持向量机1--线性SVM用于分类原理 
    2、支持向量机2--非线性SVM与核函数 
    3、一文掌握sklearn中的支持向量机
    超参数调整代码如下:

    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])

    这是我们得到的:

    e9b45b0bace1fac20b65b00795c693ac.png

    同样,缩放和归一化也没有帮助。核函数的首选是(linear),C的最佳值是1.4168540399911616gamma的最佳值是15.04230279483486。这组参数得到了99.3%的分类准确率。

    决策树

    我们将尝试只优化决策树的一些参数。算法介绍:
    1、机器学习 | 决策树模型(一)理论
    2、机器学习 | 决策树模型(二)实例 
    3、决策树算法大家庭:Random Forest、Adaboost、GBDT 算法总结
    调参数代码如下。

    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}

    以下是图表。我们可以看到,对于不同的scale值,normalizecriterion,性能几乎没有差别。

    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])
    4b178c4377f3a5f7aaa96e838bb885fa.png

    随机森林

    让我们来看看集成分类器随机森林发生了什么,随机森林只是在不同分区数据上训练的决策树集合,每个分区都对输出类进行投票,并将绝大多数类的选择为预测。随机森林模型详细文档:1、集成算法 | 随机森林分类模型   2、集成算法 | 随机森林回归模型  。

    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])

    96ce6f99d0b9158ddecd226d0d0d83be.png

    调参融合

    自动调整一个模型的参数(如SVM或KNN)非常有趣并且具有启发性,但同时调整它们并取得全局最佳模型则更有用。这使我们能够一次比较所有参数和所有模型,因此为我们提供了最佳模型。代码如下:

    # @公众号:数据STUDIO
    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。当找到新的最佳准确率时,它还会添加到输出用于更新。好奇为什么使用这种方法没有找到前面的最佳模型:参数为kernel=linearC=1.416gamma=15.042SVM

    LightGBM自动化调参

    下面我们利用hyperopt对lightgbm进行自动化调参,我们一共尝试一百个超参组合。算法文档:这次终于彻底理解了 LightGBM 原理及代码

    以下程序用时较长,可以根据情况增加或者减少尝试的超参数组合个数。

    注意我们的num_boost_round是通过early_stop自适应的,无需调参。

    导包等准备

    # @公众号:数据STUDIO
    import datetime
    import numpy as np
    from numpy.random import RandomState
    import pandas as pd
    import lightgbm as lgb
    from sklearn import datasets
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import accuracy_score,f1_score
    import matplotlib.pyplot as plt 
    from hyperopt import fmin,hp,Trials,space_eval,rand,tpe,anneal
    import warnings 
    warnings.filterwarnings('ignore')
    
    def printlog(info):
        nowtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        print("\n"+"=========="*8 + "%s"%nowtime)
        print(info+'...\n\n')

    读取数据

    printlog("step1: reading data...")
    
    # 读取dftrain,dftest
    breast = datasets.load_breast_cancer()
    df = pd.DataFrame(breast.data,
                      columns = [x.replace(' ','_') for x in breast.feature_names])
    df['label'] = breast.target
    df['mean_radius'] = df['mean_radius'].apply(lambda x:int(x))
    df['mean_texture'] = df['mean_texture'].apply(lambda x:int(x))
    dftrain,dftest = train_test_split(df)
    
    categorical_features = ['mean_radius','mean_texture']
    lgb_train = lgb.Dataset(dftrain.drop(['label'],axis = 1),label=dftrain['label'],
                            categorical_feature = categorical_features,free_raw_data=False)
    
    lgb_valid = lgb.Dataset(dftest.drop(['label'],axis = 1),label=dftest['label'],
                            categorical_feature = categorical_features,
                            reference=lgb_train,free_raw_data=False)

    搜索超参

    printlog("step2: searching parameters...")
    boost_round = 1000                   
    early_stop_rounds = 50
    
    params = {
        'learning_rate': 0.1,
        'boosting_type': 'gbdt',#'dart','rf'  
        'objective':'binary',
        'metric': ['auc'],
        'num_leaves': 31,
        'max_depth':  6,
        'min_data_in_leaf': 5,  
        'min_gain_to_split': 0,
        'reg_alpha':0,
        'reg_lambda':0,
        'feature_fraction': 0.9,
        'bagging_fraction': 0.8,
        'bagging_freq': 5,
        'feature_pre_filter':False,
        'verbose': -1
    }

    定义目标函数

    def hyperopt_objective(config):
        params.update(config)
        gbm = lgb.train(params,
                        lgb_train,
                        num_boost_round= boost_round,
                        valid_sets=(lgb_valid, lgb_train),
                        valid_names=('validate','train'),
                        early_stopping_rounds = early_stop_rounds,
                        verbose_eval = False)
        y_pred_test = gbm.predict(dftest.drop('label',axis = 1),
                                  num_iteration=gbm.best_iteration)
        val_score = f1_score(dftest['label'],y_pred_test>0.5)
        return -val_score

    带CV方法交叉验证

    若需要带交叉验证,则可以

    # @公众号:数据STUDIO
    def hyperopt_objective(config):
        params.update(config)
        gbm = lgb.train(params,
                        lgb_train,
                        num_boost_round= boost_round,
                        valid_sets=(lgb_valid, lgb_train),
                        valid_names=('validate','train'),
                        early_stopping_rounds = early_stop_rounds,
                        verbose_eval = False)
        num_round = 10
        res = lgb.cv(params,  # 如果lgb.LGBMRegressor.get_params()
                     lgb_train,
                     num_round,
                     nfold=5,
                     metrics='auc',
                     early_stopping_rounds=10)
        
        return min(res['auc-mean'])

    定义超参空间

    #可以根据需要,注释掉偏后的一些不太重要的超参
    spaces = {"learning_rate":hp.loguniform("learning_rate",np.log(0.001),np.log(0.5)),
              "boosting_type":hp.choice("boosting_type",['gbdt','dart','rf']),
              "num_leaves":hp.choice("num_leaves",range(15,128)),
              #"max_depth":hp.choice("max_depth",range(3,11)),
              #"min_data_in_leaf":hp.choice("min_data_in_leaf",range(1,50)),
              #"min_gain_to_split":hp.uniform("min_gain_to_split",0.0,1.0),
              #"reg_alpha": hp.uniform("reg_alpha", 0, 2),
              #"reg_lambda": hp.uniform("reg_lambda", 0, 2),
              #"feature_fraction":hp.uniform("feature_fraction",0.5,1.0),
              #"bagging_fraction":hp.uniform("bagging_fraction",0.5,1.0),
              #"bagging_freq":hp.choice("bagging_freq",range(1,20))
              }

    执行超参搜索

    # hyperopt支持如下搜索算法
    #随机搜索(hyperopt.rand.suggest)
    #模拟退火(hyperopt.anneal.suggest)
    #TPE算法(hyperopt.tpe.suggest,算法全称为Tree-structured Parzen Estimator Approach)
    trials = Trials()
    best = fmin(fn=hyperopt_objective, 
                space=spaces, 
                algo= tpe.suggest, 
                max_evals=100, 
                trials=trials
             rstate=RandomState(123)
               )

    获取最优参数

    best_params = space_eval(spaces,best)
    print("best_params = ",best_params)

    绘制搜索过程

    losses = [x["result"]["loss"] for x in trials.trials]
    minlosses = [np.min(losses[0:i+1]) for i in range(len(losses))] 
    steps = range(len(losses))
    
    fig,ax = plt.subplots(figsize=(6,3.7),dpi=144)
    ax.scatter(x = steps, y = losses, alpha = 0.3)
    ax.plot(steps,minlosses,color = "red",axes = ax)
    plt.xlabel("step")
    plt.ylabel("loss")

    训练模型

    printlog("step3: training model...")
    
    params.update(best_params)
    results = {}
    gbm = lgb.train(params,
                    lgb_train,
                    num_boost_round= boost_round,
                    valid_sets=(lgb_valid, lgb_train),
                    valid_names=('validate','train'),
                    early_stopping_rounds = early_stop_rounds,
                    evals_result= results,
                    verbose_eval = True)

    评估模型

    printlog("step4: evaluating model ...")
    
    y_pred_train = gbm.predict(dftrain.drop('label',axis = 1), num_iteration=gbm.best_iteration)
    y_pred_test = gbm.predict(dftest.drop('label',axis = 1), num_iteration=gbm.best_iteration)
    
    train_score = f1_score(dftrain['label'],y_pred_train>0.5)
    val_score = f1_score(dftest['label'],y_pred_test>0.5)
    
    print('train f1_score: {:.5} '.format(train_score))
    print('valid f1_score: {:.5} \n'.format(val_score))
    
    fig2,ax2 = plt.subplots(figsize=(6,3.7),dpi=144)
    fig3,ax3 = plt.subplots(figsize=(6,3.7),dpi=144)
    lgb.plot_metric(results,ax = ax2)
    lgb.plot_importance(gbm,importance_type = "gain",ax=ax3)

    保存模型

    printlog("step5: saving model ...")
    model_dir = "gbm.model"
    print("model_dir: %s"%model_dir)
    gbm.save_model("gbm.model",num_iteration=gbm.best_iteration)
    printlog("task end...")

    参考链接:

    https://www.jianshu.com/p/35eed1567463 

    https://cloud.tencent.com/developer/article/1857480 

    https://districtdatalabs.silvrback.com/parameter-tuning-with-hyperopt 

    https://link.jianshu.com?t=https%3A%2F%2Farxiv.org%2Fabs%2F1209.5111

    编辑:@公众号:数据STUDIO

    推荐阅读:

    我的2022届互联网校招分享

    我的2021总结

    浅谈算法岗和开发岗的区别

    互联网校招研发薪资汇总

    2022届互联网求职现状,金9银10快变成铜9铁10!!

    公众号:AI蜗牛车

    保持谦逊、保持自律、保持进步

    f9bbcd70a4e028329188fecddb24b8dc.png

    发送【蜗牛】获取一份《手把手AI项目》(AI蜗牛车著)

    发送【1222】获取一份不错的leetcode刷题笔记

    发送【AI四大名著】获取四本经典AI电子书

    展开全文
  • 使用hyperopt实现超参数实现神经网络优化 贝叶斯优化 贝叶斯优化的思想类似于网格搜索法和随机搜索方法,本质上是一种类似于穷举的当时,比较最优值。而网格搜索和随机搜索会消耗大量的实践,效率较低,贝叶斯优化...

    本次内容
    简单的说明贝叶斯优化算法
    使用hyperopt实现超参数实现神经网络优化

    贝叶斯优化

    贝叶斯优化的思想类似于网格搜索法和随机搜索方法,本质上是一种类似于穷举的当时,比较最优值。而网格搜索和随机搜索会消耗大量的实践,效率较低,贝叶斯优化就是在有限的时间内找到一个相对较好的结果。因此贝叶斯优化也会出现局部最优解的情况,要想尽量避免这样的问题可以将搜索范围增加,搜索点之间的间隔降低来尽量避免出现局部最优解。

    hyperopt库

    hyperopt库是我使用了多个贝叶斯优化库之后选择的结果,总体来说初次上手较为简单,可以实现TEP贝叶斯优化,优化结果展示比较简洁、美观。但是其支持的优化算法比较少,要想实现更多的优化算法可以使用optuna

    参数空间

    hyperopt的参数空间,一般是以字典形式展现的,其中包括:

    1. hp.quniform(“参数名称”,上界, 下届, 步长):此方法适合数字类的搜索,在步长的选择上可以是整型也可以是浮点型,若要想尽量避免算法陷入局部最优,可以将界限扩大,步长减小。
    2. hp.uniform("参数“,上界, 下界): 适用于随机分布的浮点型数据,可以在学习率等参数优化时使用
    3. hp.choice(“参数”, [a, b,c]):此方法中的列表中的值,可以是字符串类型,也可以是浮点型数据,可以在激活函数的选取上使用。

    常用函数

    1. fmin()基础功能的优化函数,可以在定义中选择使用tep方法或rand方法来进行算法优化
    2. Trials()用来保存优化结果,在优化结束后可以查看随时,参数等信息
    3. early_stop_fn()用来提前停止参数寻优,此函数中传入数字具体的数字n,表示在寻优过程中有n次的损失基本不再改变,则算法停止。

    安装

    pip install hyperopt
    

    案例-双向GUR网络的神经元数参数寻优

    使用tensorflow,keras库实现网络的搭建,这里并未对优化后的模型进行保存,和寻优完之后的结果进行处理。

    import pandas as pd
    import numpy as np
    from sklearn.preprocessing import MinMaxScaler
    from keras.models import Sequential
    from keras.layers import Dense, Bidirectional, GRU
    from hyperopt import hp, fmin, tpe, Trials
    from hyperopt.early_stop import no_progress_loss
    

    定义待优化的模型

    # 模型
    def model(params):
        model = Sequential()
        model.add(Bidirectional(GRU(units=int(params['units']), activation='relu'), input_shape=(x_train.shape[1], x_train.shape[-1])))
        model.add(Dense(1))
        model.summary()
        model.compile(loss='mae', optimizer='adam')
        model.fit(x_train, y_train, epochs=20, batch_size=64, validation_data=(x_val, y_val))
        # 用测试集上的损失进行寻优
        score_loss = model.evaluate(x_val, y_val, verbose=2) 
        print("Text loss:", score_loss)
        return score_loss
    

    定义数据切分函数

    def create_dataset(dataset, look_back=8):
        data_x, data_y = [], []
        for i in range(len(dataset) - look_back - 1):
            # 获取全部元素
            x = dataset[i:i + look_back, 0:dataset.shape[1]]
            data_x.append(x)
            # 第0列,想要预测的数据
            y = dataset[i + look_back, 0]
            data_y.append(y)
        return np.array(data_x), np.array(data_y)
    

    定义寻优过程

    # 定义参数优化函数
    def param_hyperopt(max_evals=100):
        trials = Trials()
        # 提前停止条件
        early_stop_fn = no_progress_loss(20)
        # 优化模型
        params_best = fmin(fn=model, space=params_space, algo=tpe.suggest, max_evals=max_evals,
                           trials=trials, early_stop_fn=early_stop_fn)
        print('best params:', params_best)
        return params_best, trials
    

    这里只对神经元进行寻优,若想对其他参数也进行寻优,添加寻优空间即可

    # 定义参数模型空间
    params_space = {
        "units": hp.quniform('units', 40, 120, 4)
    }
    

    主程序

    data1 = pd.read_csv('201701.csv', usecols=['站点名称', 'PM2.5', 'PM10'], engine='python')
    data2 = pd.read_csv('201702.csv', usecols=['站点名称', 'PM2.5', 'PM10'], engine='python')
    data3 = pd.read_csv('201703.csv', usecols=['站点名称', 'PM2.5', 'PM10'], engine='python')
    data4 = pd.read_csv('201704.csv', usecols=['站点名称', 'PM2.5', 'PM10'], engine='python')
    data5 = pd.read_csv('201705.csv', usecols=['站点名称', 'PM2.5', 'PM10'], engine='python')
    data6 = pd.read_csv('201706.csv', usecols=['站点名称', 'PM2.5', 'PM10'], engine='python')
    data = pd.concat([data1, data2, data3, data4, data5, data6])
    data = data[data['站点名称'] == '衡水监测站']
    data = pd.concat([data], ignore_index=True)
    del data['站点名称']
    print(data[:10])
    print(data.shape)  # (2880, 2)
    
    # 输入,输出划分
    data = data[['PM2.5', 'PM10']]
    print(data[0:10])
    
    # 归一化
    scale = MinMaxScaler()
    data = scale.fit_transform(data)
    print(data[0:10])
    
    # 划分数据集
    X_data = data[0:int(len(data) * 0.9)]
    Y_data = data[int(len(data) * 0.9):]
    # 训练集
    x_train, y_train = create_dataset(X_data)
    x_val, y_val = create_dataset(Y_data)
    print(x_train.shape)  # (3900, 8, 2)
    print(x_val.shape)
    # 调用参数寻优函数
    params_best, trials = param_hyperopt(20)
    

    寻优结果如下:
    寻优结果

    展开全文
  • hyperas:硬+ Hyperopt

    2021-04-11 19:19:22
    该项目现已存档。...安装 pip install hyperas 快速开始 假设您已经生成了这样的数据 def data (): x_train = np . zeros ( 100 ) x_test = np . zeros ( 100 ) y_train = np . zeros ( 100 ) y_test = np . z
  • 安装说明 ...hyperopt安装说明 Font Tian translated this article on 23 December 2017 有关MongoDB的部分 Hyperopt要求mongodb(有时候简称“mongo”)来执行并行搜索。据我所知,hyperopt与2....
  • 贝叶斯超参数优化库hyperopt安装包及依赖库,可利用pip离线安装 实现基于TPE的贝叶斯优化,不支持基于高斯过程的贝叶斯优化
  • Hyper-v安装LinuxIC方法

    2021-05-26 10:51:14
    先检查gcc和kernel-devel是否安装,先安装,然后重启,再安装LinuxIC即可。检查gcc和kernel-devel是否安装1.Linux操作系统安装好以后,查看gcc是否已经安装;# gcc -v //如果后面出现一大段,则已经安装;2.查看内核...
  • Hyper-v安装linux

    2021-05-15 02:01:41
    Step By Step Guide To Install CentOS Linux Virtual Machine in Windows Hyper-V ServerQuestion:Please follow this step by step guide to load CentOS 5.x or other Linux Operating System in Windows Hyper-V...
  • 此存储库还包括一个用于在工作流程中运行nlu-hyperopt安装 发展 pip install -r requirements.txt 在全新的ubuntu 16 VPS上(例如在Google Cloud上) 克隆此仓库 sudo bash install/install.sh 这将安装...
  • Hyperopt

    万次阅读 2016-06-28 14:09:32
    Hyperopt是一个python库,结合MongoDB可以进行分布式调参,快速找到相对较优的参数。安装的时候需要指定dev版本才能使用模拟退火调参,也支持暴力调参、随机调参等策略。 2.Win7安装 软件 MongoDB 地址 Hyperopt ...
  • 离线安装包,测试可用。使用 pip install [完整包名] 进行安装
  • HyperOpt参数优化

    2019-10-14 19:41:41
    安装hyperopt时也会安装 networkx,如果在调用时出现  TypeError: 'generator' object is not subscriptable  报错,可以将其换成1.11版本。 pip uninstall networkx pip install networkx== 1.11 2 重点...
  • 一种超参数优化技术-Hyperopt

    千次阅读 2020-11-06 23:25:38
    安装Hyperopt 你可以从PyPI安装hyperopt。 pip install hyperopt 然后导入重要的软件包 # 导入包 import numpy as np import pandas as pd from sklearn.ensemble import RandomForestClassifier from sklearn ...
  • hyperopt 是一个 Python 库,主要使用 随机搜索算法 模拟退火算法 TPE算法 来对某个算法模型的最佳参数进行智能搜索,它的全称是Hyperparameter Optimization。 本文将介绍一种快速有效的方法用于实现机器学习模型...
  • Hyperopt 参数优化

    万次阅读 多人点赞 2018-08-28 20:02:03
    Hyperopt简介 Hyperopt(Hyper-parameter Optimization)用于模型选择和参数优化。 参数选择在训练模型时是一个很关键的部分。然而存在这样的问题,一方面参数选择背后包含着一定的数学原理,对于新手来说难上手;...
  • Hyperopt官方中文文档导读

    千次阅读 2017-12-23 15:56:30
    在2017年的圣诞节前,我翻译了有关HyperOpt的中文文档,这也时填补了空白,以此作为献给所有中国程序员,以及所有其他机器学习相关行业人员的圣诞礼物。圣诞快乐,各位。HyperOpt中文文档导读翻译的文档已经发布于...
  • python调参神器hyperopt

    2017-07-12 16:38:00
    一、安装 pip installhyperopt 二、说明 Hyperopt提供了一个优化接口,这个接口接受一个评估函数和参数空间,能计算出参数空间内的一个点的损失函数值。用户还要指定空间内参数的分布情况。Hyheropt四个重要的...
  • 资源分类:Python库 所属语言:Python 资源全名:mle_hyperopt-0.0.1-py3-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
  • python 调参神器hyperopt

    千次阅读 2018-06-09 14:13:51
    最近学习到了一个hyperopt 的一个调参工具(相对于gridsearch的暴力调参,这个速度更加快一点)官网地址:http://hyperopt.github.io/hyperopt-sklearn/1.安装:sudo pip install hyperoptsudo pip install ...
  • 原标题:python训练模型调参神器hyperopt一、安装pip install hyperopt二、说明Hyperopt提供了一个优化接口,这个接口接受一个评估函数和参数空间,能计算出参数空间内的一个点的损失函数值。用户还要指定空间内参数...
  • Hyperopt的使用

    千次阅读 2017-11-15 18:05:06
    对于机器学习工程师,要选择使用的模型,也要调整各个模型的参数,才找到最好的匹配。即使模型还可以,如果它的参数设置不匹配,同样无法输出好的结果。 常用的调参方式有 grid search 和 random ...hyperopt是一种通
  • Hyperopt 超参数调优

    千次阅读 2019-06-08 20:32:30
    本文是对Parameter Tuning with Hyperopt一文的翻译。译者在设计深度学习模型的网络结构发现了hyperopt这个大杀器,相比每次手动各种试,用工具批量调节网络中的各种超参数确实能省心不少。不过hyperopt的官方文档...
  • 贝叶斯优化是当今黑盒函数估计领域最为先进和经典的方法,在同一套序贯模型下使用不同的代理模型以及采集函数、还可以发展出更多更先进的贝叶斯优化改进版算法,因此,贝叶斯优化的其算法本身就多如繁星,实现各种...
  • 应用hyperopt给keras项目自动调参

    千次阅读 2021-12-03 17:09:46
    python用hyperopt自动调参的简单介绍

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 239
精华内容 95
关键字:

hyperopt安装