我知道Python并不是编写任何此类软件的最佳选择。我的理由是将这种类型的算法用于Raspberry Pi 3的决策制定(仍然不确定将如何进行),以及我将使用的库和API(Adafruit motor HATs,Google服务,OpenCV,各种传感器等都可以很好地用于Python导入,更不用说我在这个环境中更适合rPi了。我已经诅咒了它,因为面向对象(如Java或C ++)对我来说更有意义,但我更倾向于处理它的低效率并专注于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 is
import random
DNAsize = 32
geneSize = 5
geneDiversity = 9
geneSplit = 4
numRecursions = 0
DNA = []
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))
答案 0 :(得分:4)
我现在正在使用进化计算,所以我希望我的回答对你有帮助,我个人使用java,主要是因为它是我的主要语言之一,并且为了便携性,因为我在linux中测试过, Windows和Mac。在我的情况下,我使用置换编码,但如果你仍在学习GA如何工作,我强烈建议使用二进制编码。这就是我所说的InitialPopulation。我试着描述我的程序的工作流程:
这是PopulationSize,IndividualSize,MutationRate,CrossoverRate。您还需要创建一个目标函数并决定您使用的交叉方法。对于此示例,我们说我的PopulationSize等于50
,IndividualSize为4
,MutationRate为0.04%
,CrossoverRate为90%
,交叉方法为轮盘赌轮。
我的目标函数只是检查我的个人是否能够用二进制表示数字15,所以最好的个人必须是1111
。
为此,我使用随机基因创建50
个人(50
由我的PopulationSize提供)。
对于每个人口中的每个人,您需要:
00100
这意味着他的健康状况是1.你可以看到这是一个简单的健身功能。您可以在学习期间创建自己的,例如fitness = 1/numberOfOnes
。此外,您需要将所有适应度的总和分配给名为populationFitness
的变量,这将在下一步中有用。(fitness/populationFitness) * 100
。因此,如果您的人口适应度为10,并且某个人的适应度为3,则这意味着该个人有30%的机会被选中与另一个人进行交叉。此外,如果另一个人的健康状况为4,那么他的价值将是40%。90%
),此个人可以重现,因此您选择另一个人。每个新人都有这2个父母继承他的基因。例如:
让我们说parentA = 1001
和parentB = 0111
。我们需要用这个基因创造一个新的个体。有很多方法可以做到这一点,统一交叉,单点交叉,两点交叉等。我们将使用单点交叉。在这种方法中,我们选择第一个基因和最后一个基因之间的随机点。然后,我们根据parentA
的第一个基因和parentB
的最后一个基因创建一个新的个体。以视觉形式: parentA = 1001
parentB = 0111
crossoverPoint = 2
newIndividual = 1011
正如你所看到的,这个新人分享了他父母的基因。
mutationRate = 0.04
),则在随机基因中应用突变。在二进制编码中,突变只是将0改为0或反之。以视觉形式: individual = 1011
randomPoint = 3
mutatedIndividual = 1010
获得最佳个人
如果此人已达到解决方案停止。否则,重复循环
结束
正如你所看到的,我的英语不是很好,但我希望你理解遗传算法的基本思想。如果您真的对此有兴趣,可以查看以下链接:
http://www.obitko.com/tutorials/genetic-algorithms/ 该链接以更清晰的方式解释了遗传算法的基础知识
http://natureofcode.com/book/chapter-9-the-evolution-of-code/ 本书还解释了GA是什么,还提供了一些Processing中的代码,基本上都是java。但我认为你可以理解。
我还会推荐以下书籍:
遗传算法导论 - 梅兰妮米切尔
理论与实践中的进化算法 - ThomasBäck
遗传算法简介 - S. N. Sivanandam
如果您没有钱,您可以轻松地以PDF格式查找所有这些书籍。 此外,您始终可以在scholar.google.com中搜索文章 几乎所有人都可以免费下载。
答案 1 :(得分:1)
为了向Alberto提供一些很好的答案,您需要在解决方案发展过程中注意两个问题。
第一个是过度拟合。这基本上意味着您的解决方案足够复杂,可以学习&#34;所有样本,但不适用于训练集之外。为避免这种情况,您需要确保&#34;金额&#34;您的训练集中的信息量远远大于您的解决方案中可以容纳的信息量。
第二个问题是Plateaus。在某些情况下,你会得到某些平庸的解决方案,但这些解决方案足以胜任&#34;胜出&#34;任何新兴的解决方案,所以你的进步停滞不前(一种看待这种情况的方法是,如果你看到你的健康状况&#34;卡住&#34;在一定的,低于最佳的数字)。解决这个问题的一种方法是灭绝:您可以跟踪最佳解决方案的改进速度,如果最近N代的改进为0,那么您只需要破坏您的人口。 (也就是说,删除您的人口和最佳个人名单并重新开始)。随机性将使解决方案最终超越高原。
另外要记住的是,默认的Random类在Randomness中非常糟糕。只需使用Mesernne Twister随机发生器或硬件熵发生器等产品,我就可以大大改善解决方案。
我希望这会有所帮助。祝你好运。