我目前正在尝试制作遗传算法,将浮点数列表与另一个浮点数列表相匹配(我知道这有点“毫无意义”因为我已有数据,但我只想拥有在尝试解决更复杂的遗传算法问题之前能够做到这一点)。我有以下用Python编写的代码。
from random import random
ofInterest = [
5.76260089714,
7.87666520017,
9.53163269149,
9.72801578613,
5.20002737716,
0.50133290228,
8.58820041647,
9.65056792475,
3.07043110493,
1.13232332178
]
print(ofInterest)
fits = []
for i in range(100):
fits.append([])
for j in range(10):
fits[i].append(random()*10)
fitness = []
for i in range(100):
fitness.append(100000000)
def makeFitnessList():
for i in range(100):
fitValue = 0
for j in range(10):
fitValue += (fits[i][j] - ofInterest[j])**2
fitness[i] = fitValue
topTenFitness = []
for i in range(10):
topTenFitness.append(10000000000000)
print(topTenFitness)
def sortByFitness():
makeFitnessList()
temp = []
count = 0
while len(temp) < 10:
k = 100000000000000000000000000
index = -1
for i in range(len(fitness)):
if k > fitness[i]:
k = fitness[i]
index = i
temp += [index]
topTenFitness[count] = fitness[index]
print(fitness[index])
fitness[index] = 1000000000000
count += 1
temp2 = fits
for i in range(10):
fits[i] = temp2[temp[i]]
#sortByFitness()
#print(fitness[0])
#print(fits[0])
def cross(rate):
for i in range(10,100):
parent1Place = int(random()*10.01)
if (i*random()) > rate:
parent2Place = int(random()*10.01)
crossPoint = int(random()*10.01)
for i in range(crossPoint):
tempOne = fits[parent1Place][i]
tempTwo = fits[parent2Place][i]
fits[parent1Place][i] = tempOne
fits[parent2Place][i] = tempTwo
else:
fits[i] = fits[parent1Place]
def mutate(rate):
for i in range(10,100):
for gene in range(10):
if random() < rate:
fits[i][gene] = random()*10
for i in range(10):
makeFitnessList()
sortByFitness()
print("")
cross(.6)
mutate(.4)
sortByFitness()
print(fits[0])
这个程序运行,但健身没有收获:
158.551483202
89.0049309654
150.062479048
223.447907282
162.41893599
105.727706028
169.756843723
77.0767420744
122.905567656
144.328292984
113.405444904
132.748651766
144.739705127
155.959141194
151.507885923
86.3246751862
etc...
答案 0 :(得分:1)
如果你使用numpy所有的计算都比较容易,你应该尝试更加pythonic:
import numpy as np
ofInterest = np.array([
5.76260089714,
7.87666520017,
9.53163269149,
9.72801578613,
5.20002737716,
0.50133290228,
8.58820041647,
9.65056792475,
3.07043110493,
1.13232332178
])
print(ofInterest)
fits = np.random.random((100,10)) * 10
def sortByFitness():
global fits
fitness = np.sum((fits - ofInterest)**2,axis=1)
fits = fits[fitness.argsort()]
def cross(rate):
for i in range(10,100):
parents = fits[np.random.random_integers(0,9,2)]
if (i*np.random.random()) > rate:
crossPoint = np.random.random_integers(0,10)
fits[i] = np.hstack((parents[0,:crossPoint],parents[1,crossPoint:]))
else:
fits[i] = parents[0]
def mutate(rate):
for i in range(10,100):
for gene in range(10):
if np.random.random() < rate:
fits[i][gene] = np.random.random()*10
for i in range(100):
sortByFitness()
cross(.6)
mutate(.4)
print(fits[0])
答案 1 :(得分:1)
以下是可能导致不良结果的一些事情:
你的突变率太高了。每个基因40%意味着每个个体有10个基因平均有4个变化。实际上你应该选择突变率,这样每一代人群中只有少数突变被引入。
您的cross
功能在所选父母之间交换基因,而不是让父母保持不变,并将父母双方基因的一部分复制到新创建的孩子身上。
如果你改变一个基因,你可以用一个新的独立随机变量替换它。这是无效的,因为它使算法运行的景观非常粗糙。如果只将小随机变量添加到原始值,例如在[-0.1,0.1]范围内,您将获得更平滑的景观和更好的拟合。
不是选择基因组的交叉点,而是在父母之间完全随机选择基因更有效,因为基因的顺序在你的模型中没有意义。
你没有等待足够长的时间,10代不会带你走远。
据我所知,你没有正确测量健身增益。你应该打印出人口的平均适应度(可能是最好的适应度或前10名的平均值)。
答案 2 :(得分:0)
只是因为遗传算法很有趣...... :)
import random
target_list = [1,2,3,4,5,6,7,8,9,10]
size_of_individual = len(target_list)
size_of_population = 100
n_generations = 10000
def score_fitness(individual):
return sum((val-target)**2 for val,target in zip(individual,target_list))
def create_individual():
return [random.random()*10 for _ in range(size_of_individual)]
def crossover(individual1,individual2):
return [val1 if random.random() < 0.5 else val2 for val1,val2 in zip(individual1,individual2)]
def mutate(individual,mutation_chance=0.1,mutation_size = 0.1):
def get_mutation(val):
return val if random.random()>mutation_chance else val + [-mutation_size,mutation_size][random.random()<0.5]
return [get_mutation(val) for val in individual]
def selection_step(sorted_old_population):
def select_one():
while True:
candidate_idx = random.randint(0,len(sorted_old_population)-1)
if random.randint(0,len(sorted_old_population))>= candidate_idx:
return sorted_old_population[candidate_idx]
selections = [select_one(),select_one()]
while selections[1] == selections[0]:
selections[1] = select_one()
return selections
def create_new_population(old_population,elitism=0):
sorted_population = sorted(old_population,key= score_fitness)
print "BEST OLD:",sorted_population[0],score_fitness(sorted_population[0])
print "AVG OLD:", sum(score_fitness(i) for i in sorted_population)
new_population = sorted_population[:elitism]
while len(new_population) < size_of_population:
new_population.append(mutate(crossover(*selection_step(sorted_population))))
return new_population[:size_of_population]
population = [create_individual() for _ in range(size_of_population)]
for i in range(n_generations):
population = create_new_population(population,5)
请记住,这对遗传算法来说是一个很糟糕的问题,而且还有很多很大的改进空间(IE完全消除了精英主义)