機器學習 | 特徵工程- 超參數調優方法整理

特徵工程是機器學習當中很重要的部分,能夠幫助咱們設計、建立新特徵,以便模型從中提取重要相關性。本文將記錄並持續更新相關特徵工程的工具包介紹,包括自動模型選擇和超參數調優等各方面。

· Featuretools

Featuretools 是一個開源的Python 庫,用於自動化特徵工程。自動特徵工程可以縮減時間成本,構建更優秀的預測模型,生成更有意義的特徵,還能防止數據泄漏(data leakage)。
目標任務:從數據表格集中獲取全部的數據信息並整合到一張表中,再建立特徵。
解決方案:採用深度特徵合成方法(DFS),經過調用一個函數來構建數千個特徵。
# Deep feature synthesis
feature_matrix, features = ft.dfs(entityset=es, 
                                  target_entity='clients',
                                  agg_primitives = agg_primitives,
                                  trans_primitives = trans_primitives)
其中ft 表明導入的 featuretools 庫。
經測試,自動生成特徵在數量和效率上均比手動特徵工程性能提升不少。
 
此外,Featuretools還有如下優點:
· 構建特徵時自動地考慮時間
· 可調用RF模型自動獲取特徵重要性

詳細內容請見:node

· 隨機森林超參數優化- RandomSearch和GridSearch

rf中的超參數主要爲森林中的決策樹的數量(n_estimators) 以及每一個樹在分割節點時考慮的特徵的數量(max_features)。 而且超參數優化的標準程序是經過交叉驗證來解決過分擬合問題。

1)Random Search with Cross Validation

一般,對於最佳超參數的範圍比較模糊,所以縮小搜索範圍的最佳方法是爲每一個超參數評估各類值。使用Scikit-Learn的RandomizedSearchCV方法,咱們能夠定義超參數範圍的網格,並從網格中隨機抽樣,使用每一個值組合執行K-Fold CV。
Step 1: 執行前,先獲取目前模型的參數
rf = RandomForestRegressor(random_state = 42)

from pprint import pprint
# Look at parameters used by our current forest
print('Parameters currently in use:\n')
pprint(rf.get_params())

Step 2:爲了使用RandomizedSearchCV,咱們首先須要建立一個參數網格在擬合過程當中進行採樣:python

from sklearn.model_selection import RandomizedSearchCV
# Number of trees in random forest
n_estimators = [int(x) for x in np.linspace(start = 200, stop = 2000, num = 10)]
# Number of features to consider at every split
max_features = ['auto', 'sqrt']
# Maximum number of levels in tree
max_depth = [int(x) for x in np.linspace(10, 110, num = 11)]
max_depth.append(None)
# Minimum number of samples required to split a node
min_samples_split = [2, 5, 10]
# Minimum number of samples required at each leaf node
min_samples_leaf = [1, 2, 4]
# Method of selecting samples for training each tree
bootstrap = [True, False]
# Create the random grid
random_grid = {'n_estimators': n_estimators,
'max_features': max_features,
'max_depth': max_depth,
'min_samples_split': min_samples_split,
'min_samples_leaf': min_samples_leaf,
'bootstrap': bootstrap}
pprint(random_grid)

Step 3:訓練git

# 使用隨機網格搜索最佳超參數
# 首先建立要調優的基本模型
rf = RandomForestRegressor()
# 隨機搜索參數,使用3倍交叉驗證 
# 採用100種不一樣的組合進行搜索,並使用全部可用的核心
rf_random = RandomizedSearchCV(estimator = rf, param_distributions = random_grid, n_iter = 100, cv = 3, verbose=2, random_state=42, n_jobs = -1)
# Fit模型
rf_random.fit(train_features, train_labels)

Step 4:獲得最佳參數github

rf_random.best_params_

Step 5:將優化後的參數進行訓練和比較驗證。算法

2) GridSearch

隨機搜索容許咱們縮小每一個超參數的範圍。如今咱們知道在哪裏集中搜索,咱們能夠明確指定要嘗試的每一個設置組合。GridSearchCV能夠評估咱們定義的全部組合。
Step 1:要使用網格搜索,咱們根據隨機搜索提供的最佳值建立另外一個網格
from sklearn.model_selection import GridSearchCV
# Create the parameter grid based on the results of random search 
param_grid = {
    'bootstrap': [True],
    'max_depth': [80, 90, 100, 110],
    'max_features': [2, 3],
    'min_samples_leaf': [3, 4, 5],
    'min_samples_split': [8, 10, 12],
    'n_estimators': [100, 200, 300, 1000]
}
# Create a based model
rf = RandomForestRegressor()
# Instantiate the grid search model
grid_search = GridSearchCV(estimator = rf, param_grid = param_grid, cv = 3, n_jobs = -1, verbose = 2)

Step 2: Fit模型並從新訓練和比較驗證bootstrap

grid_search.fit(train_features, train_labels)
grid_search.best_params_

best_grid = grid_search.best_estimator_
grid_accuracy = evaluate(best_grid, test_features, test_labels)
當性能的小幅降低代表咱們已經達到了超參數調整的收益遞減。
 
本部分代碼請見:

詳細內容請見:https://towardsdatascience.com/hyperparameter-tuning-the-random-forest-in-python-using-scikit-learn-28d2aa77dd74app

· Hyperopt自動化超參數調優- 貝葉斯優化

網格搜索和隨機搜索則對ml模型超參數的優化能取得不錯的效果,可是須要大量運行時間去評估搜索空間中並不太可能找到最優勢的區域。所以愈來愈多的的超參數調優過程都是經過自動化的方法完成的,它們旨在使用帶有策略的啓發式搜索(informed search)在更短的時間內找到最優超參數。
 
貝葉斯優化是一種基於模型的用於尋找函數最小值的方法。近段時間以來,貝葉斯優化開始被用於機器學習超參數調優,結果代表,該方法在測試集上的表現更加優異,而且須要的迭代次數小於隨機搜索。
Python 環境下有一些貝葉斯優化程序庫,它們目標函數的代理算法有所區別。本部分主要介紹「Hyperopt」庫,它使用樹形 Parzen 評估器(TPE, https://papers.nips.cc/paper/4443-algorithms-for-hyper-parameter-optimization.pdf)做爲搜索算法,其餘的 Python 庫還包含「Spearmint」(高斯過程代理)和「SMAC」(隨即森林迴歸)。
 
貝葉斯優化問題有四個組成部分:
1)目標函數:咱們想要最小化的對象,這裏指帶超參數的機器學習模型的驗證偏差
2)域空間:待搜索的超參數值
3)優化算法:構造代理模型和選擇接下來要評估的超參數值的方法
4)結果的歷史數據:存儲下來的目標函數評估結果,包含超參數和驗證損失
經過以上四個步驟,咱們能夠對任意實值函數進行優化(找到最小值)。
 
詳解:

1)目標函數

模型訓練目的是最小化目標函數,因此輸出爲須要最小化的實值——交叉驗證損失。Hyperopt 將目標函數做爲黑盒處理,由於這個庫只關心輸入和輸出是什麼。爲了找到使損失最小的輸入值
僞代碼:
def objective(hyperparameters):
    """Returns validation score from hyperparameters"""

    model = Classifier(hyperparameters)
    validation_loss = cross_validation(model, training_data)    
    return validation_loss
實際GBM完整的目標函數
import lightgbm as lgb
from hyperopt import STATUS_OK

N_FOLDS = 10

# Create the dataset
train_set = lgb.Dataset(train_features, train_labels)

def objective(params, n_folds = N_FOLDS):
    """Objective function for Gradient Boosting Machine Hyperparameter Tuning"""

    # Perform n_fold cross validation with hyperparameters
    # Use early stopping and evalute based on ROC AUC
    cv_results = lgb.cv(params, train_set, nfold = n_folds, num_boost_round = 10000, early_stopping_rounds = 100, metrics = 'auc', seed = 50)
#此部分爲核心代碼,

    # Extract the best score
    best_score = max(cv_results['auc-mean'])

    # Loss must be minimized
    loss = 1 - best_score

    # Dictionary with information for evaluation
    return {'loss': loss, 'params': params, 'status': STATUS_OK}

2)域空間

貝葉斯優化中,域空間對每一個超參數來講是一個機率分佈而不是離散的值。由於很難肯定不一樣數據集之間的最佳模型設定區間,此處主要採用貝葉斯算法進行推理。
此外,模型中有些參數是不須要調優的。以GBM爲例,除了n_estimator以外,還有10個左右的參數須要調整。所以咱們採用不一樣的分佈來定義每一個參數的域空間
from hyperopt import hp
# Define the search space
space = {
    'class_weight': hp.choice('class_weight', [None, 'balanced']),
    'boosting_type': hp.choice('boosting_type', 
                               [{'boosting_type': 'gbdt', 
                                    'subsample': hp.uniform('gdbt_subsample', 0.5, 1)}, 
                                {'boosting_type': 'dart', 
                                     'subsample': hp.uniform('dart_subsample', 0.5, 1)},
                                {'boosting_type': 'goss'}]),
    'num_leaves': hp.quniform('num_leaves', 30, 150, 1),
    'learning_rate': hp.loguniform('learning_rate', np.log(0.01), np.log(0.2)),
    'subsample_for_bin': hp.quniform('subsample_for_bin', 20000, 300000, 20000),
    'min_child_samples': hp.quniform('min_child_samples', 20, 500, 5),
    'reg_alpha': hp.uniform('reg_alpha', 0.0, 1.0),
    'reg_lambda': hp.uniform('reg_lambda', 0.0, 1.0),
    'colsample_bytree': hp.uniform('colsample_by_tree', 0.6, 1.0)
}
不一樣分佈名稱含義:
 choice:類別變量
   quniform:離散均勻分佈(在整數空間上均勻分佈)
   uniform:連續均勻分佈(在浮點數空間上均勻分佈)
   loguniform:連續對數均勻分佈(在浮點數空間中的對數尺度上均勻分佈)
 
定義與空間後,能夠選擇一個樣原本查看典型樣本形式
# Sample from the full space
example = sample(space)

# Dictionary get method with default
subsample = example['boosting_type'].get('subsample', 1.0)

# Assign top-level keys
example['boosting_type'] = example['boosting_type']['boosting_type']
example['subsample'] = subsample

example

3)優化算法

儘管從概念上來講,這是貝葉斯優化最難的一部分,但在 Hyperopt 中建立優化算法只需一行代碼。使用樹形 Parzen 評估器(Tree Parzen Estimation,如下簡稱 TPE)的代碼以下:
from hyperopt import tpe
# Algorithm
tpe_algorithm = tpe.suggest

4)結果歷史數據

想知道背後的發展進程,可使用「Trials」對象,它將存儲基本的訓練信息,還可使用目標函數返回的字典(包含損失「loss」和參數「params」)
from hyperopt import Trials
# Trials object to track progress
bayes_trials = Trials()
或者經過csv記錄迭代過程

5)優化算法

from hyperopt import fmin
MAX_EVALS = 500

# Optimize
best = fmin(fn = objective, space = space, algo = tpe.suggest, 
            max_evals = MAX_EVALS, trials = bayes_trials)
此部分代碼請見:
 
詳細內容參考:
 
持續更新...
相關文章
相關標籤/搜索