遗传算法/人工智能;基本上,我走在正确的道路上吗?

我知道用Python来编写这种类型的软件并不是最佳选择。我的理由是希望在Raspberry Pi 3的决策中使用这种算法(我还不确定这会如何进行),而且我将使用的库和API(Adafruit电机HATs、Google服务、OpenCV、各种传感器等)在Python中导入都很友好,更不用说我对于rPi来说,在这个环境中更加舒适。虽然我已经诅咒过面向对象的编程语言,如Java或C++对我来说更有意义,但我宁愿处理Python的低效性,并专注于rPi的整体集成大局。

我不会在这里解释代码,因为脚本中的注释部分已经很好地记录了这些。我的问题如上所述;这可以被认为是基本的遗传算法吗?如果不是,它必须具备什么才能成为基本的AI或遗传代码?我对于这种问题解决方法是否走在正确的道路上?我知道通常会有加权变量和函数来促进“适者生存”,但我想这些可以在需要时加入。

我已经阅读了很多关于这个话题的论坛和文章。我不想复制我几乎不理解的别人的代码,并将其作为我更大项目的基础;我想确切地了解它的工作原理,这样我才不会在途中因为某件事情不工作而感到困惑。所以,我只是试图理解它的基本工作原理,并按照我的理解来编写。请记住我想继续使用Python。对于这个,我知道rPi有多个C++、Java等环境,但如前所述,我使用的硬件组件大多只有Python API来实现。如果我错了,请在算法层面解释,而不是只用一段代码(再次强调,我真的想理解这个过程)。另外,除非与我的问题相关,否则请不要挑剔代码惯例,每个人都有自己的风格,这只是一个草图。现在就展示给大家,感谢阅读!

# Created by @X3r0, 7/3/2016# Basic genetic algorithm utilizing a two dimensional array system.# the 'DNA' is the larger array, and the 'gene' is a smaller array as an element# of the DNA. There exists no weighted algorithms, or statistical tracking to# make the program more efficient yet; it is straightforwardly random and solves# its problem randomly. At this stage, only the base element is iterated over.# Basic Idea:# 1) User inputs constraints onto array# 2) Gene population is created at random given user constraints# 3) DNA is created with randomized genes ( will never randomize after )#   a) Target DNA is created with loop control variable as data (basically just for some target structure)# 4) CheckDNA() starts with base gene from DNA, and will recurse until gene matches the target gene#   a) Randomly select two genes from DNA#   b) Create a candidate gene by splicing both parent genes together#   c) Check candidate gene against the target gene#   d) If there exists a match in gene elements, a child gene is created and inserted into DNA#   e) If the child gene in DNA is not equal to target gene, recurse until it isimport randomDNAsize = 32geneSize = 5geneDiversity = 9geneSplit = 4numRecursions = 0DNA = []targetDNA = []def init():    global DNAsize, geneSize, geneDiversity, geneSplit, DNA    print("This is a very basic form of genetic software. Input variable constraints below. "          "Good starting points are: DNA strand size (array size): 32, gene size (sub array size: 5, gene diversity (randomized 0 - x): 5"          "gene split (where to split gene array for splicing): 2")    DNAsize = int(input('Enter DNA strand size: '))    geneSize = int(input('Enter gene size: '))    geneDiversity = int(input('Enter gene diversity: '))    geneSplit = int(input('Enter gene split: '))    # initializes the gene population, and kicks off    # checkDNA recursion    initPop()    checkDNA(DNA[0])def initPop():    # builds an array of smaller arrays    # given DNAsize    for x in range(DNAsize):        buildDNA()        # builds the goal array with a recurring        # numerical pattern, in this case just the loop        # control variable        buildTargetDNA(x)def buildDNA():    newGene = []    # builds a smaller array (gene) using a given geneSize    # and randomized with vaules 0 - [given geneDiversity]    for x in range(geneSize):        newGene.append(random.randint(0,geneDiversity))    # append the built array to the larger array    DNA.append(newGene)def buildTargetDNA(x):    # builds the target array, iterating with x as a loop    # control from the call in init()    newGene = []    for y in range(geneSize):            newGene.append(x)    targetDNA.append(newGene)def checkDNA(childGene):    global numRecursions    numRecursions = numRecursions+1    gene = DNA[0]    targetGene = targetDNA[0]    parentGeneA = DNA[random.randint(0,DNAsize-1)]          # randomly selects an array (gene) from larger array (DNA)    parentGeneB = DNA[random.randint(0,DNAsize-1)]    pos = random.randint(geneSplit-1,geneSplit+1)           # randomly selects a position to split gene for splicing    candidateGene = parentGeneA[:pos] + parentGeneB[pos:]   # spliced gene given split from parentA and parentB    print("DNA Splice Position: " + str(pos))    print("Element A: " + str(parentGeneA))    print("Element B: " + str(parentGeneB))    print("Candidate Element: " + str(candidateGene))    print("Target DNA: " + str(targetDNA))    print("Old DNA:    " + str(DNA))    # iterates over the candidate gene and compares each element to the target gene    # if the candidate gene element hits a target gene element, the resulting child    # gene is created    for x in range(geneSize):        #if candidateGene[x] != targetGene[x]:            #print("false ")        if candidateGene[x] == targetGene[x]:            #print("true ")            childGene.pop(x)            childGene.insert(x, candidateGene[x])    # if the child gene isn't quite equal to the target, and recursion hasn't reached    # a max (apparently 900), the child gene is inserted into the DNA. Recursion occurs    # until the child gene equals the target gene, or max recursuion depth is exceeded    if childGene != targetGene and numRecursions < 900:        DNA.pop(0)        DNA.insert(0, childGene)        print("New DNA:   " + str(DNA))        print(numRecursions)        checkDNA(childGene)init()print("Final DNA:  " + str(DNA))print("Number of generations (recursions): " + str(numRecursions))

回答:

我现在正在研究进化计算,所以我希望我的回答对你有帮助。个人来说,我主要使用Java,因为这是我的主要语言之一,而且为了便携性,因为我在Linux、Windows和Mac上都进行了测试。在我的案例中,我使用排列编码,但如果你还在学习GA的工作原理,我强烈推荐使用二进制编码。这是我称之为初始种群的东西。我尝试描述我的程序工作流程:

1-. 设置我的主要变量

这些是种群大小、个体大小、变异率、交叉率。你还需要创建一个目标函数,并决定你使用的交叉方法。举个例子,假设我的种群大小等于50,个体大小是4,变异率是0.04%,交叉率是90%,交叉方法将是轮盘赌法。我的目标函数只想检查我的个体是否能够以二进制表示数字15,所以最佳个体必须是1111

2-. 初始化我的种群

为此,我创建了50个个体(50由我的种群大小决定),并随机生成基因。

3-. 循环开始

对于种群中的每个个体,你需要:

  • 根据目标函数评估适应度。如果一个个体由以下字符表示:00100,这意味着他的适应度是1。正如你所见,这是一个简单的适应度函数。你可以在学习过程中创建自己的函数,比如fitness = 1/numberOfOnes。你还需要将所有适应度的总和分配给一个名为populationFitness的变量,这在下一步中会很有用。
  • 选择最佳个体。对于这项任务,有很多方法可以使用,但我们将使用之前提到的轮盘赌法。在这种方法中,你为种群中的每个个体分配一个值。这个值由以下公式给出:(fitness/populationFitness) * 100。所以,如果你的种群适应度是10,而某个个体的适应度是3,这意味着这个个体有30%的几率被选中与另一个个体进行交叉。同样,如果另一个个体的适应度是4,他的值将是40%。
  • 应用交叉。一旦你有了种群中“最佳”的个体,你需要创建一个新的种群。这个新种群由之前种群中的其他个体组成。对于每个个体,你创建一个从0到1的随机数。如果这个数字在0.9的范围内(因为我们的交叉率是90%),这个个体可以繁殖,所以你选择另一个个体。每个新个体都有这两个父母,他们继承了他们的基因。例如:假设parentA = 1001parentB = 0111。我们需要用这些基因创建一个新个体。有很多方法可以做到这一点,统一交叉、单点交叉、双点交叉等。我们将使用单点交叉。在这种方法中,我们在第一个基因和最后一个基因之间选择一个随机点。然后,我们根据parentA的前几个基因和parentB的后几个基因创建一个新个体。视觉上展示如下:

parentA = 1001parentB = 0111crossoverPoint = 2newIndividual = 1011

如你所见,新个体共享了父母的基因。

  • 一旦你有了带有新个体的新种群,你应用变异。在这种情况下,对于新种群中的每个个体,生成一个介于0和1之间的随机数。如果这个数字在0.04的范围内(因为我们的mutationRate = 0.04),你在一个随机基因上应用变异。在二进制编码中,变异只是将1变为0或反之。视觉上展示如下:

individual = 1011randomPoint = 3mutatedIndividual = 1010

  • 获取最佳个体

  • 如果这个个体已经达到了解决方案,则停止。否则,重复循环

  • 结束

如你所见,我的英语不是很好,但我希望你能理解遗传算法的基本概念。如果你真的有兴趣学习这个,你可以查看以下链接:

http://www.obitko.com/tutorials/genetic-algorithms/这个链接更清晰地解释了遗传算法的基础知识

http://natureofcode.com/book/chapter-9-the-evolution-of-code/这本书也解释了什么是GA,但也提供了Processing中的一些代码,基本上是Java。但我想你能理解。

我还推荐以下书籍:

遗传算法导论 – Melanie Mitchell

理论与实践中的进化算法 – Thomas Bäck

遗传算法导论 – S. N. Sivanandam

如果你没有钱,你可以很容易地找到这些书的PDF版本。另外,你可以随时在scholar.google.com上搜索文章,几乎所有都是免费下载的。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注