import numpy as np
2.定义@R_404_6195@pop_size = 10 # 种群数量PC=0.6 # 交叉概率PM=0.01 #变异概率X_max=5 #最大值X_min=0 #最小值DNA_SIZE=10 #DNA长度与保留位数有关,2**10 当前保留3位小数点N_GENERATIONS=1000
3.定义遗传算法核心函数a.目标函数
"""求解的目标表达式为:y = 10 * math.sin(5 * x) + 7 * math.cos(4 * x)x=[0,5]"""def aim(x):return 10*np.sin(5*x)+7*np.cos(4*x)
b.解码函数
def decode(pop): return pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) *(X_max-X_min)/ float(2**DNA_SIZE-1) +X_min
我们的种群采取二进制的编码方式,通过这个函数将二进制解码为【X_min,X_max】之间的数。
公式可参考:
c.适应度计算函数
def fitnessget(pred): return pred + 1e-3 - np.min(pred)
一般来说,如果拟合在x的定义域内值域为非负的函可以直接将aim函数作为适应度函数,但是这里我们要拟合的函数包含负数情况,故我们要对其处理变为非负。
d.自然选择函数(轮盘赌)
def select(pop, fitness): # print(abs(fitness)) # print(fitness.sum()) IDx = np.random.choice(np.arange(pop_size), size=pop_size, replace=True,p=fitness/fitness.sum()) # print(IDx) return pop[IDx]
轮盘赌算法是比较常用的算法,直白点就是撞大运,适应度高的个体有更大的几率被选择
e.交叉函数
def change(parent, pop): if np.random.rand() < PC: #交叉 i_ = np.random.randint(0, pop_size, size=1) # print(parent) cross_points = np.random.randint(0, 2, size=DNA_SIZE).astype(np.bool) # print(np.where(cross_points==True)) # print(cross_points) parent[cross_points] = pop[i_, cross_points] # print(parent) return parent
我们之所以选择二进制的形式编码,就是因为二进制编码可以很好地模拟染色体的交叉。
即又0——>1,1——>0。但是在一个较小的种群中交配,就是我们所说的近亲间的结婚,子代会有可能继承父代的缺点,所以需要变异。
f.变异函数
def variation(child,pm): #变异 for point in range(DNA_SIZE): if np.random.rand() < pm: child[point] = 1 if child[point] == 0 else 0 # print(child) return child
至此,遗传算法的全部过程已经结束,不难看出,遗传算法最精髓最重要的地方,便是随机性,虽然每一步 *** 作都充满了随机性,可最终我们仍然会得到最优个体,这是遗传算法的魅力,也是大自然设计的魅力。
4.开始拟合pop = np.random.randint(2, size=(pop_size, DNA_SIZE))# print(pop)for i in range(N_GENERATIONS): #解码 # print(pop) X_value= decode(pop) #获取目标函数值 F_values = aim(X_value) #获取适应值 fitness = fitnessget(F_values) # print(fitness) if(i==0): max=np.max(F_values) max_DNA = pop[np.argmax(F_values), :] if(max<np.max(F_values)): max=np.max(F_values) max_DNA=pop[np.argmax(F_values), :] if (i % 10 == 0): print("Most fitted value and X: \n", np.max(F_values), decode(pop[np.argmax(F_values), :])) #选择 pop = select(pop,fitness) # print(pop) pop_copy = pop.copy() # print(pop_copy) for parent in pop: # print(parent) child = change(parent,pop_copy) child = variation(child,PM) # print(child) parent[:] = childprint("目标函数最大值为:",max)print("其DNA值为:",max_DNA)print("其X值为:",decode(max_DNA))
理解了算法的本质后,再看代码自然不会有太大的难度,这里不过多解释了
5.思考在前面的实现中,我侧重了染色体的交叉,得到了一个不错的结果,如果我们修改@R_404_6195@
pop_size = 50 # 种群数量PC=0.01 # 交叉概率PM=0.99 #变异概率X_max=5 #最大值X_min=0 #最小值DNA_SIZE=10 #DNA长度与保留位数有关,2**10 当前保留3位小数点N_GENERATIONS=1000
即完全依靠变异来进化,也是可以获得很好的结果的呢,这充分说明了遗传算法的核心便是随机!
二.使用第三方库pip install scikit-opt
这是个功能很强大效果很好的进化算法的第三方库官方文档,大家自行参考官方源码
这里给出最简单的实现
import numpy as npdef schaffer(p): ''' This function has plenty of local minimum, with strong shocks global minimum at (0,0) with value 0 ''' x= p[0] return 5*np.sin(np.log(x)) from sko.GA import GAga = GA(func=schaffer, n_dim=1, size_pop=100, max_iter=800, lb=0, ub=10, precision=1e-7)best_x, best_y = ga.run()print('best_x:', best_x, '\n', 'best_y:', best_y)import pandas as pdimport matplotlib.pyplot as pltx = np.arange(0,10,0.01)y = 5*np.sin(np.log(x))plt.plot(x,y)plt.show()
短短20行代码便能实现~三.总结
进化计算的算法熟练后可以运用到设置深度学习网络的参数,进化计算还有很大的发展空间。
总结以上是内存溢出为你收集整理的遗传算法的Python实现(通俗易懂)全部内容,希望文章能够帮你解决遗传算法的Python实现(通俗易懂)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)