35 lines
1.1 KiB
Python
35 lines
1.1 KiB
Python
import random
|
|
import copy
|
|
import torch
|
|
|
|
|
|
def mutate(model, mutation_rate=0.01):
|
|
new_model = copy.deepcopy(model)
|
|
for param in new_model.parameters():
|
|
if random.random() < mutation_rate:
|
|
noise = torch.randn_like(param) * 0.1
|
|
param.data += noise
|
|
return new_model
|
|
|
|
|
|
def crossover(parent1, parent2):
|
|
child = copy.deepcopy(parent1)
|
|
for p_child, p2 in zip(child.parameters(), parent2.parameters()):
|
|
mask = torch.rand_like(p_child) < 0.5
|
|
p_child.data[mask] = p2.data[mask]
|
|
return child
|
|
|
|
|
|
def evolve(population, fitnesses, retain_ratio=0.2, mutation_rate=0.1):
|
|
# rank by fitness (higher is better)
|
|
paired = sorted(zip(fitnesses, population), key=lambda x: x[0], reverse=True)
|
|
retain_len = int(len(paired) * retain_ratio)
|
|
parents = [ind for _, ind in paired[:retain_len]]
|
|
next_gen = parents.copy()
|
|
while len(next_gen) < len(population):
|
|
p1, p2 = random.sample(parents, 2)
|
|
child = crossover(p1, p2)
|
|
child = mutate(child, mutation_rate)
|
|
next_gen.append(child)
|
|
return next_gen
|