前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何用遗传算法进化出一只聪明的小鹦鹉

如何用遗传算法进化出一只聪明的小鹦鹉

作者头像
Stanley Sun
发布2019-09-23 15:25:08
4700
发布2019-09-23 15:25:08
举报

问题

现在有一些样本数据,如下表所示。你是否能找到其中的规律,然后计算出新样本的output是多少?

input

output

样本1

5, 8, 7

9

样本2

2, 8, 4

6

样本3

3, 0, 5

3

样本4

9, 12, 13

15

新样本

10, 6, 8

?

乍一看,规律似乎并不明显。

仔细看,可能会发现其中的规律:output=input1+input2/2+input3*0,因此问号处的值应该是13。

现在,我们想让一只小鹦鹉来做这个事情。这当然不是现实中的小鹦鹉,而是我们用代码写的小鹦鹉。

小鹦鹉

小鹦鹉要想解出上面的题目,必须会“思考”。这里的思考,我们可以理解为:具有将input转换成output的能力。我们选择神经网络作为鹦鹉的大脑。

神经网络

我们知道,人脑中有无数个神经元,神经元之间通过轴突连接。当某个神经元接收到足够多的信号后,就会被“触发”。而被“触发”的神经元会发送信号到临近的神经元,临近的神经元接收到足够的信号后,又会被“触发”。这样的过程被称之为“思考”。

我们可以用程序模拟这个过程。为了简化,这里只使用一层网络。我们给每个轴突(连接神经元的线)设置一个权重,每一个input乘以相应的轴突权重会得出一个值,然后对这些值再求和,得出output。即output=input1*w1+input2*w2+input3*w3

这就是一个简单的“大脑”。大脑是否聪明,取决于[w1,w2,w3]的值的组合。如果这三个权重值能够满足提出的问题,那它就是“聪明”的,否则就是“笨”的。于是,刚才的问题就转换成:如何找到一组“聪明”的权重组合。

对于文章开头的问题,我们已经知道,[w1=1,w2=0.5,w3=0]这种组合是最好的。那,如何生成这样的“大脑”呢?

上帝之手

现在,我们可以扮演上帝的角色,随性的创造物种。假设我们创造了一只鹦鹉,它的脑子就是一个有3个权重的神经网络。这只鹦鹉只会做上面的题(但不一定能做好)。它的大脑是随机生成的,假设他的权重组合为[0.5,0.3,1.2]。

此时,这只鹦鹉就可以用大脑去“思考”上面的问题了。它会先看样本数据,从样本1开始看。这只鹦鹉根据input算出来的output是:0.5*5+0.3*8+1.2*7=13.3,而样本给出的output是9。于是它的误差(error1)是13.3-9=4.3。同样,还可以知道这只鹦鹉计算其它样本时的误差,它们分别是:

代码语言:javascript
复制
error2=2.2

error3=4.5

error4=8.7

我们知道,鹦鹉计算得越准(误差越小),就越聪明。因此,我们可以给鹦鹉的智商设定一个计算方法:

根据这个公式,可以算出这只鹦鹉的智商(intelligence)为9.15

我们再随机创建第二只鹦鹉。假设它的大脑的神经网络权重组合为[0.8,0.7,0.1]。

根据同样的方法,可以算出它的智商为35.65。它比第一支鹦鹉“聪明”!

进化

种群

我们可以创建一个鹦鹉种群,这个种群里有若干只鹦鹉,比如有100只。每个鹦鹉的智商也各不相同。下一步就是让这个种群进行自我进化。

进化

物竞天择、适者生存!大自然的这个法则,让地球上的物种不断进化,诞生了越来越高级的物种,乃至出现了我们人类。我们的这个鹦鹉种群也可以通过进化变得越来越聪明。

种群中的鹦鹉比拼的是智商。每一次比拼,我们把低智商的鹦鹉淘汰掉,把高智商鹦鹉留下来。然后,让留下来的鹦鹉繁衍下一代,这样它们和下一代的个体会组成一个新群体。然后再来一次全员智商比拼,再把低智商鹦鹉淘汰掉,高智商留下。留下的鹦鹉再次繁殖。这样不断迭代,经过若干代的筛选后,最后留下的就是特别聪明的鹦鹉。

在最后留下来的鹦鹉中,找到最聪明的那个。让它去“思考”文章开头提到的问题,它会给出一个不错的答案!

繁衍

现实中的鹦鹉是双性繁殖,那是长期进化的结果。我们的鹦鹉还很原始,只能单性繁殖:)

繁殖的方式是把自己复制一份,再做一次“基因突变”。所谓“基因突变”就是对神经网络的权重进行微调。比如有一只鹦鹉,它的大脑神经网络是[2, 3, 3.5],它繁衍的某一个后代可能是[2, 3.01, 3.5]或[1.98, 3, 3.5]等。

这样,后代基本保留了父代智商,又做了微调。这种微调可能是正向的(更聪明),也可能是负向的(更笨)。

代码

代码语言:javascript
复制
import random
import copy
import numpy as np

class Parrot():
    brain = 2 * np.random.random((3, 1)) - 1
    intelligence = 0

    def think(self,inputs):
        return np.dot(inputs,self.brain)

    '''
    基因变异
    '''    
    def mutation(self,max=0.05):
        #随机选中一个神经网络权重,进行微调
        index = np.random.randint(0,len(self.brain))
        adjustment = np.random.uniform(-max,max)
        self.brain[index] +=adjustment

    def copy(self):
        child = Parrot()
        child.brain = copy.copy(self.brain)
        child.intelligence = self.intelligence
        return child


class GA():
    def __init__(self, count):
        #进化的代数
        self.gen_num = 0
        # 种群中个体数量
        self.count = count
        # 种群个体要尽可能得去满足input和output关系
        self.inputs,self.outputs=self.load_data()
        # 随机生成初始种群
        self.population = self.gen_population(count)

    def load_data(self):
        inputs = np.array([[5, 8, 7], [2, 8, 4], [3, 0, 5], [9, 12, 13]])
        outputs = np.array([[9, 6, 3, 15]]).T
        return inputs,outputs

    def create_parrot(self):
        parrot = Parrot()
        parrot.brain = 2 * np.random.random((3, 1)) - 1
        parrot.intelligence = self.calc_intelligence(parrot)
        return parrot

    """
    获取初始种群
    """    
    def gen_population(self,count):
        return [self.create_parrot() for i in range(count)]    

    #计算适应度
    def calc_intelligence(self, parrot):
        errors = self.outputs - parrot.think(self.inputs)
        intelligence = 1/np.sum(np.sqrt(np.square(errors)))
        return intelligence

    '''
    繁殖
    '''
    def reproduction(self, mothers):
        # 新出生的孩子,最终会被加入存活下来的父母之中,形成新一代的种群。
        children = []
        # 需要繁殖的孩子的量
        target_count = len(self.population) - len(mothers)
        # 开始根据需要的量进行繁殖
        while len(children) < target_count:
            mother = mothers[np.random.randint(0,len(mothers))]
            child = mother.copy()
            child.mutation()
            children.append(child)
        self.population = mothers + children
    
    '''
    选择
    '''
    def selection(self, retain_rate, random_select_rate):
        # 计算每一个鹦鹉的智商
        graded = [(self.calc_intelligence(parrot), parrot) for parrot in self.population]
        # 智商从大到小进行排序
        graded = [x[1] for x in sorted(graded, key = lambda graded: graded[0], reverse=True)]
        # 选出智商最高的一部分鹦鹉
        retain_length = int(len(graded) * retain_rate)
        retain_parrots = graded[:retain_length]
        # 选出智商不高,但是幸存的鹦鹉
        for parrot in graded[retain_length:]:
            if random.random() < random_select_rate:
                retain_parrots.append(parrot)
        return retain_parrots        
    
    '''
    进化
    retain_rate:保留最聪明个体的比例
    random_select_rate:不够聪明的个体中,也要保留一定比例的个体,以保持物种的多样性。
    '''    
    def evolve(self,retain_rate=0.2, random_select_rate=0.2):
        self.gen_num += 1
        mothers = self.selection(retain_rate, random_select_rate)
        self.reproduction(mothers)

    def smartest_parrot(self):
        graded = [(self.calc_intelligence(parrot), parrot) for parrot in self.population]
        graded = [x[1] for x in sorted(graded, key = lambda graded: graded[0], reverse=True)]
        return graded[0]    

if __name__ == '__main__':
    #种群数量为100
    ga = GA(100)
    for x in range(300):
        ga.evolve()
    winner = ga.smartest_parrot()
    print("brain=",winner.brain.T)
    print("output=",winner.think(np.array([10, 6, 8])))

运行

代码语言:javascript
复制
python3 ga.py 

运行结果

代码语言:javascript
复制
brain= [[0.99293629 0.498883   0.00599333]]
output= [12.97060759]

新样本中的output应该是13,进化出来的鹦鹉给出的答案是12.97060759,已经相当接近!

它的大脑[0.99293629, 0.498883, 0.00599333]与最优解[1,0.5,0]非常接近!

这就是自然选择的力量!

让我们向大自然的规则致敬!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题
  • 小鹦鹉
    • 神经网络
      • 上帝之手
      • 进化
        • 种群
          • 进化
            • 繁衍
              • 代码
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档