[英]genetic algorithm string guess
我试图了解如何实现遗传算法并编写了一个简单的字符串猜测。 我无法理解为什么此解决方案无法正常工作。
我相信我的问题在于我的新世代吗? 最新一代似乎并没有提高健身价值。 我也不确定我是否正确执行了交叉和变异率。 任何帮助将非常感激!
POP_SIZE = 300;
CROSSOVER_RATE = 0.7;
MUTATION_RATE = 0.01
GENESET = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"
target = "Hello World"
RAND_NUM = random.random()
def generateBasePopulation(population_size):
population = dict()
for _ in range(POP_SIZE):
gene = generateParent(len(target))
population[gene] = 0
return population
def generateNewPopulation(population, population_size):
newPopulation = dict()
while(len(newPopulation) <= POP_SIZE):
child_one, child_two = crossover(child_one, child_two)
child_one = mutate(child_one)
child_two = mutate(child_two)
newPopulation[child] = 0
newPopulation[child_two] = 0
return newPopulation
def assignFitness(population):
for x in population:
population[x] = getFitness(x)
def generateParent(length):
genes = list("")
for i in range(0,length):
random_gene = random.choice(GENESET)
genes.append(random_gene)
return(''.join(genes))
def getFitness(candidate):
fitness = 0
for i in range(0, len(candidate) - 1):
if target[i] == candidate[i]:
fitness += 1
return(fitness)
def mutate(parent):
gene_index_to_mutate = random.randint(0, len(parent) - 1)
mutation_value = random.choice(GENESET)
genes = list(parent)
genes[gene_index_to_mutate] = mutation_value
return(''.join(genes))
def crossover(parentA, parentB):
if(RAND_NUM < CROSSOVER_RATE):
random_index = random.randint(0, len(target))
parentASlice = parentA[:random_index]
parentBSlice = parentB[random_index:]
return (parentASlice + parentBSlice), (parentBSlice + parentASlice)
return parentA, parentB
def chooseChild(population):
fitnessSum = sum(population.values())
pick = random.uniform(0, fitnessSum)
current = 0
for pop in population:
current += population[pop]
if current >= pick:
return pop
def main():
population = generateBasePopulation(POP_SIZE)
targetNotFound = True
while(targetNotFound):
assignFitness(population)
if target in population:
print("target found!")
targetNotFound = False
if(targetNotFound):
tempPopulation = generateNewPopulation(population, POP_SIZE)
population.clear()
population = tempPopulation
generateNewPopulation
函数存在一些问题。
child_one
和child_two
您需要人口中的两个人来执行交叉。 有几种选择算法,但是为了给您一个思路,您可以从锦标赛选择的形式开始:
def extractFromPopulation(population):
best = random.choice(list(population.keys()))
for _ in range(4):
gene = random.choice(list(population.keys()))
if population[gene] > population[best]:
best = gene
return best
此处选择压力( range(4)
)是固定的。 在实际情况下,这是您必须调整的参数之一。
现在我们有:
def generateNewPopulation(population, population_size):
newPopulation = dict()
while len(newPopulation) <= POP_SIZE:
child_one = extractFromPopulation(population)
child_two = extractFromPopulation(population)
# ...
该代码仍然无法正常工作,因为
newPopulation
只需缩进两行:
newPopulation[child] = 0
newPopulation[child_two] = 0
(它们必须是while
循环的一部分)
修改后的generateNewPopulation
函数如下:
def generateNewPopulation(population, population_size):
newPopulation = dict()
while len(newPopulation) <= POP_SIZE:
child_one = extractFromPopulation(population)
child_two = extractFromPopulation(population)
child_one, child_two = crossover(child_one, child_two)
child_one = mutate(child_one)
child_two = mutate(child_two)
newPopulation[child_one] = 0
newPopulation[child_two] = 0
return newPopulation
crossover
功能不能基于固定的RAND_NUM
值 删除RAND_NUM = random.random()
分配,并更改crossover
函数以在每次调用时使用新的随机值:
def crossover(parentA, parentB):
if random.random() < CROSSOVER_RATE:
random_index = random.randint(0, len(target))
parentASlice = parentA[:random_index]
parentBSlice = parentB[random_index:]
return (parentASlice + parentBSlice), (parentBSlice + parentASlice)
return parentA, parentB
另外,由于未保留第二个父代的模式,因此代码无法正确执行单点交叉。
您可以更改许多细节以提高性能,但是,作为一个开始的示例,它可能就足够了(...有效)。
寻找解决方案的平均世代数约为158
( 200
次运行的平均值)。
编辑(感谢Alexis的评论 )
MUTATION_RATE
未使用,并且总是发生突变。 mutate
函数应类似于:
def mutate(parent):
if random.random() < MUTATION_RATE:
gene_index_to_mutate = random.randint(0, len(parent) - 1)
mutation_value = random.choice(GENESET)
genes = list(parent)
genes[gene_index_to_mutate] = mutation_value
return ''.join(genes)
return parent
如果您保留轮盘赌选择算法,则此修复程序特别重要(没有该修复程序, chooseChild
通常不会收敛)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.