这个系列还有两篇:
计算机智能专题-遗传算法(1不带约束的)_两只蜡笔的小新的博客-CSDN博客
计算机智能专题-遗传算法(2带约束的实数编码)_两只蜡笔的小新的博客-CSDN博客
前言:
遗传算法的原理及python实现
一、原理
遗传算法(Genetic Algorithm, GA)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。
其主要特点是直接对结构对象进行操作,不存在求导和函数连续性的限定;具有内在的隐并行性和更好的全局寻优能力;采用概率化的寻优方法,不需要确定的规则就能自动获取和指导优化的搜索空间,自适应地调整搜索方向。
遗传算法以一种群体中的所有个体为对象,并利用随机化技术指导对一个被编码的参数空间进行高效搜索。其中,选择、交叉和变异构成了遗传算法的遗传操作;参数编码、初始群体的设定、适应度函数的设计、遗传操作设计、控制参数设定五个要素组成了遗传算法的核心内容。
二、整体步骤
以下步骤是遗传算法的基本原理,可以在此基础上进行扩展。
三、编程实现
求0.5x-x^2的最大值,x为整数。
import numpy as np
import copy
'''目标函数'''
f = lambda x:0.5*x-x*x
class genetic_algorithms():
def __init__(self,N=8,Bit_num=5):
_groups = np.zeros([N,Bit_num],int)
for index in range(0,N):
for _index in range(0,Bit_num):
_groups[index,_index] = np.random.choice([0,1])
self._groups = _groups
def Binary2Decimal(self,Binary,include_negative=False):
'''
fct: 将二进制转化为十进制
:param Binary: 输入的二进制数组
:param include_negative: 最高位是不是 符号位
:return:
'''
sum = 0
bit_flag = -1 if include_negative==True else 1
for index in range(1,len(Binary)):
sum = sum + Binary[-index]*2**(index-1)
if bit_flag==-1:
if Binary[0]==1:
sum = sum * bit_flag
else:
sum = sum + 0
else:
sum = sum + Binary[0]*2**(index)
return sum
# 适宜度的设计 很重要
# 会出现负数,负数怎么处理
# 这里将 负数变成正数 进行处理
def calculate_suitability(self,input):
y_get = list(map(lambda x:f(x),input))
if np.min(y_get)<=0:
input_Data = y_get - np.min(y_get) # 这里有一个bug 当所有的值都为 负数 且都一样时,分母为零
if np.sum(input_Data)==0:
input_Data = list(map(lambda x:x+1,input_Data))
else:
input_Data = y_get
out_data = []
for data in input_Data:
out_data.append(float(data)/np.sum(input_Data))
return out_data
def optimize_choose(self,input_Data):
out_data_index = []
for index in range(len(input_Data)): # 需要优选的次数
random_value = np.random.rand(1)
sum_value = 0
for _index in range(len(input_Data)): # 遍历查找优选的值
sum_value = sum_value + input_Data[_index]
if random_value <= sum_value:
out_data_index.append(_index)
break
else:
continue
return out_data_index
def cross_variation(self,init_groups, opt_chose):
opt_chose_data = [] # 优选的后的结果
for opt_flag in opt_chose:
opt_chose_data.append(init_groups[opt_flag,:])
cross_Data = copy.deepcopy(opt_chose_data)
# 分组
index_groups = list(range(0,len(init_groups)))
np.random.shuffle(index_groups) #分组是随机的,按顺序排完之后,再次打乱
# 染色体 交叉
# 1. 交叉的位置是随机的
for index in range(0,int(len(index_groups)/2)):
index = index*2
variation_site = np.random.choice(list(range(0,np.shape(init_groups)[-1]))[1:]) # 变异的起始位置 是随机的
try:
variation_data = opt_chose_data[index_groups[index]][variation_site:] # 保存 中间变量
except:
a = 10
cross_Data[index_groups[index]][variation_site:] = opt_chose_data[index_groups[index+1]][variation_site:]
cross_Data[index_groups[index + 1]][variation_site:] = variation_data
# 染色体 变异
# 1. 变异的位置是随机的
# 2. 变异是否 发生是随机的
variation_Data = copy.deepcopy(cross_Data)
variation_value = 1/np.shape(init_groups)[-1]
for index in range(len(variation_Data)):
variation_random_value = np.random.rand(1)
if variation_random_value>=variation_value:
variation_site = np.random.choice(list(range(0, np.shape(init_groups)[-1]))[1:]) #变异发生的位置
variation_Data[index][variation_site] = 1 - variation_Data[index][variation_site]
return np.array(variation_Data)
def run(self):
init_groups = self._groups
data_collect = []
for epochs in range(100):
y_group = [] # 转十进制
for Binary in init_groups:
y_group.append(self.Binary2Decimal(Binary,True))
if y_group[0]=='nan':
a = 10
y_suit = self.calculate_suitability(y_group)
opt_chose = self.optimize_choose(y_suit)
cross_variation_data = self.cross_variation(init_groups, opt_chose)
init_groups = copy.deepcopy(cross_variation_data)
y_get = list(map(lambda x: f(self.Binary2Decimal(x,True)), init_groups))
data_collect.append(np.max(y_get))
print('epoch: %d 当前最优值为%f'%(epochs,np.max(data_collect)))
# print('epoch: %d 当前最优值为%f'%(epochs,np.max(y_get)))
# if __name__=='__mian__':
obj = genetic_algorithms(N=4,Bit_num=9)
obj.run()
版权声明:本文为weixin_44503976原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。