说明
遗传算法的简单应用到这里就告一段落,原理比较简单,上手也容易。在应用过程中发现几个问题:
- 1 文档做的太粗糙,我很多参数是靠猜的(比如cv)
- 2 调用的参数还是比较复杂
- 3 用matplotlib画图的效果不好(特别是对中文的支持很差,应该改为前端展示)
当然这个包的计算效果(效率)是很不错的,所以这里计划:
- 1 进行封装,方便日后调用
- 2 解读源码,参考性的进行重构(例如目前都是基于numpy计算,可以转向pytorch的tensor计算)
在应用上,遗传算法有几个方向:
- 1 直接的应用问题,例如之前的爬虫优化
- 2 辅助建模,例如构造海量的变量,然后通过遗传算法选择
当然,在更高层次上,还可以做模型的组合优化。
内容
1 源码
在github上可以找到这个包的源码,整个包大概100M
未来我会参考源码,重构一套新的遗传算法工具包,特别是使用pytorch替代numpy,这样可以利用CUDA进行更快速的计算。
2 封装示例
一些和问题相关的常量
#服务器起的爬虫数 k1,k2
k1 = 4
k2 = 3
#服务器金额 m1, m2
m1 = 2000
m2 = 600
#两种代理稳定时间 t1, t2
t1 = 2
t2 = 6
#每日使用上限 N1, N2
N1 = 150000
N2 = 580000
#单位时间可维持的最大ip数 n1, n2
n1 = 10
n2 = 10
#代理金额 M1, M2
M1 = 1000
M2 = 1360
#爬虫爬取速度 c1, c2
c1 = 1.2033
c2 = 1.9567
#总预算 M
M = 8000
定义问题
import numpy as np
import geatpy as ea
class MyProblem(ea.Problem): # 继承Problem父类
def __init__(self):
name = 'MyProblem' # 初始化name(函数名称,可以随意设置)
M = 1 # 初始化M(目标维数)
maxormins = [-1] # 初始化目标最小最大化标记列表,1:min;-1:max
Dim = 4 # 初始化Dim(决策变量维数)
varTypes = [1] * Dim # 初始化决策变量类型,0:连续;1:离散
lb = [0,0,0,0] # 决策变量下界
ub = [30,30,30,30] # 决策变量上界
lbin = [1]*Dim # 决策变量下边界
ubin = [1]*Dim # 决策变量上边界 # 调用父类构造方法完成实例化
ea.Problem.__init__(self, name, M, maxormins, Dim, varTypes, lb, ub, lbin, ubin)
def aimFunc(self, pop): # 目标函数,pop为传入的种群对象
Vars = pop.Phen # 得到决策变量矩阵
x1 = Vars[:, [0]] # 取出第一列得到所有个体的x1组成的列向量
x2 = Vars[:, [1]] # 取出第二列得到所有个体的x2组成的列向量
x3 = Vars[:, [2]] # 取出第三列得到所有个体的x3组成的列向量
x4 = Vars[:, [3]]
# 计算目标函数值,赋值给pop种群对象的ObjV属性
pop.ObjV = c1* x3 + c2 * x4
# 采用可行性法则处理约束,生成种群个体违反约束程度矩阵
# 约束
# 约束1:k1x1 + k2x2 - y1 - y2 = 0
cv1 = np.abs(k1* x1 + k2* x2 - x3 - x4)
# 约束2: x1m1 + x2m2 + M1 + M2 - M <=0
cv2 = x1 * m1 + x2 * m2 + M1 + M2 - M
# 约束3:x3 * 1day/ t1 - N1
cv3 = 1440 * x3/t1 - N1
# 约束4:x4 * 1day/t2 - N2
cv4 = 1440 * x4 / t2 - N2
# 约束5:y1 -n1 <=0
cv5 = x3 - n1
# 约束6:y2 -n2 <=0
cv6 = x4 - n2
pop.CV = np.hstack([cv1,cv2,cv3,cv4,cv5,cv6]) # 第1.2.3个约束
执行算法
# -*- coding: utf-8 -*-
"""main.py"""
import geatpy as ea # import geatpy
# from MyProblem import MyProblem # 导入自定义问题接口
"""===============================实例化问题对象================================"""
problem = MyProblem() # 生成问题对象
"""==================================种群设置=================================="""
Encoding = 'RI' # 编码方式(用BG好像效率更高)
NIND = 1000 # 种群规模
Field = ea.crtfld(Encoding, problem.varTypes, problem.ranges, problem.borders) # 创建区域描述器
population = ea.Population(Encoding, Field, NIND) # 实例化种群对象(此时种群还没被初始化,仅仅是完成种群对象的实例化)
"""================================算法参数设置================================="""
myAlgorithm = ea.soea_EGA_templet(problem, population) # 实例化一个算法模板对象
myAlgorithm.MAXGEN = 200 # 最大进化代数
myAlgorithm.logTras = 1 # 设置每隔多少代记录日志,若设置成0则表示不记录日志
myAlgorithm.verbose = True # 设置是否打印输出日志信息
myAlgorithm.drawing = 0 # 设置绘图方式(0:不绘图;1:绘制结果图;2:绘制目标空间过程动画;3:绘制决策空间过程动画)
"""===========================调用算法模板进行种群进化==============--==========="""
[BestIndi, population] = myAlgorithm.run() # 执行算法模板,得到最优个体以及最后一代种群
# BestIndi.save() # 把最优个体的信息保存到文件中
"""==================================输出结果=================================="""
print('用时:%f 秒' % myAlgorithm.passTime)
print('评价次数:%d 次' % myAlgorithm.evalsNum)
if BestIndi.sizes != 0:
print('最优的目标函数值为:%s' % BestIndi.ObjV[0][0])
print('最优的控制变量值为:')
for i in range(BestIndi.Phen.shape[1]):
print(BestIndi.Phen[0, i])
else:
print('没找到可行解。')
---
用时:0.232716 秒
评价次数:199801 次
最优的目标函数值为:30.396700000000003
最优的控制变量值为:
1.0
5.0
9.0
10.0
3 画图
myAlgorithm.trace.keys()
---
dict_keys(['f_best', 'f_avg'])
s1 = myAlgorithm.trace['f_best']
s2 = myAlgorithm.trace['f_avg']
# 看起来被“烧掉”了9次迭代
len(s1)
---
191
画图函数
import pyecharts.options as opts
from pyecharts.charts import Line
def pe_line_pair(x_list, y_list1, y_list2, y_list1_name = '', y_list2_name='',
is_show_label_number = False, title=''):
c = (
Line()
.add_xaxis(x_list)
.add_yaxis(y_list1_name, y_list1, is_smooth=True)
.add_yaxis(y_list2_name, y_list2, is_smooth=True)
.set_global_opts(title_opts=opts.TitleOpts(title=title))
.set_series_opts(label_opts=opts.LabelOpts(is_show=is_show_label_number))
.render_notebook()
)
return c
画图
# pe_line_pair(x_list, y_list1, y_list2)
x_list = list(range(len(s1)))
y_list1 = myAlgorithm.trace['f_best']
y_list2 = myAlgorithm.trace['f_avg']
y_list1_name = 'best'
y_list2_name = 'average'
is_show_label_number = False
title = '迭代过程目标值'
pe_line_pair(x_list, y_list1, y_list2,y_list1_name =y_list1_name, y_list2_name=y_list2_name,title=title)
结果
到这里geatpy的使用就告一段落,可以先用,但之后还是要重写。