Memahami Kebijakan Gradien Berasal

19

Saya mencoba membuat ulang contoh Gradient Kebijakan yang sangat sederhana, dari sumbernya, blog Andrej Karpathy . Dalam artikel itu, Anda akan menemukan contoh dengan CartPole dan Policy Gradient dengan daftar bobot dan aktivasi Softmax. Ini adalah contoh gradien kebijakan CartPole yang saya buat dan sangat sederhana, yang berfungsi sempurna .

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)

masukkan deskripsi gambar di sini

.

.

Pertanyaan

Saya coba lakukan, contoh yang hampir sama tetapi dengan aktivasi Sigmoid (hanya untuk kesederhanaan). Hanya itu yang perlu saya lakukan. Beralih aktivasi dalam model dari softmaxke sigmoid. Yang pasti berhasil (berdasarkan penjelasan di bawah). Tetapi model Gradient Kebijakan saya tidak mempelajari apa pun dan tetap acak. Ada saran?

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)

Merencanakan semua pembelajaran dilakukan secara acak. Tidak ada yang membantu dengan menyetel parameter hiper. Di bawah gambar contoh.

masukkan deskripsi gambar di sini

Referensi :

1) Pembelajaran Penguatan Dalam: Pong from Pixels

2) Pengantar Gradien Kebijakan dengan Cartpole dan Doom

3) Turunkan Gradien Kebijakan dan Implementasi REINFORCE

4) Machine Learning Trick of the Day (5): Log Derivative Trick 12


MEMPERBARUI

Sepertinya jawaban di bawah ini dapat melakukan beberapa pekerjaan dari grafik. Tapi itu bukan probabilitas log, dan bahkan tidak gradien kebijakan. Dan mengubah seluruh tujuan Kebijakan Gradien RL. Silakan periksa referensi di atas. Setelah gambar kita pernyataan selanjutnya.

masukkan deskripsi gambar di sini

Saya perlu mengambil Gradien fungsi Log Kebijakan saya (yang hanya berupa bobot dan sigmoidaktivasi).

GensaGames
sumber
4
Saya menyarankan Anda untuk mengirim pertanyaan ini di Data Science Stack Exchange karena sebagian besar merupakan pertanyaan teoretis (Stack Overflow terutama untuk pertanyaan pengkodean). Anda juga akan menjangkau lebih banyak orang yang berpengetahuan luas di domain ini.
Gilles-Philippe Paillé
@ Gilles-PhilippePaillé Saya menambahkan kode, yang mewakili masalahnya. Apa yang perlu saya lakukan, itu hanya untuk memperbaiki beberapa bagian dengan aktivasi. Silakan periksa jawaban yang diperbarui.
GensaGames
1
Untuk Turunkan Gradien Kebijakan, berikut adalah artikel referensi dengan contoh kerja dari jenis pengaturan yang sama, Semoga Anda akan belajar secara terperinci: medium.com/@thechrisyoon/… .
Muhammad Usman
@Muhammad Usman. Terima kasih atas informasinya. Saya merah sumber itu. Saat ini sudah jelas dan membentuk contoh di atas, saya mencoba mengubah aktivasi dari softmaxmenjadi signmoid. Itu hanya satu hal yang perlu saya lakukan pada contoh di atas.
GensaGames
2
@JasonChia sigmoid menampilkan bilangan real dalam kisaran [0, 1]yang dapat diartikan sebagai kemungkinan tindakan positif (belok kanan di CartPole, misalnya). Maka probabilitas tindakan negatif (belok kiri) adalah 1 - sigmoid. Jumlah dari probabilitas ini adalah 1. Ya, ini adalah lingkungan kartu tiang standar.
Pavel Tyshevskyi

Jawaban:

8

Masalahnya dengan gradmetode.

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

Dalam kode asli Softmax digunakan bersama dengan fungsi kerugian CrossEntropy. Ketika Anda beralih aktivasi ke Sigmoid, fungsi kerugian yang tepat menjadi Binary CrossEntropy. Sekarang, tujuan dari gradmetode ini adalah untuk menghitung gradien dari fungsi kehilangan wrt. beban. Menyelamatkan detail, gradien yang tepat diberikan oleh (probs - action) * statedalam terminologi program Anda. Hal terakhir adalah menambahkan tanda minus - kami ingin memaksimalkan negatif dari fungsi kerugian.

gradMetode yang tepat sebagai berikut:

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

Perubahan lain yang mungkin ingin Anda tambahkan adalah untuk meningkatkan tingkat belajar. LEARNING_RATE = 0.0001dan NUM_EPISODES = 5000akan menghasilkan plot berikut:

Benar berarti imbalan vs jumlah episode

Konvergensi akan jauh lebih cepat jika bobot diinisialisasi menggunakan distribusi Gaussian dengan mean nol dan varians kecil:

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

masukkan deskripsi gambar di sini

MEMPERBARUI

Menambahkan kode lengkap untuk mereproduksi hasil:

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)
Pavel Tyshevskyi
sumber
Terima kasih banyak. Saya akan mencoba solusi ini nanti.
GensaGames
Saya tidak yakin, di mana Anda mengambil derivasi tersebut untuk fungsi saya. Seperti Anda dapat memeriksa gambar di atas. Saya perlu mengambil gradien dari log kebijakan . Di mana Kebijakan dalam kasus saya hanya berbobot sigmoid. Tetapi gradien Anda sebagai jawaban tidak ada hubungannya dengan gradien saya. Baik?
GensaGames
Perhatikan bahwa Anda tidak memasukkan informasi apa pun tentang tindakan apa yang dilakukan. Menurut kuliah tentang Gradien Kebijakan (slide 13) ini , pembaruan seharusnya terlihat seperti (action - probs) * sigmoid_grad(probs), tetapi saya dihilangkan sigmoid_gradkarena masalah menghilang dengan gradien sigmoid.
Pavel Tyshevskyi
Intinya di sini adalah untuk menunjukkan arah di mana kita ingin mengubah bobot. Jika action = 1, kita ingin probslebih dekat dengan 1, meningkatkan bobot (gradien positif). Jika action=0, kita ingin probslebih dekat 0, maka mengurangi bobot (gradien negatif).
Pavel Tyshevskyi
1
Bagaimanapun, perubahan di atas tidak berfungsi sama sekali, dapatkah Anda membagikan seluruh file? Pada saat yang sama, saya ingin membuat sampel yang jelas, dan tidak peduli masalah lenyap dalam kasus ini. Dan (action - probs)itu hanyalah cara lain untuk mengubah bobot yang sama.
GensaGames