Hyperopt 基于MongoDB的并行計算

Hyperopt是實現(xiàn)超參數(shù)優(yōu)化的python第三方庫, 最近發(fā)現(xiàn)其可以運(yùn)用mongo進(jìn)行并行計算, 稍微研究了一番,記錄并分享一下.

Mongo的安裝就不說了, 遵循鏈接內(nèi)容即可

在Ubuntu下進(jìn)行MongoDB安裝步驟

安裝完成后啟動mongo, 運(yùn)行下官方的demo看一下:

import math
from hyperopt import fmin, tpe, hp
from hyperopt.mongoexp import MongoTrials

trials = MongoTrials('mongo://localhost:1234/foo_db/jobs', exp_key='exp1')
best = fmin(math.sin, hp.uniform('x', -2, 2), trials=trials, algo=tpe.suggest, max_evals=10)

以上的代碼中, 實例化 MongoTrials 并賦值給trials變量, 其第一個參數(shù)是 mongo 進(jìn)程, 數(shù)據(jù)庫是 'foodb', 'jobs' 表. 'exp_key' 是任務(wù)的編號.(如果修改這個參數(shù), 表明是一個新的任務(wù), 會重新運(yùn)行搜索而不是從數(shù)據(jù)庫中取結(jié)果).
實際運(yùn)行demin的過程中, fmin 會被阻塞. 這是因為 MongoTrials 會將 fmin 作為異步對象, 所以出現(xiàn)新的搜索點(參數(shù)組合)時, fmin 不會去評估目標(biāo)函數(shù)而是等待另一個進(jìn)程替它完成這個工作.

hyperopt-mongo-worker 腳本就是干這個活滴, 新開一個 shell 輸入
hyperopt-mongo-worker --mongo=localhost:1234/foo_db --poll-interval=0.1
第一個參數(shù)就是 mongo 的地址, 第二個參數(shù)是輪詢間隔. 由于demo很簡單, 我們很快就得到一個最優(yōu)的 x 值.

但以上的demo太簡單了, 我們想將自己編寫的模型替換掉 math.sin. 以一個隨機(jī)森林舉例:

import hyperopt.mongoexp
import pandas as pd
import numpy as np

from hyperopt import fmin, tpe, hp, space_eval, pyll, rand, anneal
from hyperopt.mongoexp import MongoTrials
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score, cross_val_predict, train_test_split

def randomforest(args):
    class_weight = args['class_weight']
    criterion = args['criterion']
    min_impurity_split = args['min_impurity_split']
    n_estimators = args['n_estimators']
    min_samples_leaf = args['min_samples_leaf']
    min_samples_split = args['min_samples_split']

    estim = RandomForestClassifier(
                                                        n_estimators=n_estimators, 
                                                        class_weight=class_weight, 
                                                        criterion=criterion, 
                                                        min_impurity_decrease=min_impurity_split,
                                                        min_samples_leaf=min_samples_leaf,
                                                        min_samples_split = min_samples_split
                                                        )
    
    y_pred = cross_val_predict(estim, train_x, train_y, cv=3)
    metric = f1_score(train_y, y_pred)
    return -metric

space = {
            'class_weight': hp.choice('class_weight', [None, 'balanced']),
            'criterion': hp.choice('criterion', ['gini', 'entropy']),
            'min_impurity_split': hp.lognormal('min_impurity_split', 1e-10, 1e-4)*1e-7,
            'min_samples_leaf': hp.randint('min_samples_leaf', 10)+1,
            'min_samples_split': hp.randint('min_samples_split', 10)+1,
            'n_estimators': hp.randint('n_estimators', 950)+50
                }

if __name__  == '__main__':
    trials = MongoTrials('mongo://localhost:1234/foo_db/jobs', exp_key='exp2')
    best = fmin(fn=randomforest, space=space,  algo=rand.suggest, max_evals=100, trials=trials)
    print best

很遺憾有個屬性錯誤, 就是找不到 randomforest 這個模塊.
AttributeError: Can't get attribute 'randomforest' on <module '__main__' from ...hyperopt-mongo-worker
google了一下, 有網(wǎng)友給出了一些解決辦法, 我們先將 objective function 寫到另外的腳本中, 例如:

# hyperopt_model.py
# !-*- coding: utf-8 -*-
from sklearn.metrics import accuracy_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score, cross_val_predict,  train_test_split

import pandas as pd
df = pd.read_csv('xxxxx.csv', header=0)
y, X = df[df.columns[0]], df[df.columns[1:]]

def randomforest(args):
    n_estimators = args['n_estimators']
    criterion = args['criterion']
    max_features = args['max_features']
    min_impurity_split = args['min_impurity_split']
    min_samples_leaf = args['min_samples_leaf']
    min_samples_split = args['min_samples_split']
    class_weight = args['class_weight']

    global X, y
    clf = RandomForestClassifier(
                                class_weight=class_weight,
                                criterion=criterion,
                                max_features=max_features,
                                min_samples_leaf=min_samples_leaf,
                                min_impurity_split=min_impurity_split,
                                min_samples_split=min_samples_split,
                                n_estimators=n_estimators,
                                random_state=1
                                )
    y_pred = cross_val_predict(clf, X, y, cv=3)
    metric = accuracy_score(y, y_pred)
    return -metric

將這個腳本命名為 hyperopt_model.py 并將其寫入環(huán)境變量中, 順便修改下最上面的腳本:
export PYTHONPATH="${PYTHONPATH}:<hyperopt_model.py>"

import pandas as pd
import numpy as np
import hyperopt_model
import hyperopt.mongoexp

from hyperopt import fmin, tpe, hp, space_eval, pyll, rand, anneal
from hyperopt.mongoexp import MongoTrials
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score, cross_val_predict, train_test_split

if __name__  == '__main__':
    trials = MongoTrials('mongo://localhost:1234/foo_db/jobs', exp_key='exp2')
    best = fmin(fn=hyperopt_model.randomforest, space=hyperopt_model.space,  algo=rand.suggest, max_evals=100, trials=trials)
    print best

之后再運(yùn)行 hyperopt-mongo-worker 就ok了, 總體時間消耗大概降低了50% 左右.

我還嘗試了用進(jìn)程管理池管理這兩個進(jìn)程(代碼如下), 但是總有一些error沒有解決, 如果那位大佬有更好的方法, 煩請告知, 感謝!

# coding: utf-8
import sys
import logging
import hyperopt_model

from multiprocessing import Pool, Process
from hyperopt import fmin, tpe, hp, rand
from hyperopt.mongoexp import MongoTrials


def task1():
    logging.basicConfig(stream=sys.stderr, level=logging.INFO)
    print 'task1 running'    
    sys.exit(hyperopt.mongoexp.main_worker())
    

def task2(msg):
    trials = MongoTrials('mongo://localhost:1234/foo_db/jobs', exp_key='exp3')
    best = fmin(fn=hyperopt_model.randomforest, space=hyperopt_model.space,  algo=rand.suggest, max_evals=100, trials=trials)
    print msg
    print 'task2 is running'
    return best

if __name__ == '__main__':
    pool = Pool(processes=4)
    p = Process(target=task1)
    
    p.start()
    ret = pool.apply_async(task2, args=(1,))
    
    pool.close()
    pool.join()
    p.join()
    
    print 'processes done, result:'
    print ret.get()

### hyperopt  ### MongoDB  ### 并行計算  ### 自定義超參優(yōu)化模型
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末猛遍,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子颜矿,更是在濱河造成了極大的恐慌壮莹,老刑警劉巖变逃,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件街立,死亡現(xiàn)場離奇詭異犯助,居然都是意外死亡住诸,警方通過查閱死者的電腦和手機(jī)猫胁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門箱亿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人弃秆,你說我怎么就攤上這事届惋∷杳保” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵脑豹,是天一觀的道長郑藏。 經(jīng)常有香客問我,道長瘩欺,這世上最難降的妖魔是什么必盖? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮俱饿,結(jié)果婚禮上歌粥,老公的妹妹穿的比我還像新娘。我一直安慰自己拍埠,他們只是感情好失驶,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著械拍,像睡著了一般突勇。 火紅的嫁衣襯著肌膚如雪装盯。 梳的紋絲不亂的頭發(fā)上坷虑,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機(jī)與錄音埂奈,去河邊找鬼迄损。 笑死,一個胖子當(dāng)著我的面吹牛账磺,可吹牛的內(nèi)容都是我干的芹敌。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼垮抗,長吁一口氣:“原來是場噩夢啊……” “哼氏捞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起冒版,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤液茎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后辞嗡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捆等,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年续室,在試婚紗的時候發(fā)現(xiàn)自己被綠了栋烤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡挺狰,死狀恐怖明郭,靈堂內(nèi)的尸體忽然破棺而出买窟,到底是詐尸還是另有隱情,我是刑警寧澤薯定,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布蔑祟,位于F島的核電站,受9級特大地震影響沉唠,放射性物質(zhì)發(fā)生泄漏疆虚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一满葛、第九天 我趴在偏房一處隱蔽的房頂上張望径簿。 院中可真熱鬧,春花似錦嘀韧、人聲如沸篇亭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽犁河。三九已至早龟,卻和暖如春焰扳,著一層夾襖步出監(jiān)牢的瞬間搪搏,已是汗流浹背垂券。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工布近, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留炎辨,地道東北人捕透。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像碴萧,于是被迫代替她去往敵國和親乙嘀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容