智科人工智能最后的大实验是四选一的:当然选择最简单的遗传算法。。。
不过BP手写数字识别也在机器学习的大课设那篇文章中有写,感兴趣也可以去学习。。。。
遗传算法的程序我放在资料区提供下载,具有动态绘图功能,验收时候老师应该会让你改函数,问你怎么求最小值(如果你一开始设置的是求最大值),只需要回答说把那个适应度函数改成原来求最大值时候的倒数,或者根据她问的其他问题:改成原来函数的负数等等。
至于why,自己想就知道了,如果求最大的那个点,我改倒数或者负数是不是反过来了。。。。。。
如果遗传算法选的人多,那么先验收的才有优,抓紧时间!
文件名:人工智能之遗传算法参考程序
文件内容参考:
动态绘制过程:(程序在资料区)
报告如下:
5.程序设计与实现、解析
代码的注释都是自己打上去的
max_loop = 200 # 最大迭代次数 100~500
tribe_number = 50 # 种群初始化数量 20~100
limit_left = -1 # 定义域左界限
limit_right = 1 # 定义域右界限
limit_bit = 15 # 编码位数
cross_probability = 0.9 # 交叉概率 0.4~0.99
variation_probability = 0.1 # 变异概率 0.0001~0.1
actions_probability = np.array([cross_probability, variation_probability])
解码方法(用了上文说的等差数列来决定每个元素)
def To_decode(num):
x = num[:15] #0到14位
y = num[15:]
# 转为10进制整数
x = int(str(x), 2) #后是二进制
y = int(str(y), 2)
# 转换为-1,1区间的小数
d = fabs(limit_left - limit_right) / (2 ** limit_bit - 1)
x = limit_left + d * x
y = limit_left + d * y
return x, y #返回x,y对应的(-1,1)区间小数
# 初始化一个二进制基因个体
def init_one(bit=30):
s = ''
for i in range(bit):
s += str(random.randint(0, 1)) #随机0,1插入
return s #返回一个30位的二进制串
# 初始化一个种群,第一代
def init_tribe(tribe_number): #参数tribe_number是种群个数
tribe = []
while len(set(tribe)) != tribe_number: #set集合筛选list当中不同的元素,set不能重复的,len返回集合元素个数,要参数这么多个
tribe.append(init_one()) #把所有的添加这个tribe,成为['11','22']这种形式
return tribe
tribe这个列表中存着第一个种群,一个个体(元素)三十位
def roulette_select_tribe(value, tribe):#用tribe列表的值value做参数
'''''
轮盘选择: 根据概率选择出个体, 返回选择后的种群
这里优化了一个操作,就是始终会将 启发值最大的节点加入选择后的种群
:param value: 传入参数: 代表每个个体被选择的概率
:param tribe: 传入参数: 代表种群的信息 ['11','22']这种形式
:return:
'''
new_tribe = []
# 设置随机数种子
np.random.seed(random.randint(1, 100) + random.randint(100, 10000000))
index_list = [i for i in range(tribe_number)] #返回索引值,0到49
for i in range(tribe_number): #添加五十次(个体总数)
# 根据概率获取索引
index = np.random.choice(index_list, p=value.ravel()) #p为概率,拉直value代表的列表,index对应的原value值大的更大可能被选中,选中的是index_list中的index(索引)
new_tribe.append(tribe[index]) #不断添加选中的下标对应的值
# 判断启发值最大的节点是否被加入
li = list(value) #value变成列表
max_index = li.index(max(li))
if tribe[max_index] not in new_tribe:
tmp_value = list(estimate(new_tribe))
min_index = tmp_value.index(min(tmp_value))
new_tribe[min_index] = tribe[max_index]
return new_tribe
# 返回被选择的个体索引(下标)
def roulette_select_human(value, tribe): #选一个个体,主要看参数value代入的是哪个
'''''
轮盘选择: 根据概率选择出个体, 返回一个被选择的对象与其索引
:param value: 传入参数: 代表每个个体被选择的概率
:param tribe: 传入参数: 代表种群的信息
'''
np.random.seed(random.randint(1, 100) + random.randint(100, 10000000))
index_list = [i for i in range(tribe_number)] #索引列表
index = np.random.choice(index_list, p=value.ravel()) #ravel扁平化拉数组为一维
return tribe[index], index #只选择了一次
# 评估每个个体被选择的概率
def estimate(tribe):
'''''
返回一个 numpy.array类型的 概率数组,代表了tribe中每一个个体被选中的概率
'''
start_value = []
for human in tribe: #定义一个human代表tribe中的每个原二进制码
x, y = To_decode(human) #return x,y代表的定义域内的小数过来
human_value = 1+x*sin(pi*y) +y*sin(pi*x)
start_value.append(human_value if human_value > 0 else 0) #大于0的赋进来,否则赋个0
# 将列表中的每个value转换为相应的概率
result_value = [i / sum(start_value) for i in start_value]
return np.array(result_value) #概率数组
交叉操作
if type == '交叉':
# 初始化需要的参数
value = estimate(tribe)
cross_tmp = [] #记忆位点的列表,不能重复从该位点交叉
# 随机选择父母节点
father, father_index = roulette_select_human(value, tribe)
mother, mother_index = roulette_select_human(value, tribe)
# 随机确定 交叉点
cross_location = random.randint(0, 29) #30位中随便找个交叉位点
cross_tmp.append(cross_location)
# 执行交叉操作
infant = father[0:cross_location] + mother[cross_location:]
# 计算其评估值是否变优秀,没有变优秀就重来
score = cal_func(infant) - cal_func(father)
while score < 0:
if len(cross_tmp) == 30:
return tribe
cross_location = random.randint(0, 29)
if cross_location in cross_tmp: #判断是否已经选择过这个位点交叉,选择过了就continue重新循环找
continue
cross_tmp.append(cross_location) #选择过的加入记忆列表
infant = father[0:cross_location] + mother[cross_location:]
score = cal_func(infant) - cal_func(father)
# 修改tribe (将交叉后的结果与原先的节点替换/不变)
tribe[father_index] = infant
return tribe
变异操作
if type == '突变':
# 初始化需要的参数
value = estimate(tribe) #概率数组
# 随机选择变异节点
variation_human, variation_human_index = roulette_select_human(value, tribe) #随机选,但是是概率大的中标
tmp_human = variation_human
# 随机选择变异位置
variation_location = random.randint(0, 29)
# 取反
num = 1 - int(variation_human[variation_location])
tmp = list(variation_human)
tmp[variation_location] = str(num)
variation_human = ''.join(tmp) #’‘与后面连接成新字符串
# 判断是否有效
if cal_func(variation_human) < cal_func(tmp_human): #有效突变
tribe[variation_human_index] = variation_human
return tribe
函数动态画图出来表示的方法
#画图准备
fig = plt.figure() # 创建空图像
ax = Axes3D(fig) # 创建3D图像
plt.ion() # 切换到交互模式绘制动态图像
init_graph(ax) # 初始化图
plt.ioff() # 关闭交互模式
plt.show() # 绘制结果
# 循环结束,得到最终优秀的tribe
# 找到里面 value最大的情况即可
print('循环结束')
把这个二元函数画出来的方法,再在什么取点找极大值
def init_graph(ax):
#fig=plt.figure(figsize=(5,5)) #绘制画布尺寸
#ax=Axes3D(fig) #绘制三维图形
ax.set_zlim(-2, 2) # 自定义z轴范围
ax.set_xlabel('x') # 设置x坐标轴标题
ax.set_ylabel('y') # 设置y坐标轴标题
ax.set_zlabel('z') # 设置z坐标轴标题
#x,y的取值区间范围
x=np.arange(-1,1,0.01)
y=np.arange(-1,1,0.01)
z=np.arange(-1, 1, 0.00000001)
x,y=np.meshgrid(x,y)
#定义二元函数
z=function(x, y)
#图形绘制风格
ax.plot_surface(x, y, z,rstride=5,cstride=2,cmap=plt.get_cmap('rainbow'), edgecolor='none')
#绘制图形
plt.show()
7.关键参数分析
'''全局变量'''
max_loop = 200 # 最大迭代次数 100~500
tribe_number = 50 # 种群初始化数量 20~100
limit_left = -1 # 定义域左界限
limit_right = 1 # 定义域右界限
limit_bit = 15 # 编码位数
cross_probability = 0.9 # 交叉概率 0.4~0.99
variation_probability = 0.1 # 变异概率 0.0001~0.1
关键参数就是迭代的次数、种群的数量、定义域、编码位数等等,这些都会对结果造成改变,像我取的15位,会让结果更加接近,更加精确。
这里取的交叉和变异概率相加为1,方便调用python中的函数进行操作。
三、课程设计(综合实验)总结或结论
略
四、参考文献
知乎-使用遗传算法求解函数最值
https://zhuanlan.zhihu.com/p/94477212
笔者介绍:某智科卑微牛马,一项省级大创已结项,一项国家级大创和一项校级大创已成功立项,都交给小自己一届的学弟去做,参加的挑战杯项目在其余队友参加大创后也获得了省级优秀和国家级优秀结项。同时组织并担任了2022年挑战杯、两项互联网+、电子商务大赛、舞蹈机器人大赛、“创青春”青年创新创业大赛的队长,并参加过节能减排大赛、调研河北大赛、数学建模美赛、蓝桥杯省赛、机器人国赛等比赛若干,获得过舞蹈机器人一等、电子商务大赛二等、挑战杯三等、节能减排省一等、创新创业优秀个人、社会实践优秀个人等奖项。
程序下载说明:作者所有的实验、课设验收基本都是优,也不缺这几米,不过不想自己的文章或者作品烂大街,想留点门槛,应该是几米这样子,作品都是保证高质量的,给有需要的学弟学妹们学习,大部分还是免费的,因为一些大型的文件不好上传,故放在付费资料区下载,真的非常良心!!