智科人之人工智能大实验四选一验优报告参考:基于遗传算法的函数极值求取

智科人工智能最后的大实验是四选一的:当然选择最简单的遗传算法。。。
不过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年挑战杯、两项互联网+、电子商务大赛、舞蹈机器人大赛、“创青春”青年创新创业大赛的队长,并参加过节能减排大赛、调研河北大赛、数学建模美赛、蓝桥杯省赛、机器人国赛等比赛若干,获得过舞蹈机器人一等、电子商务大赛二等、挑战杯三等、节能减排省一等、创新创业优秀个人、社会实践优秀个人等奖项。

程序下载说明:作者所有的实验、课设验收基本都是优,也不缺这几米,不过不想自己的文章或者作品烂大街,想留点门槛,应该是几米这样子,作品都是保证高质量的,给有需要的学弟学妹们学习,大部分还是免费的,因为一些大型的文件不好上传,故放在付费资料区下载,真的非常良心!!

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

华电第一深情

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值