Примечание: весь исходный код можно найти в этом хранилище
Итак, я строю довольно сложный нейроэволюционный проект, в котором я использую естественный отбор для определения следующего поколения.
На высоком уровне, вот что ДОЛЖЕН сделать мой алгоритм естественного отбора ...
Шаги:
- Выберите сеть с наивысшей оценкой и клонируйте ее, немедленно включите в следующее поколение И НЕ ПРИКАСАЙТЕСЬ К ЭТОМУ ... (ЭТО ЧАСТЬ, КОТОРАЯ БРОЛА)
- Снова выберите сеть с наивысшей оценкой, клонируйте ее, но также измените ее.
- Что касается остальной части населения, возьмите 2 родителей и скрестите их, чтобы создать 2 детей и добавить детей в новый список населения.
Настройка сети
Нейронные сети обрабатываются в моем 'NeuralNetwork' классе, который дополняет 'EvolutionaryNeuralNetwork' , который добавляет такие вещи, как клон , мутировать , кроссовер и т. д.
Сетевые слои хранятся в 'layer_weights' .
layer_weights
= список ванильных Python NumPy ndarrays.
layer_weights[i]
= матрица, содержащая все слои i's
нейроны / веса.
layer_weights[i][j][k]
= вес на слое i
, нейрон j
, вес k
.
Метод клонирования: (найдено ЗДЕСЬ )
def clone(self):
copied_weights = []
for layer in self.layer_weights:
copied_weights.append(np.copy(layer))
out = EvoNeuralNetwork(
layer_weights=copied_weights
)
return out
Метод естественного отбора в тестовой среде (найдено ЗДЕСЬ )
def natural_selection(self):
"""Uses natural selection to alter the current Neural Network population."""
print('Selecting new generation...')
new_best = self.best().clone()
new_genomes = [
new_best,
new_best.clone().mutate()
]
for i in range(round(len(self.genomes) / 2 - 1)):
parentA = self.pick_random()
parentB = self.pick_random()
children = parentA.crossover(parentB)
[child.mutate() for child in children]
new_genomes.extend(children)
self.genomes = new_genomes
Ожидаемый результат:
Я ожидаю, что в моей тестовой среде лучший геном будет сохранен и скопирован в следующее поколение UNTOUCHED.
Фактический результат:
Кажется, что геном, который делает все возможное, либо уничтожается, либо действует совершенно иначе при тех же точных входных данных.
Фактические примеры:
Первая часть, моя мышь следует за наиболее подходящим геномом, однако следующее поколение, похоже, исчезло, несмотря на ТОЧНЫЕ входные данные.