遗传算法IndexError:列表索引超出范围



我得到这个索引的一个超出范围的错误。我理解错误的意思,我调用的值不在索引中。但我不明白它为什么这么说。我已经添加了代码以及末尾有问题的部分。

from game import *
import math as math
import random as rand
class RandomPlayer:
def __init__(self, i):
self.i = i
def get_move(self, board, snake):
r = rand.randint(0,3)
return MOVES[r]
class GeneticPlayer:
def __init__(self, pop_size, num_generations, num_trails, window_size, hidden_size, board_size, mutation_chance=0.1, mutation_size=0.1):
self.pop_size = pop_size
self.num_generations = num_generations
self.num_trails = num_trails
self.window_size = window_size
self.hidden_size = hidden_size
self.board_size = board_size
self.mutation_chance = mutation_chance
self.mutation_size = mutation_size
self.display = False
self.current_brain = None
self.pop = [self.generate_brain(self.window_size**2, self.hidden_size, len(MOVES)) for _ in range(self.pop_size)]
def generate_brain(self, input_size, hidden_size, output_size):
hidden_layer1 = np.array([[rand.uniform(-1, 1) for _ in range(input_size + 1)] for _ in range(hidden_size)])
hidden_layer2 = np.array([[rand.uniform(-1, 1) for _ in range(hidden_size + 1)] for _ in range(hidden_size)])
output_layer = np.array([[rand.uniform(-1, 1) for _ in range(hidden_size + 1)] for _ in range(output_size)])
return[hidden_layer1, hidden_layer2, output_layer]
def get_move(self, board, snake):
input_vector = self.proccess_board(board, snake[-1][0], snake[-1][1], snake[-2][0], snake[-2][1])
hidden_layer1 = self.current_brain[0]
hidden_layer2 = self.current_brain[1]
output_layer = self.current_brain[2]
hidden_result1 = np.array([math.tanh(np.dot(input_vector, hidden_layer1[i])) for i in range(hidden_layer1.shape[0])] + [1])
hidden_result2 = np.array([math.tanh(np.dot(hidden_result1, hidden_layer2[i])) for i in range(hidden_layer2.shape[0])] + [1])
output_result = np.array([np.dot(hidden_result2, output_layer[i]) for i in range(output_layer.shape[0])])
max_index = np.argmax(output_result)
return MOVES[max_index]
def proccess_board(self, board, x1, y1, x2, y2):
input_vector = [[0 for _ in range(self.window_size)] for _ in range(self.window_size)]
for i in range(self.window_size):
for j in range(self.window_size):
ii = x1 + i - self.window_size//2
jj = y1 + j - self.window_size//2
if ii < 0 or jj < 0 or ii >= self.board_size or jj >= self.board_size:
input_vector[i][j] = -1
elif board[ii][jj] == FOOD:
input_vector[i][j] = 1
elif board[ii][jj] == EMPTY:
input_vector[i][j] = 0
else:
input_vector[i][j] = -1
if self.display:
print(np.array(input_vector))
input_vector = list(np.array(input_vector).flatten()) + [1]
return np.array(input_vector)
def reproduce(self, top_25):
new_pop = []
for brain in top_25:
new_pop.append(brain)
for brain in top_25:
new_brain = self.mutate(brain)
new_pop.append(new_brain)
for _ in range(self.pop_size//2):
new_pop.append(self.generate_brain(self.window_size**2, self.hidden_size, len(MOVES)))
return new_pop
def mutate(self, brain):
new_brain = []
for layer in brain:
new_layer = np.copy(layer)
for i in range(new_layer.shape[0]):
for j in range(new_layer.shape[1]):
if rand.uniform(0,1) < self.mutation_chance:
new_layer[i][j] += rand.uniform(-1,1)*self.mutation_size
new_brain.append(new_layer)
return new_brain
def one_generation(self):
scores = [0 for _ in range(self.pop_size)]
max_score = 0
for i in range(self.pop_size):
for j in range(self.num_trails):
self.current_brain = self.pop[i]
game = Game(self.board_size, 1, [self])
outcome = game.play(False, termination=True)
score = len(game.snakes[0])
scores[i] += score
if outcome == 0:
print("Snake", i, "made it to the last turn")
if score > max_score:
max_score = score
print(max_score, "at ID", i)
top_25_indexes = list(np.argsort(scores))[3*(self.pop_size//4):self.pop_size]
print(scores)
top_25 = [self.pop[i] for i in top_25_indexes][::-1]
self.pop = self.reproduce(top_25)
def evolve_pop(self):
for i in range(self.num_generations):
self.one_generation()
print("gen", i)
key = input("enter any character to display boards")
for brain in self.pop:
self.display = True
self.current_brain = brain
game = Game(self.board_size, 1, [self], display=True)
gui = Gui(game, 800)
game.play(True, termination=True)
print("Snake length", len(game.snakes[0]))

当前的大脑指数是给我错误的指数

def get_move(self, board, snake):
input_vector = self.proccess_board(board, snake[-1][0], snake[-1][1], snake[-2][0], snake[-2][1])
hidden_layer1 = self.current_brain[0]
hidden_layer2 = self.current_brain[1]
output_layer = self.current_brain[2]
hidden_result1 = np.array([math.tanh(np.dot(input_vector, hidden_layer1[i])) for i in range(hidden_layer1.shape[0])] + [1])
hidden_result2 = np.array([math.tanh(np.dot(hidden_result1, hidden_layer2[i])) for i in range(hidden_layer2.shape[0])] + [1])
output_result = np.array([np.dot(hidden_result2, output_layer[i]) for i in range(output_layer.shape[0])])
max_index = np.argmax(output_result)
return MOVES[max_index]

这是堆栈跟踪

Traceback (most recent call last):
File "C:UserssamueDocumentssnakemain.py", line 19, in <module>
gen_player.evolve_pop()
File "C:UserssamueDocumentssnakeplayers.py", line 122, in evolve_pop
self.one_generation()
File "C:UserssamueDocumentssnakeplayers.py", line 103, in one_generation
outcome = game.play(False, termination=True)
File "C:UserssamueDocumentssnakegame.py", line 106, in play
moves = self.move()
File "C:UserssamueDocumentssnakegame.py", line 51, in move
move_i = self.players[i].get_move(self.board, snake_i)
File "C:UserssamueDocumentssnakeplayers.py", line 42, in get_move
hidden_layer2 = self.current_brain[1]

问题是第二代人口的成员没有正确形成。发生这种情况是因为mutate函数中存在错误。目前;大脑;只有一个list元素,因为for循环提前退出。这是由return new_brain线的放置引起的。更改最后一行的缩进应该可以修复它。

def mutate(self, brain):
new_brain = []
for layer in brain:
new_layer = np.copy(layer)
for i in range(new_layer.shape[0]):
for j in range(new_layer.shape[1]):
if rand.uniform(0, 1) < self.mutation_chance:
new_layer[i][j] += rand.uniform(-1, 1) * self.mutation_size
new_brain.append(new_layer)
return new_brain  # <---- DEDENT THIS LINE

此外,有两件事可能有助于防止未来出现这样的错误:

  1. 当函数开始变得过于嵌套时,将其分解为更小的部分
  2. 使用列表理解并使用内置的库函数,这样它就不会嵌套太多

在这种情况下,我可能会将逻辑重写到mutate_brainmutate_layer函数中,如下所示:

import itertools

def mutate_layer(self, layer):
# start with a non-mutated copy
new_layer = np.copy(layer)
# iterate through each cell of the layer
rows = new_layer.shape[0]
cols = new_layer.shape[1]
for i, j in itertools.product(range(rows), range(cols)):
# the cell has an independent random chance of mutating
if rand.uniform(0, 1) < self.mutation_chance:
new_layer[i][j] += rand.uniform(-1, 1) * self.mutation_size
return new_layer

def mutate_brain(self, brain):
return [mutate_layer(layer) for layer in brain]

最新更新