Розуміння перенесення градієнтної політики


19

Я намагаюся відтворити дуже простий приклад програми «Градієнт політики» з його ресурсного джерела блогу «Андрій Карпаті» . У цьому артикулі ви знайдете приклад із CartPole та Gradient Policy зі списком ваги та активації Softmax. Ось мій відтворений і дуже простий приклад градієнта політики CartPole, який ідеально працює .

import gym
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
import copy

NUM_EPISODES = 4000
LEARNING_RATE = 0.000025
GAMMA = 0.99


# noinspection PyMethodMayBeStatic
class Agent:
    def __init__(self):
        self.poly = PolynomialFeatures(1)
        self.w = np.random.rand(5, 2)

    def policy(self, state):
        z = state.dot(self.w)
        exp = np.exp(z)
        return exp/np.sum(exp)

    def __softmax_grad(self, softmax):
        s = softmax.reshape(-1,1)
        return np.diagflat(s) - np.dot(s, s.T)

    def grad(self, probs, action, state):
        dsoftmax = self.__softmax_grad(probs)[action,:]
        dlog = dsoftmax / probs[0,action]
        grad = state.T.dot(dlog[None,:])
        return grad

    def update_with(self, grads, rewards):

        for i in range(len(grads)):
            # Loop through everything that happend in the episode
            # and update towards the log policy gradient times **FUTURE** reward

            total_grad_effect = 0
            for t, r in enumerate(rewards[i:]):
                total_grad_effect += r * (GAMMA ** r)
            self.w += LEARNING_RATE * grads[i] * total_grad_effect
            print("Grads update: " + str(np.sum(grads[i])))



def main(argv):
    env = gym.make('CartPole-v0')
    np.random.seed(1)

    agent = Agent()
    complete_scores = []

    for e in range(NUM_EPISODES):
        state = env.reset()[None, :]
        state = agent.poly.fit_transform(state)

        rewards = []
        grads = []
        score = 0

        while True:

            probs = agent.policy(state)
            action_space = env.action_space.n
            action = np.random.choice(action_space, p=probs[0])

            next_state, reward, done,_ = env.step(action)
            next_state = next_state[None,:]
            next_state = agent.poly.fit_transform(next_state.reshape(1, 4))
            grad = agent.grad(probs, action, state)

            grads.append(grad)
            rewards.append(reward)

            score += reward
            state = next_state

            if done:
                break

        agent.update_with(grads, rewards)
        complete_scores.append(score)

    env.close()
    plt.plot(np.arange(NUM_EPISODES),
             complete_scores)
    plt.savefig('image1.png')


if __name__ == '__main__':
    main(None)

введіть тут опис зображення

.

.

Питання

Я намагаюся зробити, майже такий же приклад, але з активацією Sigmoid (просто для простоти). Це все, що мені потрібно зробити. Переключіть активацію в моделі з softmaxна sigmoid. Що повинно працювати точно (на основі пояснення нижче). Але моя політика Gradient model нічого не вчиться, і вона залишається випадковою. Будь-яка пропозиція?

import gym
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures

NUM_EPISODES = 4000
LEARNING_RATE = 0.000025
GAMMA = 0.99


# noinspection PyMethodMayBeStatic
class Agent:
    def __init__(self):
        self.poly = PolynomialFeatures(1)
        self.w = np.random.rand(5, 1) - 0.5

    # Our policy that maps state to action parameterized by w
    # noinspection PyShadowingNames
    def policy(self, state):
        z = np.sum(state.dot(self.w))
        return self.sigmoid(z)

    def sigmoid(self, x):
        s = 1 / (1 + np.exp(-x))
        return s

    def sigmoid_grad(self, sig_x):
        return sig_x * (1 - sig_x)

    def grad(self, probs, action, state):
        dsoftmax = self.sigmoid_grad(probs)
        dlog = dsoftmax / probs
        grad = state.T.dot(dlog)
        grad = grad.reshape(5, 1)
        return grad

    def update_with(self, grads, rewards):
        if len(grads) < 50:
            return
        for i in range(len(grads)):
            # Loop through everything that happened in the episode
            # and update towards the log policy gradient times **FUTURE** reward

            total_grad_effect = 0
            for t, r in enumerate(rewards[i:]):
                total_grad_effect += r * (GAMMA ** r)
            self.w += LEARNING_RATE * grads[i] * total_grad_effect


def main(argv):
    env = gym.make('CartPole-v0')
    np.random.seed(1)

    agent = Agent()
    complete_scores = []

    for e in range(NUM_EPISODES):
        state = env.reset()[None, :]
        state = agent.poly.fit_transform(state)

        rewards = []
        grads = []
        score = 0

        while True:

            probs = agent.policy(state)
            action_space = env.action_space.n
            action = np.random.choice(action_space, p=[1 - probs, probs])

            next_state, reward, done, _ = env.step(action)
            next_state = next_state[None, :]
            next_state = agent.poly.fit_transform(next_state.reshape(1, 4))

            grad = agent.grad(probs, action, state)
            grads.append(grad)
            rewards.append(reward)

            score += reward
            state = next_state

            if done:
                break

        agent.update_with(grads, rewards)
        complete_scores.append(score)

    env.close()
    plt.plot(np.arange(NUM_EPISODES),
             complete_scores)
    plt.savefig('image1.png')


if __name__ == '__main__':
    main(None)

Складання всього навчання зберігається випадковим чином. Ніщо не допомагає в налаштуванні гіпер параметрів. Нижче зразка зображення.

введіть тут опис зображення

Список літератури :

1) Навчання глибокого зміцнення: понг з пікселів

2) Ознайомлення з градієнтами політики з Cartpole та Doom

3) Отримання градієнтів політики та реалізація REINFORCE

4) Машинобудівний трюк дня (5): Трюк похідних журналів 12


ОНОВЛЕННЯ

Здається, відповідь нижче може зробити якусь роботу з графіки. Але це не ймовірність журналу, а не навіть градієнт політики. І змінює всю мету політики щодо градієнтів Р.Л. Перевірте посилання вище. Після зображення ми наступне твердження.

введіть тут опис зображення

Мені потрібно взяти градієнт журналу функції моєї політики (це просто ваги та sigmoidактивація).


4
Я пропоную вам опублікувати це питання на Data Science Stack Exchange, оскільки це здебільшого теоретичне запитання (Переповнення стека - це переважно для питань кодування). Ви також охопите більше людей, які знають у цій галузі.
Жиль-Філіп Пайле

@ Gilles-PhilippePaillé Я додав код, який представляє проблему. Що мені потрібно зробити, це просто виправити деякі частини за допомогою активації. Перевірте оновлену відповідь.
GensaGames

1
Для отримання градієнтів політики, тут довідкова стаття з робочим прикладом однотипних домовленостей. Сподіваємось, ви дізнаєтесь детально: medium.com/@thechrisyoon/… .
Мухаммад Усман

@MuhammadUsman. Дякую за інформацію. Я червоне це джерело. Зараз це зрозуміло і приклад форми вгорі, я намагаюся змінити активацію з softmaxна signmoid. Це лише одне, що мені потрібно зробити в прикладі вище.
GensaGames

2
@JasonChia сигмоїд виводить реальне число в діапазоні, [0, 1]яке можна інтерпретувати як ймовірність позитивної дії (наприклад, поверніть праворуч у CartPole). Тоді ймовірність негативної дії (повернути ліворуч) 1 - sigmoid. Сума цієї ймовірності становить 1. Так, це стандартне середовище полюсної карти.
Павло Тишевський

Відповіді:


8

Проблема полягає в gradметоді.

def grad(self, probs, action, state):
    dsoftmax = self.sigmoid_grad(probs)
    dlog = dsoftmax / probs
    grad = state.T.dot(dlog)
    grad = grad.reshape(5, 1)
    return grad

У вихідному коді Softmax використовувався разом із функцією втрати CrossEntropy. Коли ви переключите активацію на Sigmoid, правильною функцією втрати стає Binary CrossEntropy. Тепер мета gradметоду - обчислити градієнт функції втрат wrt. ваги. Економлячи деталі, належний градієнт визначається (probs - action) * stateу термінології вашої програми. Останнє - додати знак мінус - ми хочемо максимізувати мінус функції втрати.

Правильний gradспосіб таким чином:

def grad(self, probs, action, state):
    grad = state.T.dot(probs - action)
    return -grad

Ще одна зміна, яку ви можете додати, - це збільшити рівень навчання. LEARNING_RATE = 0.0001і NUM_EPISODES = 5000створить наступний сюжет:

Правильна середня винагорода проти кількості епізодів

Конвергенція буде набагато швидшою, якщо ваги ініціалізуються з використанням розподілу Гаусса з нульовою середньою та малою дисперсією:

def __init__(self):
    self.poly = PolynomialFeatures(1)
    self.w = np.random.randn(5, 1) * 0.01

введіть тут опис зображення

ОНОВЛЕННЯ

Додано повний код для відтворення результатів:

import gym
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures

NUM_EPISODES = 5000
LEARNING_RATE = 0.0001
GAMMA = 0.99


# noinspection PyMethodMayBeStatic
class Agent:
    def __init__(self):
        self.poly = PolynomialFeatures(1)
        self.w = np.random.randn(5, 1) * 0.01

    # Our policy that maps state to action parameterized by w
    # noinspection PyShadowingNames
    def policy(self, state):
        z = np.sum(state.dot(self.w))
        return self.sigmoid(z)

    def sigmoid(self, x):
        s = 1 / (1 + np.exp(-x))
        return s

    def sigmoid_grad(self, sig_x):
        return sig_x * (1 - sig_x)

    def grad(self, probs, action, state):
        grad = state.T.dot(probs - action)
        return -grad

    def update_with(self, grads, rewards):
        if len(grads) < 50:
            return
        for i in range(len(grads)):
            # Loop through everything that happened in the episode
            # and update towards the log policy gradient times **FUTURE** reward

            total_grad_effect = 0
            for t, r in enumerate(rewards[i:]):
                total_grad_effect += r * (GAMMA ** r)
            self.w += LEARNING_RATE * grads[i] * total_grad_effect


def main(argv):
    env = gym.make('CartPole-v0')
    np.random.seed(1)

    agent = Agent()
    complete_scores = []

    for e in range(NUM_EPISODES):
        state = env.reset()[None, :]
        state = agent.poly.fit_transform(state)

        rewards = []
        grads = []
        score = 0

        while True:

            probs = agent.policy(state)
            action_space = env.action_space.n
            action = np.random.choice(action_space, p=[1 - probs, probs])

            next_state, reward, done, _ = env.step(action)
            next_state = next_state[None, :]
            next_state = agent.poly.fit_transform(next_state.reshape(1, 4))

            grad = agent.grad(probs, action, state)
            grads.append(grad)
            rewards.append(reward)

            score += reward
            state = next_state

            if done:
                break

        agent.update_with(grads, rewards)
        complete_scores.append(score)

    env.close()
    plt.plot(np.arange(NUM_EPISODES),
             complete_scores)
    plt.savefig('image1.png')


if __name__ == '__main__':
    main(None)

Дуже дякую. Я спробую це рішення пізніше.
GensaGames

Я не впевнений, звідки ви берете таке виведення для моєї функції. Як ви можете перевірити зображення вище. Мені потрібно взяти градієнт журналу політики . Де Політика в моєму випадку просто зважує sigmoid. Але ваш градієнт у відповідь не повинен мати нічого спільного з моїм градієнтом. Правильно?
GensaGames

Зауважте, що ви не включаєте будь-яку інформацію про те, яку дію було виконано. Відповідно до цієї лекції з „Градієнти політики” (слайд 13) , оновлення має виглядати так (action - probs) * sigmoid_grad(probs), але я пропустив sigmoid_gradчерез проблему, що зникає з сигмоподібним градієнтом.
Павло Тишевський

Суть тут полягає в тому, щоб вказати напрямок, в якому ми хочемо змінити вагу. Якщо action = 1ми хочемо probsбути ближче 1, збільшуючи ваги (позитивний градієнт). Якщо action=0ми хочемо probsбути ближче 0, отже, зменшуємо ваги (від’ємний градієнт).
Павло Тишевський

1
У будь-якому випадку, зміни вище не працюють взагалі, чи можете ви поділитися цілим файлом? Одночасно я хочу зробити чіткий зразок, і мені не байдуже зникати проблеми в цьому випадку. І (action - probs)це просто ще один спосіб зміни однакових ваг.
GensaGames
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.