赞
踩
之前在学校写论文的时候各种群体优化算法用得挺多的,工作之后虽然没怎么用了,不过这类算法在优化一些算法超参数的时候还是比较有用的,比如优化SVM。。。
准备空闲的时候将这类算法整合成一个工具箱方便使用,目前写好了GA、PSO、CS、GWO、WOA、HHO,后续有空更新其他算法。
工具箱为每个优化算法提供统一的参数接口,因此使用的时候只需要关注自己的目标函数即可。使用仅需四个步骤:1、定义目标函数;2、设置目标函数待优化参数信息;3、设置优化器本身需要的参数信息;4、调用优化算法。
举例:
假设用遗传算法优化目标函数:
y = sum(x^2)
首先,定义目标函数:
def objf(x):
return np.sum(x**2)
然后设置目标函数中待优化参数信息,假设我们x为100维,每个维度在[-10, 10]范围内取值,则目标函数参数信息设置为:
parms_func = { 'x_lb': -10, 'x_ub': 10, 'dim': 100}
再设置优化器需要的参数信息,遗传算法需要参数包括种群大小、迭代次数、交叉概率、变异概率、每代最优保留数,因此GA优化器参数设置为:
parms_ga = {'PopSize': 20, 'Niter':100, 'Pcrs': 0.7, 'Pmut': 0.1, 'Ntop': 2}
最后整合参数信息并调用GA就可以了完成优化了:
func_opter_parms = FuncOpterInfo(parms_func, parms_opter)
func_opter_parms = GA(objf, func_opter_parms)
运行完成之后,优化过程信息会保存在func_opter_parms中,比如最优参数结果为:
func_opter_parms.best_x
全局最优值收敛曲线和每代平均函数值曲线分别为:
func_opter_parms.convergence_curve
func_opter_parms.convergence_curve_mean
画出收敛过程:
测试灰狼优化算法GWO优化SVM中的超参数,首先定义目标函数(测试集分类误差):
from sklearn.svm import SVC
from sklearn import metrics
def svc_objf(C_gamma, Xtrain=None, Ytrain=None, Xtest=None, Ytest=None):
'''
构造SVM分类模型目标函数(适应度函数)
'''
mdl = SVC(C=C_gamma[0], gamma=C_gamma[1])
mdl = mdl.fit(Xtrain, Ytrain)
Ypre = mdl.predict(Xtest)
error = 1 - metrics.accuracy_score(Ytest, Ypre)
return error
准备数据集:
from sklearn import datasets
from sklearn.model_selection import train_test_split as tts
data = datasets.load_iris()
X = pd.DataFrame(data_cls['data'], columns=data_cls.feature_names)
Y = pd.Series(data_cls['target'])
Xtrain, Xtest, Ytrain, Ytest = tts(X, Y, test_size=0.4, random_state=0)
然后设置待优化参数C和gamma信息:
parms_func = {'x_lb': 0.01, 'x_ub': 100, 'dim': 2,
'kwargs': {'Xtrain': Xtrain, 'Ytrain': Ytrain,
'Xtest': Xtest, 'Ytest': Ytest}}
设置GWO优化器需要的参数信息:
parms_gwo = {'opter_name': 'GWO', 'PopSize': 20, 'Niter': 100}
优化:
gwo_parms = FuncOpterInfo(parms_func, parms_gwo)
gwo_parms = GWO(objf, gwo_parms)
完成后查看最优参数结果:
gwo_parms.best_x
Out[1]: array([3.60648373e+01, 1.00000000e-02])
当然,除了优化模型超参数外,也可以用来尝试优化模型,比如逻辑回归,通常求解逻辑回归参数用的都是梯度下降或者牛顿法,来看看用布谷鸟优化算法求解逻辑回归中的w和b的效果如何。
定义逻辑回归模型优化目标函数(误差率):
import numpy as np def LR_cls_bin_objf(W_b, X_train=None, y_train=None, p_cut=0.5): def sigmoid(x): return 1.0 / (1 + np.exp(-x)) def forward(X, W): '''前向传播(模型表达式)''' return sigmoid(np.dot(X, W)) def XaddConst(X): '''X添加常数列''' const = np.ones((X.shape[0], 1)) return np.concatenate((X, const), axis=1) W = np.array(W_b).reshape(-1, 1) X_train, y_train = np.array(X_train), np.array(y_train) Xconst = XaddConst(X_train) # X添加常数项 # y转化为二维 if len(y_train.shape) == 1 or y_train.shape[1] == 1: y_train = y_train.reshape(-1, 1) y_pre_p = forward(Xconst, W) y_pre = (y_pre_p >= p_cut).astype(int) error = 1 - metrics.accuracy_score(y_train, y_pre) return error
数据准备
# 分类任务数据集
data = pd.read_excel('../utils_datsci/test/test_data1.xlsx')
X = data[['x1', 'x2']]
y = data['y']
X_train, y_train = X, y
目标函数参数信息设置:
parms_func = {'x_lb': -20, 'x_ub': 20, 'dim': 3,
'kwargs': {'X_train': X_train, 'y_train': y_train}}
CS算法参数设置:
parms_cs = {'PopSize': 10, 'Niter': 100, 'pa': 0.25}
优化结果(分界线):
跟梯度下降的优化结果比较一下:
从效果来看,CS貌似比经典梯度下降法更好,不过对更复杂的参数优化问题就可能不一定了。。。
需要工具箱源码的同学请关注公众号Genlovy562,后台回复关键词 “群体优化”:
github:
https://github.com/Genlovy-Hoo/utils_hoo/tree/master
群体优化工具库在utils_optimizer里面
如果对您有用,欢迎star
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。