Я пытаюсь проверить, присутствует ли конкретный объект класса, здесь называемый new_state
, как ключ в словаре.Однако, когда я запускаю команду if new_state not in dictionary:
, я получаю следующую ошибку:
ValueError: Значение истинности массива с более чем одним элементом является неоднозначным.Используйте a.any () или a.all ()
Более конкретно, я хочу сохранить набор уникальных объектов (называемых «состояниями») в качестве ключей в словаре (здесь инициализируется как self.Q = dict()
), и каждому ключу сохранить соответствующий список в качестве значения словаря.Состояния являются объектами class State:
, чьи атрибуты являются входными данными для матриц и определяются как:
class State:
"""Defines the current state of the agent."""
def __init__(self, grid):
self.grid = grid
def __eq__(self, other):
"""Override the default Equals behaviour."""
if isinstance(other, self.__class__):
return self.grid == other.grid
return False
def __ne__(self, other):
"""Override the default Unequal behaviour."""
return self.grid != other.grid
В какой-то момент в программе я хочу проверить, является ли объект new_state' is in the dictionary
собственным.Q , and if it isn't, then a list of random numbers is to be added to the dictionary with
new_state`as ключ:
new_state = State(cur_env)
if new_state not in self.Q:
self.Q[new_state] = np.random.rand(len(ACTIONS)) # Add list of random numbers
return new_state, a
И вот где происходит ошибка.Что тут происходит?Я не понимаю, что означает ошибка, и я не смог найти аналогичный пост, который охватывает это.Этот код является частью простой реализации задачи обучения подкреплению (я приведу полный код ниже).Предполагается, что агент перемещается из точки A в B на сетке с использованием алгоритма Q-обучения, который сохраняется в виде матрицы в текущем состоянии агента.Мой код свободно основан на коде, найденном в этой статье https://medium.com/@curiousily/solving-an-mdp-with-q-learning-from-scratch-deep-reinforcement-learning-for-hackers-part-1-45d1d360c120,, однако, похоже, что они не сталкиваются с этой проблемой, и я не вижу, в чем будет разница.
# Reinforcement learning
import numpy as np
import random as rnd
from copy import deepcopy
grid_size = 4
m_A = 0 # Start coordinate in matrix
n_A = 0 # Start coordinate in matrix
m_B = grid_size - 1 # End coordinate
n_B = grid_size - 1 # End coordinate
ACTIONS = ['Right', 'Left', 'Up', 'Down']
eps = 0.1
gamma = 0.7
alpha = 1
class State:
"""Defines the current state of the agent."""
def __init__(self, grid):
self.grid = grid
def __eq__(self, other):
"""Override the default Equals behaviour."""
if isinstance(other, self.__class__):
return self.grid == other.grid
return False
def __ne__(self, other):
"""Override the default Unequal behaviour."""
return self.grid != other.grid
def __hash__(self):
return hash(str(self.grid))
terminal_grid = np.zeros((grid_size, grid_size), dtype = int)
terminal_grid[m_B][n_B]
terminal_state = State(terminal_grid)
class Robot:
"""Implements agent. """
def __init__(self, row = m_A, col = n_A, cargo = False):
self.m = row # Robot position in grid (row)
self.n = col # Robot position in grid (col)
self.carry = cargo # True if robot carries cargo, False if not
self.Q = dict()
self.Q[terminal_state] = [0, 0, 0, 0]
def move_robot(self, state):
"""Moves the robot according to the given action."""
m = self.m # Current row
n = self.n # Current col
p = [] # Probability distribution
for i in range(len(ACTIONS)):
p.append(eps/4)
if self.carry is False: # If the robot is moving from A to B
Qmax = max(self.Q[state])
for i in range(len(p)):
if self.Q[state][i] == Qmax:
p[i] = 1 - eps + eps/4
break # Use if number of episodes is large
cur_env = deepcopy(state.grid)
# cur_env = state.grid
cur_env[m][n] = 0
action = choose_action(p)
if action == 'Right':
if n + 1 >= grid_size or cur_env[m][n+1] == 1:
Rew = -5 # Reward -5 if we move into wall or another agent
else:
n += 1
Rew = -1 # Reward -1 otherwise
a = 0 # Action number
elif action == 'Left':
if n - 1 < 0 or cur_env[m][n-1] == 1:
Rew = -5
else:
n -= 1
Rew = -1
a = 1
elif action == 'Up':
if m - 1 < 0 or cur_env[m-1][n] == 1:
Rew = -5
else:
m -= 1
Rew = -1
a = 2
elif action == 'Down':
if m + 1 >= grid_size or cur_env[m+1][n] == 1:
Rew = -5
else:
m += 1
Rew = -1
a = 3
m = m % grid_size
n = n % grid_size
self.m = m
self.n = n
cur_env[m][n] = 1
# print(cur_env)
new_state = State(cur_env)
if new_state not in self.Q:
self.Q[new_state] = np.random.rand(len(ACTIONS)) # Add list of random numbers
return new_state, a
def choose_action(prob): # Given a probability distribution, chooses an action!
"""Defines policy to follow."""
action = np.random.choice(ACTIONS, p = prob) # Chooses an action at random
return action
def episode(robot):
"""Simulation of one episode."""
# Initialize E, S
E = np.zeros((grid_size, grid_size), dtype = int) # Initializes the environment, E
E[m_A][n_A] = 1 # Initializes position of robot
S = State(E) # Initializes state of robot
robot.Q[S] = np.random.rand(len(ACTIONS))
# print(S.grid)
# print(robot.Q[S])
count = 0
while robot.carry is False:
print('Carry == False')
S_new, action_number = robot.move_robot(S)
print('New state: ', S_new.grid)
m_new = robot.m
n_new = robot.n
if m_new != m_B or n_new != n_B:
R = -1
else:
R = 5
robot.carry = True # Picks up cargo
robot.Q[S][action_number] += alpha*(R + gamma*max(robot.Q[S_new]) - robot.Q[S][action_number])
S = S_new
# print(E)
# print()
count += 1
return count
nepisodes = []
step_list = []
def simulation():
"""Iterates through all episodes."""
r1 = Robot()
for i in range(400):
nsteps = episode(r1)
nepisodes.append(i+1)
step_list.append(nsteps)
r1.m = m_A
r1.n = n_A
print("End of episode!")
print(nsteps)
simulation()
plt.plot(nepisodes, step_list, '.')
plt.show()
Любая помощь будет принята с благодарностью!Заранее спасибо.