Как исправить 'ValueError: Истинное значение массива с более чем одним элементом неоднозначно.'при сравнении объектов в словаре? - PullRequest
0 голосов
/ 12 февраля 2019

Я пытаюсь проверить, присутствует ли конкретный объект класса, здесь называемый 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()

Любая помощь будет принята с благодарностью!Заранее спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...