利用机器学习拟合复杂函数,并利用遗传算法求最优解

利用机器学习拟合复杂函数,并利用遗传算法求最优解


编程语言:Python
利用工具:sklearn、keras、geatpy
步骤原理简述:
1、利用机器学习到数据集的多维特征和输出的拟合函数关系(模型去学,并保存模型)。
2、加载模型函数,利用遗传算法找到该函数的最优解(实际是在不同约束条件下的变量值中,求取拟合函数的最大值或最小值)
工具介绍:
   1、sklearn: https://scikit-learn.org/stable/ 官网教程网页,我利用了其中的Regression(回归模型),利用pipeline(将数据预处理和模型训练集成在一起)
基于sklearn的回归模型去拟合,模型如下(采用了LinearRegression和TheilSenRegressor/XGBRegressor(因为数据集较简单采用了线性拟合模型)),sklear提供的回归模型其余多种类型。拟合效果如下:

#LinearRegression
Pipeline([
    ('scale', MinMaxScaler()),
    ('reg', linear_model.LinearRegression())
])
data_size: 6715	
mse: 36.539681516210784	rmse: 6.044806160350452	mae:4.63826039731241	
mape: 3.3011660989748934	r2: 0.808433725049098

#TheilSenRegressor
Pipeline([
    ('scale', StandardScaler()),
    ('reg', TheilSenRegressor(random_state=5))
])
data_size: 6715	
mse: 35.90317863408285	rmse: 5.9919261205461 mae:4.5948612203764805	mape: 3.281180987786468	r2: 0.8117707132511071```

#XGBRegressor
Pipeline([
 ('scale', StandardScaler()),
    ('reg', XGBRegressor(max_depth=5, n_estimators=100, n_jobs=8))
])
data_size: 6715	
mse: 44.95695040186879	rmse: 6.704994437124373	mae: 5.23324546786106	  
mape: 3.69434252416818	r2: 0.7643045816418063

   2、keras,官网教程https://keras.io/zh/ 因为数据集较简单,试验过程,具体结构与结果记录如下:

基于keras神经网络的回归拟合
Keras1: (别人原始输出)
 y: _Power_chiller	data_size: 6715	
mse: 109.89059902559949	rmse: 10.482871697469138	mae: 8.92583014113255
mape: 6.267563752145885	r2: 0.4238774988195254


keras2:
model.add(Dense(output_dim=1, input_dim=9))
model.compile(loss='mean_squared_error', optimizer='sgd')
data_size: 6715	
mse: 34.67461192389513 	rmse: 5.888515256318449	mae: 4.535644083885483	
mape: 3.2163304659323524	r2: 0.8182117094074346

keras3:
model.add(Dense(4,input_dim=9,activation='sigmoid'))
model.add(Dense(1,activation='linear')data_size: 6715mse: 
mse: 105.27507699250788	rmse: 10.26036436938318	mae: 8.179505252179268	
mape: 5.890991045203168	r2: 0.4480752566035091


keras4:
model.add(Dense(4,input_dim=9,activation='sigmoid'))
model.add(Dense(4, activation='sigmoid'))
model.add(Dense(1, activation='linear'))
data_size: 6715	
mse: 116.41971469072959	rmse: 10.789796786350037	mae: 8.7450677473619	
mape: 6.026414498738246	r2: 0.38964736011025247

keras5:
model.add(Dense(18,input_dim=9,activation='sigmoid'))
model.add(Dense(18, activation='sigmoid'))
model.add(Dense(1, activation='linear'))
data_size: 6715	mse: 126.90706426348436	rmse: 11.26530355842595	
mae: 8.772541177423156	mape: 6.09706260143816	r2: 0.33466542243602104

keras6:
model.add(Dense(18,input_dim=9,activation='sigmoid'))
model.add(Dense(18, activation='sigmoid'))
model.add(Dense(1, activation='linear'))
data_size: 6715	mse: 92.46484791330296	rmse: 9.61586438721465	mae: 6.507704671795376
mape: 4.631009747366009	r2: 0.5152353347471101

3、拟合函数求到后,利用geatpy求取使输出值最小的变量
工具介绍:
geatpy:http://www.geatpy.com/start
Geatpy提供了许多已实现的遗传和进化算法相关算子的库函数,如初始化种群、选择、交叉、变异、重插入、多种群迁移、多目标优化非支配排序等,并且提供开放式的进化算法框架来实现多样化的进化算法。其执行效率高于Matlab遗传算法工具箱和Matlab第三方遗传算法工具箱Gaot、gatbx、GEATbx,学习成本低。
Geatpy支持二进制/格雷码编码种群、实数值种群、整数值种群、排列编码种群。支持轮盘赌选择、随机抽样选择、锦标赛选择。提供单点交叉、两点交叉、洗牌交叉、部分匹配交叉(PMX)、线性重组、离散重组、中间重组等重组算子。提供简单离散变异、实数值变异、整数值变异、互换变异等变异算子。支持随机重插入、精英重插入。支持awGA、rwGA、nsga2、快速非支配排序等多目标优化的库函数、提供进化算法框架下的常用进化算法模板等。

""" main.py """

import numpy as np
from keras.engine.saving import load_model
from sklearn import preprocessing
import geatpy as ga

# 定义目标函数
def aimfuc(variables,LegV):
   #模型路径
    path = "/home/lyw/桌面/workworkworkworkworkworkwork/GDS_SZ2/saved_models/B_chiller_power"
    #加载模型
    model = load_model(path + '-keras')
    #模型预处理
    scaler = preprocessing.MinMaxScaler()
    train_data = scaler.fit_transform(variables)
    #模型预测
    pred = model.predict(train_data)
    # 约束条件
    x1 = variables[:, [0]] # get x1
    x2 = variables[:, [1]] # get x2
    idx1 = np.where(x1 + x2 > 40)[0]
    exIdx = np.unique(np.hstack([idx1])) # 得到非可行解个体的下标
    LegV[exIdx] = 0 # 标记非可行解在种群可行性列向量中对应的值为0(0表示非可行解,1表示可行解)
    return [pred,LegV]

def punishing(LegV, FitnV):
    FitnV[np.where(LegV == 0)[0]] = 0 # 惩罚非可行解个体的适应度
    return FitnV

if __name__ == "__main__":
    AIM_M = __import__('main') # 获取目标函数地址
    PUN_M = __import__('main') # 获取罚函数地址
    # 变量设置
    x1 = [20, 25]                        # 自变量t的范围
    x2 = [16, 20]                        # 自变量wet_temp的范围
    x3 = [-5,5]                         # 自变量_T_CHW_diff的范围
    x4 = [50,55]                         # 自变量_CHW的范围
    x5 = [5,10]                          # 自变量_COW的范围
    x6 = [435,440]                        # 自变量_WTF1的范围
    x7 = [5,10]                           # 自变量_WTF3的范围
    x8 = [35,40]                           # 自变量_F_fan的范围
    x9 = [40,43]                           # 自变量__F_pump的范围
    b1 = [1, 1]                          # 自变量1-9是否包含下界
    b2 = [1, 1]
    b3 = [1, 1]
    b4 = [1, 1]
    b5 = [1, 1]
    b6 = [1, 1]
    b7 = [1, 1]
    b8 = [1, 1]
    b9 = [1, 1]
    ranges = np.vstack([x1, x2,x3,x4,x5,x6,x7,x8,x9]).T       # 生成自变量的范围矩阵
    borders = np.vstack([b1, b2,b3,b4,b5,b6,b7,b8,b9]).T      # 生成自变量的边界矩阵
    FieldDR = ga.crtfld(ranges, borders) # 生成区域描述器
    # 调用Geatpy内置进化算法模板
    [pop_trace, var_trace, times] = ga.sga_new_real_templet(AIM_M, 'aimfuc', PUN_M, 'punishing', FieldDR, problem = 'I', maxormin = 1, MAXGEN = 10, NIND = 1000, SUBPOP = 1, GGAP = 0.9, selectStyle = 'tour', recombinStyle = 'xovdp', recopt = 0.9, pm = 0.3, distribute = True, drawing = 1)

利用geatpy 改写比较困难,但利用geatpy提供的算法框架改写就很便利,只需要对目标函数进行更好,例如本文直接利用 ga.sga_new_real_templet模板。
同时geatpy提供的模板多达十几种,使用说明网址:https://github.com/geatpy-dev/geatpy/tree/master/geatpy/source-code/templets

最后优化结果如下:

1、最优的目标函数值为:107.97457885742188
最优的控制变量值为:
21.0
16.0
5.0
50.0
10.0
435.0
10.0
39.0
41.0
有效进化代数:100
最优的一代是第 30 代
时间已过 1657.3300688266754 秒

2、最优的目标函数值为:107.97457885742188
最优的控制变量值为:
21.0
16.0
5.0
50.0
10.0
435.0
10.0
39.0
41.0
有效进化代数:50
最优的一代是第 44 代
时间已过 365.3190333843231 秒

3、最优的目标函数值为:107.97457885742188
最优的控制变量值为:
21.0
16.0
5.0
50.0
10.0
435.0
10.0
39.0
41.0
有效进化代数:50
最优的一代是第 22 代
时间已过 375.3887228965759 秒
4、最优的目标函数值为:108.38638305664062
最优的控制变量值为:
21.0
16.0
5.0
50.0

谢谢大家的观看~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~进来了就点个赞呗~~~~~~~~`

你可能感兴趣的:(最优解问题)