今天将用python实现GEP算法中,适应度计算、评估操作
【PS:注意结合前边内容,今天的内容比较复杂,特别是如何将基因转换为逆波兰式,如何将样本数据代入运算都有一定难度,本次的内容就不涉及选择,复制,变异等的内容】
基因表达式编程(GEP)自学 第【1】天 Python 实现
基因表达式编程(GEP)自学 第【2】天 Python 实现
基因表达式编程(GEP)自学 第【3】天 Python 实现
基因表达式编程(GEP)自学 第【4】天 Python 实现(代码)
def evalFunction(C_value, T_value, maxFitness_flag=False,M=100,DataCount=10,):
'''
:param C_value: 表示染色体,样本输出值
:param T_value: 表示染色体,样本真实值
:param maxFitness_flag: 用于是否为最大适应度值
:param M: M 常数
:param DataCount: 数据的个数
:return:
'''
if maxFitness_flag:
return M*DataCount
sum_fitness = 0
for i in range(len(C_value)):
if not math.isfinite(C_value[i][0]):
sum_fitness += 0
pass
result = M - abs(C_value[i][0] - T_value[i][0])
if result < 0: result = 0
sum_fitness = result + sum_fitness
fitness = sum_fitness
return fitness
【PS:其中,这里计算出来的绝对误差,即使适应度差的,但也可能遗传其基因给后代,只是概率极低。这里将其设置为1,如果,你其他想法,也可付出实践。】
#即使适应度差的,但也可能遗传其基因给后代,只是概率极低
其中定义函数 run 用于调用执行GEP主要操作
def run(self, inputsOutputs, evalFunction,generationCount=200,M=100,DataCount=10):
'''
:param inputsOutputs: 保存输入与输出集合
:param evalFunction: 适应度函数
:param generationCount: 执行代数
:return:
generation: 表示第几代种群
i_chromosome 用于保存当代种群第i条染色体
C_valueList 表示染色体,样本输出值
fitness 保存当前染色体的适应度
maxFitness_flag=True 为True,返回的maxFitness:M*DataCount
'''
generation = 0
while True:
generation += 1
for i in range(len(self.population)):
C_valueList = []
i_chromosome = self.population[i]
#计算每个染色体对应的 C_value
for inputs in inputsOutputs[0]:
C_valueList.append(i_chromosome.eval(inputs))
#evalFunction 进行适应度评估
fitness = evalFunction(C_valueList, inputsOutputs[1], M=M, DataCount=DataCount,)
print("[",i,"] "," Fitness=",fitness)
if fitness == evalFunction([], [], maxFitness_flag=True,M=M,DataCount=DataCount,):
print("*" * 46, " 完美解 ", "*" * 46)
i_chromosome.printChromosome()
return i_chromosome
# 繁衍代数大于generationCount退出
if generation >= generationCount:
return 0
def eval(self, inputs):
'''
:param inputs: 样本输入值
:return: returnValues
'''
returnValues = []
#基因赋值运算、结果保存在returnValues
for gene in self.genes:
#将终结值赋予对应的数值,如 a:1 ,b:2
evalInputs = {terminal: value for (terminal, value) in list(zip(gene.genome.terminals, inputs))}
returnValues.append(gene.eval(evalInputs))
#连接函数运算、最终结果保存在returnValues
homeoticReturnValues = []
if len(self.homeotics) > 0:
outputs = {index: output for (index, output) in list(zip(range(0, len(self.genes)), returnValues))}
for homeotic in self.homeotics:
homeoticReturnValues.append(homeotic.eval(outputs))
returnValues = homeoticReturnValues
return returnValues
def eval(self, inputs):
'''
对精英进行赋值运算评估
:param inputs: 参数输入值
:return:
'''
elementLayers = self.orderStack()
evalStack = self.tranformRPN(elementLayers)
return self.evalStack(evalStack, inputs)
#例子【'+':2,'-':2,'*':2,'a':0,'a':0,'a':0,'a':0】
#首先,取出一个符号'+',即arity初始为:arity=1
#然后,保存该符号的arity数值。由'+':2得arity=2,同时将取出得'+'在elementLayers保存
#循环,此时arity=2,取出2个符号即'-','*'。
#根据'-','*'得到max_arity数值,max_arity=4
#以此类推直到max_arity=0。
#这其实就模拟树,一层一层得取出。
#【【'+':2】,【'-':2,'*':2】,【'a':0,'a':0,'a':0,'a':0】】
def orderStack(self):
elementLayers = []
gene = self.head + self.tail
arity = 1
while arity > 0:
elementList = []
for i in range(arity):
elementList.append(gene.pop(0))
arity = 0
for i_element in elementList:
arity += self.genome.symbols()[i_element]
elementLayers.append(elementList)
# print(elementLayers)
return elementLayers
#用递归实现逆波兰式的装转变
def tranformRPN(self, elementLayers, layerIndex = 0):
'''
:param elementLayers: orderStack输出的层次结构
:param layerIndex: 几层用于递归调用
:return:
'''
stack = []
for i in range(self.genome.symbols()[elementLayers[layerIndex][0]]):
stack = stack + self.tranformRPN(elementLayers, layerIndex + 1)
stack.append(elementLayers[layerIndex].pop(0))
return stack
#inputs=['a':1,'b':3]已赋值,取值运算
def evalStack(self, stack, inputs):
'''
:param stack: 为逆波兰式
:param inputs: 参数输入值
:return:returnStack 保存最后的运算结果
'''
returnStack = []
for symbol in stack:
if symbol in inputs.keys():
returnStack.append(inputs[symbol])
else:
self.genome.functions[symbol][0](returnStack)
return returnStack[0]
【PS:随机种子设置为10】
random.seed(10)
if __name__=='__main__':
#---------------操作数设置 Begin--------------#
genome = Genome()
genome.functions.update(Genome.linker_set)
genome.terminals = ['a','b']
genome.symbols()
my_link_genome=Genome()
my_link_genome.functions.update(Genome.linker_set)
#----------------操作数设置 end---------------#
#---------------种群初始化 Begin--------------#
environment = Environment()
environment.init(populationSize=20,numGenes=3,numHomeotics=1,headLength=4,homeoticHeadLength=5,genome=genome,link_genome=my_link_genome)
environment.setRates(homeoticRate=0.5, mutationRate=0.044,ISTranspositionRate=0.1,
RISTranspositionRate=0.1, geneTranspositionRate=0.1,onePointRecombinationRate=0.3,
twoPointRecombinationRate=0.3, geneRecombinationRate=0.1)
##----------输出测试----------##
#----------------种群初始化 end---------------#
#---------------Run Begin--------------#
M=100
DataCount=10
generationCount=0
inputsOutputs=GenerateData(DataCount=DataCount)
result=environment.run(inputsOutputs,evalFunction,M=M,generationCount=generationCount)
#----------------Run end---------------#
输出结果:
0
0 :['-', '+', '/', '/', 'a', 'a', 'b', 'b', 'b']:['-', 'a', '/', '*', 'a', 'a', 'b', 'a', 'b']:['*', '*', '/', '/', 'b', 'b', 'b', 'a', 'b']:['-', '/', 2, 2, '-', 1, 2, 1, 0, 2, 0]:
1 :['/', '-', '*', 'a', 'b', 'a', 'b', 'b', 'b']:['+', 'b', 'a', '*', 'a', 'a', 'b', 'a', 'a']:['-', '*', 'a', 'b', 'a', 'a', 'a', 'b', 'b']:['-', 2, 2, '+', '/', 0, 0, 1, 1, 1, 1]:
2 :['-', '*', '-', 'a', 'a', 'a', 'b', 'b', 'b']:['+', 'b', '-', '-', 'b', 'b', 'b', 'b', 'a']:['/', 'b', '+', '*', 'b', 'a', 'a', 'b', 'b']:['/', '-', '/', 2, '/', 2, 0, 2, 2, 1, 2]:
3 :['*', '/', '+', '-', 'b', 'b', 'b', 'a', 'b']:['+', '/', '/', 'b', 'a', 'b', 'a', 'b', 'a']:['/', 'a', '+', '+', 'b', 'a', 'a', 'a', 'b']:['/', '/', 2, '/', 2, 2, 1, 1, 2, 1, 2]:
4 :['/', '*', 'b', 'a', 'a', 'a', 'b', 'a', 'a']:['*', '+', '*', '/', 'a', 'b', 'a', 'a', 'a']:['+', 'b', '/', '-', 'b', 'b', 'a', 'b', 'a']:['/', '-', '/', '-', '+', 2, 1, 1, 2, 2, 2]:
5 :['-', 'b', 'b', 'a', 'a', 'b', 'b', 'a', 'a']:['*', 'a', '/', '/', 'a', 'a', 'b', 'a', 'a']:['*', '*', '/', '/', 'a', 'b', 'b', 'b', 'b']:['/', '/', 1, '*', '*', 2, 1, 1, 1, 1, 2]:
6 :['*', 'b', 'a', 'b', 'b', 'b', 'a', 'b', 'a']:['-', 'a', '*', 'b', 'b', 'a', 'b', 'b', 'b']:['/', '-', '*', '+', 'a', 'a', 'a', 'b', 'a']:['*', 2, 0, '+', '/', 0, 1, 2, 0, 2, 2]:
7 :['-', 'b', 'b', 'a', 'a', 'a', 'b', 'b', 'b']:['/', '+', 'a', '*', 'a', 'a', 'b', 'a', 'b']:['*', '*', '+', '-', 'b', 'b', 'b', 'b', 'a']:['/', '/', 2, 2, '*', 2, 2, 1, 1, 0, 0]:
8 :['+', '-', '+', '-', 'a', 'b', 'b', 'b', 'a']:['+', '*', '-', '+', 'a', 'a', 'b', 'a', 'b']:['/', 'a', '/', '+', 'b', 'a', 'b', 'a', 'a']:['-', 2, '/', 2, '*', 0, 0, 0, 2, 2, 1]:
9 :['/', 'b', 'b', '/', 'a', 'b', 'a', 'a', 'a']:['*', 'b', '*', 'b', 'b', 'a', 'b', 'b', 'a']:['/', 'b', '-', 'b', 'b', 'a', 'a', 'b', 'a']:['/', '-', '*', '*', '+', 0, 2, 2, 2, 0, 0]:
10 :['/', '+', 'b', '/', 'b', 'a', 'a', 'b', 'b']:['/', '+', '-', '-', 'b', 'a', 'a', 'a', 'b']:['/', '+', '-', '+', 'a', 'a', 'a', 'a', 'a']:['-', '+', 1, '/', 1, 2, 0, 2, 1, 0, 2]:
11 :['/', 'b', '/', 'a', 'b', 'b', 'b', 'a', 'a']:['-', '/', '/', 'b', 'b', 'a', 'a', 'b', 'b']:['+', '/', '+', '-', 'b', 'a', 'b', 'a', 'a']:['-', 1, 0, 2, '*', 0, 2, 1, 2, 2, 1]:
12 :['*', '+', 'b', '+', 'a', 'a', 'a', 'a', 'a']:['/', '/', '-', '+', 'b', 'a', 'b', 'b', 'b']:['/', 'b', '-', '+', 'b', 'a', 'b', 'a', 'b']:['*', '+', '/', 0, '/', 0, 1, 2, 1, 0, 1]:
13 :['/', 'a', 'a', '/', 'a', 'b', 'b', 'a', 'a']:['+', 'b', '*', 'a', 'a', 'b', 'a', 'a', 'a']:['/', '*', '/', '-', 'b', 'a', 'a', 'a', 'b']:['-', '*', '-', 1, '-', 2, 1, 2, 2, 2, 0]:
14 :['-', '-', '/', '-', 'b', 'b', 'a', 'a', 'a']:['-', 'b', '/', '/', 'a', 'a', 'a', 'b', 'a']:['+', '/', 'b', '-', 'a', 'b', 'b', 'b', 'a']:['+', '/', '*', '*', '+', 1, 2, 1, 2, 2, 2]:
15 :['+', 'b', '*', '/', 'a', 'a', 'b', 'b', 'a']:['/', '-', '+', '/', 'a', 'a', 'b', 'b', 'a']:['/', '/', '/', '-', 'b', 'a', 'b', 'b', 'b']:['/', 0, 1, '-', '/', 0, 0, 1, 1, 2, 1]:
16 :['-', 'b', 'a', '/', 'a', 'b', 'b', 'b', 'a']:['*', '*', 'a', '-', 'a', 'a', 'a', 'a', 'b']:['+', '-', '+', '-', 'b', 'b', 'a', 'a', 'a']:['*', 1, '/', '/', 2, 1, 0, 1, 2, 2, 1]:
17 :['*', '-', '*', '+', 'a', 'a', 'a', 'b', 'b']:['/', 'a', '/', 'b', 'b', 'b', 'b', 'a', 'a']:['-', 'b', 'b', '*', 'b', 'b', 'b', 'b', 'a']:['+', '-', 0, 2, '*', 1, 0, 0, 2, 2, 1]:
18 :['-', '-', '-', '/', 'b', 'b', 'a', 'b', 'a']:['-', '+', '/', '+', 'b', 'b', 'a', 'a', 'a']:['-', '/', '/', 'b', 'a', 'b', 'a', 'b', 'b']:['+', 1, 1, 2, 2, 1, 1, 2, 0, 0, 2]:
19 :['-', 'b', 'a', 'b', 'a', 'a', 'a', 'b', 'a']:['/', 'b', 'a', '*', 'b', 'b', 'a', 'b', 'a']:['+', '/', 'a', '+', 'b', 'a', 'a', 'a', 'a']:['-', '-', '*', 1, 1, 1, 1, 2, 1, 0, 1]:
[ 0 ] Fitness= 580.3166666666667
[ 1 ] Fitness= 609
[ 2 ] Fitness= 237.7
[ 3 ] Fitness= 624.6833333333333
[ 4 ] Fitness= 1
[ 5 ] Fitness= 645.9166666666667
[ 6 ] Fitness= 645.9166666666667
[ 7 ] Fitness= 609.0497442713691
[ 8 ] Fitness= 617.7087123960696
[ 9 ] Fitness= 625.2666666666667
[ 10 ] Fitness= 651.25
[ 11 ] Fitness= 569.0833333333334
[ 12 ] Fitness= 1
[ 13 ] Fitness= 724.0
[ 14 ] Fitness= 692.4166666666666
[ 15 ] Fitness= 525.3071428571429
[ 16 ] Fitness= 609.0
[ 17 ] Fitness= 363.0
[ 18 ] Fitness= 709.4999999999999
[ 19 ] Fitness= 577.1319444444443
进程已结束,退出代码0
为了方便演示,我将每个类整合到一个py文件上,GEP-5 适应度计算、评估实现
本文作者:九重!
本文链接:https://blog.csdn.net/weixin_43798572/article/details/122834003
关于博主:评论和私信会在第一时间回复。或者直接私信我。
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【点赞】【收藏】一下。您的鼓励是博主的最大动力!