我当前正在尝试制作一种遗传算法,以将浮点号列表匹配到另一个浮点数列表(我知道这是"毫无意义"的,因为我已经有了数据,但我只想在尝试解决更复杂的遗传算法问题之前能够做到这一点)。我有以下用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...
如果使用numpy,所有计算都更容易,并且应该尝试变得更加柔软:
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])
这可能会导致不良结果:
-
您的突变率太高了。每个基因的40%意味着每个个体有10个基因的平均4个变化。实际上,您应该选择突变率,以便每一代人在整个人群中仅引入少数突变。
-
您的
cross
功能交换了所选父母之间的基因,而不是让父母不变,并将父母双方的基因的分数复制到一个新创造的孩子。 -
如果您突变基因,则由新的独立随机变量代替。这是无效的,因为它使算法在其上运行的景观非常粗糙。如果您仅在原始值中添加小的随机变量,例如在[-0.1,0.1]。
-
而不是选择基因组的跨点,而是在父母之间完全随机选择基因会更有效,因为基因的顺序在您的模型中没有意义。
-
您的等待时间不够长,10代不会带您远。
-
据我所知,您无法正确衡量健身的增益。您应该打印出人口的平均健身(也许是TOP10的最佳健身或平均水平)。
只是遗传算法很有趣...:)
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)
请记住,这对于遗传算法是一个糟糕的问题,而且还有很多改进的空间(即一起摆脱精英主义)