機器學習——交叉驗證實現多進程並行

一、前言

1、衆所周知,python因爲其全局解釋器鎖GIL而無法通過線程實現真正的平行計算,所以我們不用python的多線程
2、我沒有用sklearn內置的機器學習庫(sklearn或者xgboost可能內置了一些方便的參數,調用就可實現並行)
2、對於我這樣的懶人來說,看了multiprocess模塊還是嫌麻煩。
3、所以我推薦from concurrent.futures import ProcessPoolExecutor


二、有兩個概念需要了解:

IO密集型:讀取文件,讀取網絡套接字頻繁。

  • 計算密集型:大量消耗CPU的數學與邏輯運算,也就是我們這裏說的並行計算。

似乎IO密集型更適合用異步處理,這裏我們不討論。


三、concurrent.futures模塊,可以利用multiprocessing實現真正的平行計算

核心原理是:concurrent.futures會以子進程的形式,平行的運行多個python解釋器,從而令python程序可以利用多核CPU來提升執行速度。由於子進程與主解釋器相分離,所以他們的全局解釋器鎖也是相互獨立的。每個子進程都能夠完整的使用一個CPU內核。


四、首先,你需要寫一個能將Dataframe數據處理成可迭代的函數

(不寫函數也行,你只要能拿到這個可迭代的數據就行哈哈)

什麼叫可迭代的數據呢?——
比如,我處理後返回的結構是[[train_data1, validation_data1], [train_data2, validation_data2], ...],這樣我通過map第一次傳進的就是一個列表[train_data1, validation_data1], 我只需要for i in data, train=i[0], validation=i[1]就可以取出每次傳進來的訓練集和驗證集了。

最後返回的數據格式是要可以迭代就好,列表,元組,字典都行,我這裏用的是列表。

def mkCVData(data):
    """
    數據集劃分
    :param data:    一個完整的數據集
    :return:        返回一個列表型的datarfame
    """
    k = 4  # k折
    k_sample_count = data.shape[0] // k  # 每折多少行數據(這裏使用整除)

    # 新建一個列表用於裝載dataframe
    data_set = []

    # 根據k折,劃分數據集
    from tqdm import tqdm
    for fold in tqdm(range(k)):
        print(f"第{fold}折")  # f 代表format

        validation_begin = k_sample_count * fold
        validation_end = k_sample_count * (fold + 1)

        validation_data = data[validation_begin:validation_end]

        # pd.concat 沿着垂直的方向堆疊數據,拼接得到訓練集
        train_data = pd.concat([
            data[:validation_begin],
            data[validation_end:]
        ])

        # 重新索引train_data和validation_data
        train_data.index = np.arange(len(train_data))
        validation_data.index = np.arange(len(validation_data))

        data_set.append(([train_data, validation_data]))

    return list(data_set)

五、主函數多進程代碼

if __name__ == '__main__':

    # pandas讀取
    tmp_data  = pd.read_csv("label.csv", index_col=[0])

    # 打亂數據集
    from sklearn import utils
    tmp_data = utils.shuffle(tmp_data)
    # 數據集劃分
    tmp_data = mkCVData(tmp_data)

    # 記錄時間和進程池
    start_time = time.time()
    pool = ppExe(max_workers=4)

    # 設置一個交叉驗證得分列表
    crossVal_list = []
    crossVal_list.extend(list(pool.map(crossVal, tmp_data)))# 這裏是extend還是append取決於你的評估分數是什麼結構

    # 記錄結束時間,計算過程時間
    end_time = time.time()
    ti = end_time - start_time
    print(f"過程花費時間={ti//60}分{ti%60}秒")

參考博文:
《機器學習並行化(parallel machine learning)》
《python concurrent.futures》
《三行Python代碼,可以讓你的數據處理快別人4倍》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章