遗传算法和超参数
遗传算法是什么?
遗传算法是优化问题的一种解决方案,例如,如果你需要找到最佳的参数集来最小化损失函数。遗传算法是进化算法的一部分。这个想法受到自然和自然选择的启发。
在自然界中,进化至少需要三个条件:
- 遗传——生物体必须能够将某些特定的特征遗传给后代;
- 变异——种群内的生物必须具有不同的特征;
- 竞争——产生的后代数量超过了生存能力。
现在想象一下,你在一个特定的编程环境中编码了一些对象,而不是生物体。例如,如果你有一个机器学习(ML)模型的种群,它会如何工作?
- 首先生成ML模型的初始种群,随机选择超参数。
- 计算每个模型的损失函数,例如,对数损失。
- 然后选择一些误差最小的模型。
- 现在您需要创建后代,因此您需要基于上一代最好的模型创建一组新的机器学习(ML)模型,并稍微更改它们的超参数。您的新种群将从以前的种群中的模型和新生成的模型中以一定比例包含,例如,50/50。
- 计算损失函数,对模型进行排序,然后再重复整个过程。
遗传算法并不完美,您仍然需要指定您的损失函数、您的种群大小、具有变化参数的后代比例等等。
TPOT
可能是对遗传超参数调优最友好的库。
GitHub:https://github.com/EpistasisLab/tpot
以下是我从TPOT中提取最佳超参数的方法,Python代码如下:
#Search for best hyperparameters for XGBoost
from xgboost import XGBClassifier
from tpot import TPOTClassifier, TPOTRegressor
from deap.gp import Primitive
#Define your hyperparameters
params = {'max_depth': np.arange(1,200,1),
'learning_rate': np.arange(0.0001,0.1,0.0001),
'n_estimators': np.arange(1,200,1),
'nthread':[6],
'gamma':np.arange(0.00001,0.1,0.00001),
'subsample':np.arange(0.1,2,0.1),
'reg_lambda': np.arange(0.1,200,1),
'reg_alpha': np.arange(1,200,1),
'min_child_weight': np.arange(1,200,1),
'gamma': np.arange(0.1,2,0.1),
'colsample_bytree': np.arange(0.1,2,0.1),
'colsample_bylevel': np.arange(0.1,2,0.1)
}
#Run TPOT
tpot_classifier = TPOTClassifier(generations=20, population_size=500, offspring_size=250,
verbosity=2, early_stop=8,
config_dict={'xgboost.XGBClassifier': params}, cv = 10, scoring = 'accuracy')
tpot_classifier.fit(X, Y)
#Extract best parameters
args = {}
for arg in tpot_classifier._optimized_pipeline:
if type(arg) != Primitive:
try:
if arg.value.split('__')[1].split('=')[0] in ['max_depth', 'n_estimators', 'nthread','min_child_weigh']:
args[arg.value.split('__')[1].split('=')[0]] = int(arg.value.split('__')[1].split('=')[1])
else:
args[arg.value.split('__')[1].split('=')[0]] = float(arg.value.split('__')[1].split('=')[1])
except:
pass
params = args
#Now you can use XGBoost with best hyperparameters
xgbxgb == XGBClassifierXGBClas (**params)
如何调整神经网络?
在神经网络的情况下,您还可以使用遗传算法,它们的工作速度比基于网格搜索的方法快得多。
我找到了这个GitHub存储库 - 使用遗传算法演化神经网络(https://github.com/harvitronix/neural-network-genetic-algorithm),并且非常喜欢这种方法。
用法示例:
from evolution import NeuroEvolution
params = {
"epochs": [10, 20, 35],
"batch_size": [10, 20, 40],
"n_layers": [1, 2, 3, 4],
"n_neurons": [20, 40, 60],
"dropout": [0.1, 0.2, 0.5],
"optimizers": ["nadam", "adam"],
"activations": ["relu", "sigmoid"],
"last_layer_activations": ["sigmoid"],
"losses": ["binary_crossentropy"],
"metrics": ["accuracy"]
}
....
# x_train, y_train, x_test, y_test - prepared data
search = NeuroEvolution(generations = 10, population = 10, params=params)
search.evolve(x_train, y_train, x_test, y_test)
100%|██████████| 10/10 [05:37<00:00, 29.58s/it]
100%|██████████| 10/10 [03:55<00:00, 25.55s/it]
100%|██████████| 10/10 [02:05<00:00, 15.05s/it]
100%|██████████| 10/10 [01:37<00:00, 14.03s/it]
100%|██████████| 10/10 [02:49<00:00, 22.53s/it]
100%|██████████| 10/10 [02:37<00:00, 23.14s/it]
100%|██████████| 10/10 [02:36<00:00, 21.37s/it]
100%|██████████| 10/10 [01:57<00:00, 18.56s/it]
100%|██████████| 10/10 [02:42<00:00, 25.29s/it]
"best accuracy: 0.79, best params: {'epochs': 35, 'batch_size': 40, 'n_layers': 2, 'n_neurons': 20, 'dropout': 0.1, 'optimizers': 'nadam', 'activations': 'relu', 'last_layer_activations': 'sigmoid', 'losses': 'binary_crossentropy', 'metrics': 'accuracy'}"
# or you can call it with
search.best_params
它还可以搜索最佳数量的图层和神经元,以及您定义的超参数的位置。