示例#1
0
class Learner:
    def __init__(self, n_rays):
        self.evaluate_mode = False
        # here +2 is for 2 inputs from elements of Action that we are trying to predict
        self.neural_net = Network(
            [
                n_rays + 4,
                # внутренние слои сети: выберите, сколько и в каком соотношении вам нужно
                # например, (self.rays + 4) * 2 или просто число
                n_rays + 4,
                (n_rays + 4) // 2,
                1
            ],
            output_function=lambda x: x,
            output_derivative=lambda x: 1)
        self.ALPHA = 0.1
        self.GAMMA = 0.8

        self.reset_history()

    def reset_history(self):
        self.history = deque([], maxlen=50000)

        self.step = 0

        self.last_reward = 0
        self.last_qvalue = 0

    def start_episode(self):
        self.reset_history()

    def update_qvalue(self, state, action, reward, agent, next_agent_state):
        old_qvalue = self.predict_reward(state, action)
        item = HistoryItem(state, action, old_qvalue, reward)
        self.history.append(item)
        self.last_reward = reward

    def update_final_qvalue(self, state, action, reward):
        item = HistoryItem(state, action, reward, reward)
        self.history.append(item)
        self.last_reward = reward

    def backtrack_qvalues(self, history, callback):
        qvalue = None
        for item in (list(history))[::-1]:
            if qvalue is None:
                qvalue = item.reward
                print("qvalue in final state:", qvalue)
            else:
                qvalue = self.calculate_new_qvalue(item.qvalue, item.reward,
                                                   qvalue)
            callback(item, qvalue)

    def calculate_new_qvalue(self, old_qvalue, reward, estimate_of_optimal):
        new_qvalue = (1 - self.ALPHA) * old_qvalue + self.ALPHA * (
            reward + self.GAMMA * estimate_of_optimal)
        print(
            "Q value update. New: %.4f, old: %.4f, reward: %.4f, estimate: %.4f"
            % (new_qvalue, old_qvalue, reward, estimate_of_optimal))
        return new_qvalue

    def learn(self):
        def tuple_to_ndvector(x):
            v = np.asarray(x)
            v = v.flatten()[:, np.newaxis]
            return v

        training_data = []

        def on_training_item(item, qvalue):
            x = tuple_to_ndvector(
                self.state_and_action_to_neunet_vector(item.state,
                                                       item.action))
            training_data.append((x, qvalue))

        self.backtrack_qvalues(self.history, on_training_item)
        self.neural_net.SGD(training_data=training_data,
                            epochs=15,
                            mini_batch_size=50,
                            eta=0.05)

    def receive_feedback(self, reward, train_every=50, reward_depth=7):
        """
        Получить реакцию на последнее решение, принятое сетью, и проанализировать его
        :param reward: оценка внешним миром наших действий
        :param train_every: сколько нужно собрать наблюдений, прежде чем запустить обучение на несколько эпох
        :param reward_depth: на какую глубину по времени распространяется полученная награда
        """
        # считаем время жизни сети; помогает отмерять интервалы обучения
        self.step += 1

        # начиная с полной полученной истинной награды,
        # размажем её по предыдущим наблюдениям
        # чем дальше каждый раз домножая её на 1/2
        # (если мы врезались в стену - разумно наказывать не только последнее
        # действие, но и предшествующие)
        i = -1
        while len(self.reward_history) > abs(i) and abs(i) < reward_depth:
            self.reward_history[i] += reward
            reward *= 0.5
            i -= 1

        # Если у нас накопилось хоть чуть-чуть данных, давайте потренируем нейросеть
        # прежде чем собирать новые данные
        # (проверьте, что вы в принципе храните достаточно данных (параметр `history_data` в `__init__`),
        # чтобы условие len(self.reward_history) >= train_every выполнялось
        if not self.evaluate_mode and (len(self.reward_history) >= train_every
                                       ) and not (self.step % train_every):
            X_train = np.concatenate(
                [self.sensor_data_history, self.chosen_actions_history],
                axis=1)
            y_train = self.reward_history
            train_data = [(x[:, np.newaxis], y)
                          for x, y in zip(X_train, y_train)]
            self.neural_net.SGD(training_data=train_data,
                                epochs=15,
                                mini_batch_size=train_every,
                                eta=0.05)

    def predict_reward(self, state, action):
        agent_vector_representation = self.state_and_action_to_neunet_vector(
            state, action)
        return float(self.neural_net.feedforward(agent_vector_representation))

    # Vector is horizontal
    def state_and_action_to_vector(self, state, action):
        agent_vector_representation = np.append(state, action)
        # It would make the vector vertical
        #agent_vector_representation = agent_vector_representation.flatten()[:, np.newaxis]
        return tuple(agent_vector_representation)

    def state_and_action_to_neunet_vector(self, state, action):
        agent_vector_representation = np.append(state, action)
        agent_vector_representation = agent_vector_representation.flatten(
        )[:, np.newaxis]
        return agent_vector_representation
示例#2
0
class SimpleCarAgent(Agent):
    def __init__(self, history_data=int(500000)):
        """
        Создаёт машинку
        :param history_data: количество хранимых нами данных о результатах предыдущих шагов
        """
        self.evaluate_mode = False  # этот агент учится или экзаменутеся? если учится, то False
        self._rays = 5  # выберите число лучей ладара; например, 5
        # here +2 is for 2 inputs from elements of Action that we are trying to predict
        self.neural_net = Network(
            [
                self.rays + 4,
                100,  # внутренние слои сети: выберите, сколько и в каком соотношении вам нужно
                10,  # например, (self.rays + 4) * 2 или просто число
                1
            ],
            output_function=lambda x: x,
            output_derivative=lambda x: 1)
        self.sensor_data_history = deque([], maxlen=history_data)
        self.chosen_actions_history = deque([], maxlen=history_data)
        self.reward_history = deque([], maxlen=history_data)
        self.step = 0
        self.avg_reward = 0.  # средняя награда за последнюю тысячу шагов
        self.sum_reward = 0.  # сумма всех наград

    @classmethod
    def from_weights(cls, layers, weights, biases):
        """
        Создание агента по параметрам его нейронной сети. Разбираться не обязательно.
        """
        agent = SimpleCarAgent()
        agent._rays = weights[0].shape[1] - 4
        nn = Network(layers,
                     output_function=lambda x: x,
                     output_derivative=lambda x: 1)

        if len(weights) != len(nn.weights):
            raise AssertionError(
                "You provided %d weight matrices instead of %d" %
                (len(weights), len(nn.weights)))
        for i, (w, right_w) in enumerate(zip(weights, nn.weights)):
            if w.shape != right_w.shape:
                raise AssertionError("weights[%d].shape = %s instead of %s" %
                                     (i, w.shape, right_w.shape))
        nn.weights = weights

        if len(biases) != len(nn.biases):
            raise AssertionError("You provided %d bias vectors instead of %d" %
                                 (len(weights), len(nn.weights)))
        for i, (b, right_b) in enumerate(zip(biases, nn.biases)):
            if b.shape != right_b.shape:
                raise AssertionError("biases[%d].shape = %s instead of %s" %
                                     (i, b.shape, right_b.shape))
        nn.biases = biases

        agent.neural_net = nn

        return agent

    @classmethod
    def from_string(cls, s):
        from numpy import array  # это важный импорт, без него не пройдёт нормально eval
        layers, weights, biases = eval(s.replace("\n", ""), locals())
        return cls.from_weights(layers, weights, biases)

    @classmethod
    def from_file(cls, filename):
        c = open(filename, "r").read()
        return cls.from_string(c)

    def show_weights(self):
        params = self.neural_net.sizes, self.neural_net.weights, self.neural_net.biases
        #np.set_printoptions(threshold=np.nan)
        np.set_printoptions(threshold=1e9)
        return repr(params)

    def to_file(self, filename):
        c = self.show_weights()
        f = open(filename, "w")
        f.write(c)
        f.close()

    @property
    def rays(self):
        return self._rays

    def choose_action(self, sensor_info):
        # хотим предсказать награду за все действия, доступные из текущего состояния
        rewards_to_controls_map = {}
        # дискретизируем множество значений, так как все возможные мы точно предсказать не сможем
        all_actions = ((0., 0.), (0., .75), (0., -.75), (1., .75), (-1., .75))
        probabilities = np.zeros(5)
        s = 0.  # sum for softmax
        ind = 0
        for steering, acceleration in all_actions:
            action = Action(steering, acceleration)
            agent_vector_representation = np.append(sensor_info, action)
            agent_vector_representation = agent_vector_representation.flatten(
            )[:, np.newaxis]
            predicted_reward = float(
                self.neural_net.feedforward(agent_vector_representation))
            probabilities[ind] = np.exp(predicted_reward)
            s += probabilities[ind]
            ind += 1
        probabilities /= s
        ind = np.random.choice(5, size=1, p=probabilities)[0]
        steering, acceleration = all_actions[ind]
        best_action = Action(steering, acceleration)
        # запомним всё, что только можно: мы хотим учиться на своих ошибках
        self.sensor_data_history.append(sensor_info)
        self.chosen_actions_history.append(best_action)
        self.reward_history.append(
            0.0)  # мы пока не знаем, какая будет награда, это
        # откроется при вызове метода receive_feedback внешним миром

        return best_action

    def receive_feedback(self, reward, train_every=100, reward_depth=10):
        """
        Получить реакцию на последнее решение, принятое сетью, и проанализировать его
        :param reward: оценка внешним миром наших действий
        :param train_every: сколько нужно собрать наблюдений, прежде чем запустить обучение на несколько эпох
        :param reward_depth: на какую глубину по времени распространяется полученная награда
        """
        # считаем время жизни сети; помогает отмерять интервалы обучения
        self.step += 1
        q = .001 if self.step > 1000 else 1. / float(self.step)
        self.avg_reward = (1. - q) * self.avg_reward + q * reward
        self.sum_reward += reward

        # начиная с полной полученной истинной награды,
        # размажем её по предыдущим наблюдениям
        # чем дальше каждый раз домножая её на 1/2
        # (если мы врезались в стену - разумно наказывать не только последнее
        # действие, но и предшествующие)
        i = -1
        while len(self.reward_history) > abs(i) and abs(i) < reward_depth:
            self.reward_history[i] += reward
            reward *= 0.9
            i -= 1

        # Если у нас накопилось хоть чуть-чуть данных, давайте потренируем нейросеть
        # прежде чем собирать новые данные
        # (проверьте, что вы в принципе храните достаточно данных (параметр `history_data` в `__init__`),
        # чтобы условие len(self.reward_history) >= train_every выполнялось
        if not self.evaluate_mode and (len(self.reward_history) >= train_every
                                       ) and not (self.step % train_every):
            X_train = np.concatenate(
                [self.sensor_data_history, self.chosen_actions_history],
                axis=1)[-10 * train_every:]
            y_train = np.array(self.reward_history)[-10 * train_every:]
            train_data = [(x[:, np.newaxis], y)
                          for x, y in zip(X_train, y_train)]
            self.neural_net.SGD(training_data=train_data,
                                epochs=15,
                                mini_batch_size=train_every,
                                eta=0.05)
示例#3
0
文件: agent.py 项目: Bibazavr/car
class SimpleCarAgent(Agent):
    def __init__(self, history_data=int(50000)):
        """
        Создаёт машинку
        :param history_data: количество хранимых нами данных о результатах предыдущих шагов
        """
        self.evaluate_mode = False  # этот агент учится или экзаменутеся? если учится, то False
        self._rays = 7  # выберите число лучей ладара; например, 5
        # here +2 is for 2 inputs from elements of Action that we are trying to predict
        self.neural_net = Network(
            [
                self.rays + 4,
                6,
                # внутренние слои сети: выберите, сколько и в каком соотношении вам нужно
                # например, (self.rays + 4) * 2 или просто число
                1
            ],
            output_function=lambda x: x,
            output_derivative=lambda x: 1)
        self.sensor_data_history = deque([], maxlen=history_data)
        self.chosen_actions_history = deque([], maxlen=history_data)
        self.reward_history = deque([], maxlen=history_data)
        self.step = 0

    @classmethod
    def from_weights(cls, layers, weights, biases):
        """
        Создание агента по параметрам его нейронной сети. Разбираться не обязательно.
        """
        agent = SimpleCarAgent()
        agent._rays = weights[0].shape[1] - 4
        nn = Network(layers,
                     output_function=lambda x: x,
                     output_derivative=lambda x: 1)

        if len(weights) != len(nn.weights):
            raise AssertionError(
                "You provided %d weight matrices instead of %d" %
                (len(weights), len(nn.weights)))
        for i, (w, right_w) in enumerate(zip(weights, nn.weights)):
            if w.shape != right_w.shape:
                raise AssertionError("weights[%d].shape = %s instead of %s" %
                                     (i, w.shape, right_w.shape))
        nn.weights = weights

        if len(biases) != len(nn.biases):
            raise AssertionError("You provided %d bias vectors instead of %d" %
                                 (len(weights), len(nn.weights)))
        for i, (b, right_b) in enumerate(zip(biases, nn.biases)):
            if b.shape != right_b.shape:
                raise AssertionError("biases[%d].shape = %s instead of %s" %
                                     (i, b.shape, right_b.shape))
        nn.biases = biases

        agent.neural_net = nn

        return agent

    @classmethod
    def from_string(cls, s):
        from numpy import array  # это важный импорт, без него не пройдёт нормально eval
        layers, weights, biases = eval(s.replace("\n", ""), locals())
        return cls.from_weights(layers, weights, biases)

    @classmethod
    def from_file(cls, filename):
        c = open(filename, "r").read()
        return cls.from_string(c)

    def show_weights(self):
        params = self.neural_net.sizes, self.neural_net.weights, self.neural_net.biases
        np.set_printoptions(threshold=None)
        return repr(params)

    def to_file(self, filename):
        c = self.show_weights()
        f = open(filename, "w")
        f.write(c)
        f.close()

    @property
    def rays(self):
        return self._rays

    def choose_action(self, sensor_info):
        # хотим предсказать награду за все действия, доступные из текущего состояния
        rewards_to_controls_map = {}
        # дискретизируем множество значений, так как все возможные мы точно предсказать не сможем
        for steering in np.linspace(
                -1, 1, 3):  # выбирать можно и другую частоту дискретизации, но
            for acceleration in np.linspace(
                    -0.75, 0.75, 3):  # в наших тестах будет именно такая
                action = Action(steering, acceleration)
                agent_vector_representation = np.append(sensor_info, action)
                agent_vector_representation = agent_vector_representation.flatten(
                )[:, np.newaxis]
                predicted_reward = float(
                    self.neural_net.feedforward(agent_vector_representation))
                rewards_to_controls_map[predicted_reward] = action

        # ищем действие, которое обещает максимальную награду
        rewards = list(rewards_to_controls_map.keys())
        highest_reward = max(rewards)
        best_action = rewards_to_controls_map[highest_reward]

        # Добавим случайности, дух авантюризма. Иногда выбираем совершенно
        # рандомное действие
        if (not self.evaluate_mode) and (random.random() < 0.05):
            highest_reward = rewards[np.random.choice(len(rewards))]
            best_action = rewards_to_controls_map[highest_reward]
            # следующие строки помогут вам понять, что предсказывает наша сеть
            print("Chosen random action w/reward: {}".format(highest_reward))
        else:
            print("Chosen action w/reward: {}".format(highest_reward))

        # запомним всё, что только можно: мы хотим учиться на своих ошибках
        self.sensor_data_history.append(sensor_info)
        self.chosen_actions_history.append(best_action)
        self.reward_history.append(
            0.0)  # мы пока не знаем, какая будет награда, это
        # откроется при вызове метода receive_feedback внешним миром

        return best_action

    def receive_feedback(self, reward, train_every=100, reward_depth=7):
        """
        Получить реакцию на последнее решение, принятое сетью, и проанализировать его
        :param reward: оценка внешним миром наших действий
        :param train_every: сколько нужно собрать наблюдений, прежде чем запустить обучение на несколько эпох
        :param reward_depth: на какую глубину по времени распространяется полученная награда
        """
        # считаем время жизни сети; помогает отмерять интервалы обучения
        self.step += 1

        # начиная с полной полученной истинной награды,
        # размажем её по предыдущим наблюдениям
        # чем дальше каждый раз домножая её на 1/2
        # (если мы врезались в стену - разумно наказывать не только последнее
        # действие, но и предшествующие)
        i = -1
        while len(self.reward_history) > abs(i) and abs(i) < reward_depth:
            self.reward_history[i] += reward
            reward *= 0.5
            i -= 1

        # Если у нас накопилось хоть чуть-чуть данных, давайте потренируем нейросеть
        # прежде чем собирать новые данные
        # (проверьте, что вы в принципе храните достаточно данных (параметр `history_data` в `__init__`),
        # чтобы условие len(self.reward_history) >= train_every выполнялось
        if not self.evaluate_mode and (len(self.reward_history) >= train_every
                                       ) and not (self.step % train_every):
            X_train = np.concatenate(
                [self.sensor_data_history, self.chosen_actions_history],
                axis=1)
            y_train = self.reward_history
            train_data = [(x[:, np.newaxis], y)
                          for x, y in zip(X_train, y_train)]
            self.neural_net.SGD(training_data=train_data,
                                epochs=15,
                                mini_batch_size=train_every,
                                eta=0.05)
示例#4
0
class SimpleCarAgent(Agent):
    def __init__(self, history_data: int = 50000):
        """
        Creates Car Agent
            :param history_data: num of stored records (results of previous steps)
        """
        self.evaluate_mode = False  # # (True) if we evaluate model, otherwise - training mode (False)
        self._rays = RAYS_COUNT  # radar beams count

        self.neural_net = Network(NETWORK,
                                  output_function=lambda x: x,
                                  output_derivative=lambda x: 1)
        self.sensor_data_history = deque([], maxlen=history_data)
        self.chosen_actions_history = deque([], maxlen=history_data)
        self.reward_history = deque([], maxlen=history_data)
        self.step = 0

    @classmethod
    def from_weights(cls, layers: List[int], weights, biases):
        """
        Creates agent by neural network params.
        """
        agent = SimpleCarAgent()
        agent._rays = weights[0].shape[1] - NUM_DEFAULT_INPUT_NEURONS
        nn = Network(layers,
                     output_function=lambda x: x,
                     output_derivative=lambda x: 1)

        if len(weights) != len(nn.weights):
            raise AssertionError(
                "You provided %d weight matrices instead of %d" %
                (len(weights), len(nn.weights)))
        for i, (w, right_w) in enumerate(zip(weights, nn.weights)):
            if w.shape != right_w.shape:
                raise AssertionError("weights[%d].shape = %s instead of %s" %
                                     (i, w.shape, right_w.shape))
        nn.weights = weights

        if len(biases) != len(nn.biases):
            raise AssertionError("You provided %d bias vectors instead of %d" %
                                 (len(weights), len(nn.weights)))
        for i, (b, right_b) in enumerate(zip(biases, nn.biases)):
            if b.shape != right_b.shape:
                raise AssertionError("biases[%d].shape = %s instead of %s" %
                                     (i, b.shape, right_b.shape))
        nn.biases = biases

        agent.neural_net = nn

        return agent

    @classmethod
    def from_string(cls, s):
        from numpy import array  # important for eval execution
        layers, weights, biases = eval(s.replace("\n", ""), locals())
        return cls.from_weights(layers, weights, biases)

    @classmethod
    def from_file(cls, filename):
        with open(filename, "r") as f:
            return cls.from_string(f.read())

    def show_weights(self):
        params = self.neural_net.sizes, self.neural_net.weights, self.neural_net.biases
        np.set_printoptions(threshold=np.nan)
        return repr(params)

    def to_file(self, filename):
        c = self.show_weights()
        f = open(filename, "w")
        f.write(c)
        f.close()

    @property
    def rays(self):
        return self._rays

    def choose_action(self, sensor_info):
        # try to predict reward for all actions that are avaliable from current state
        rewards_to_controls_map = {}

        # make discrete a set of values,
        # because we can to predict just some of them

        # you can choose another step of discretization
        for steering in np.linspace(-1, 1, 3):
            for acceleration in np.linspace(-0.75, 0.75, 3):
                action = Action(steering, acceleration)
                agent_vector_representation = np.append(sensor_info, action)
                agent_vector_representation = agent_vector_representation.flatten(
                )[:, np.newaxis]
                predicted_reward = float(
                    self.neural_net.feedforward(agent_vector_representation))
                rewards_to_controls_map[predicted_reward] = action

        # search for action with best reward
        rewards = list(rewards_to_controls_map.keys())
        highest_reward = max(rewards)
        best_action = rewards_to_controls_map[highest_reward]

        # Sometimes we make random action
        if (not self.evaluate_mode) and (random.random() < 0.05):
            highest_reward = rewards[np.random.choice(len(rewards))]
            best_action = rewards_to_controls_map[highest_reward]

        # следующие строки помогут вам понять, что предсказывает наша сеть
        #     print("Chosen random action w/reward: {}".format(highest_reward))
        # else:
        #     print("Chosen action w/reward: {}".format(highest_reward))

        # запомним всё, что только можно: мы хотим учиться на своих ошибках
        self.sensor_data_history.append(sensor_info)
        self.chosen_actions_history.append(best_action)

        # here we do not know what reward is
        # method receive_feedback calculates real reward from predicted action
        self.reward_history.append(0.0)

        return best_action

    def receive_feedback(self, reward, train_every=50, reward_depth=7):
        """
        Receive feedback on the latest decision,
            predicted by neural network and analyze it

        :param reward: real world reward
        :param train_every: sufficient data count for training mode
        :param reward_depth: how many actions in a row affects on reward

        """
        # считаем время жизни сети; помогает отмерять интервалы обучения
        self.step += 1

        # начиная с полной полученной истинной награды,
        # размажем её по предыдущим наблюдениям
        # чем дальше каждый раз домножая её на 1/2
        # (если мы врезались в стену - разумно наказывать не только последнее
        # действие, но и предшествующие)
        i = -1
        while len(self.reward_history) > abs(i) and abs(i) < reward_depth:
            self.reward_history[i] += reward
            reward *= 0.5
            i -= 1

        # Если у нас накопилось хоть чуть-чуть данных, давайте потренируем нейросеть
        # прежде чем собирать новые данные
        # (проверьте, что вы в принципе храните достаточно данных (параметр `history_data` в `__init__`),
        # чтобы условие len(self.reward_history) >= train_every выполнялось
        if not self.evaluate_mode and (len(self.reward_history) >= train_every
                                       ) and not (self.step % train_every):
            X_train = np.concatenate(
                [self.sensor_data_history, self.chosen_actions_history],
                axis=1)
            y_train = self.reward_history
            train_data = [(x[:, np.newaxis], y)
                          for x, y in zip(X_train, y_train)]
            self.neural_net.SGD(training_data=train_data,
                                epochs=15,
                                mini_batch_size=train_every,
                                eta=0.05)