勾配ポリシー導出について


19

元のリソースであるAndrej Karpathyブログから、ポリシーグラデーションの非常に単純な例を再現しようとしています。その記事には、カートポールとポリシーグラディエントの例と、ウェイトとソフトマックスのアクティブ化のリストがあります。これは、完璧に機能する 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どちらも確実に機能するはずです(以下の説明に基づく)。しかし、私のポリシーグラディエントモデルは何も学習せず、ランダムに保ちます。なにか提案を?

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)カートポールとドゥームによる政策勾配の紹介

3)ポリシーの勾配の導出とREINFORCEの実装

4)今日の機械学習トリック(5):ログ微分トリック12


更新

以下の答えのようにグラフィックからいくつかの作業を行うことができるようです。しかし、それは確率の対数ではなく、ポリシーの勾配でもありません。RLグラデーションポリシーの目的全体を変更します。上記の参考文献を確認してください。画像に続いて、次のステートメントです。

ここに画像の説明を入力してください

私のポリシーのログ関数の勾配(単に重みとsigmoidアクティブ化)を取得する必要があります。


4
この質問はほとんどが理論的な質問であるため、Data Science Stack Exchangeに投稿することをお勧めします(Stack Overflowは主にコーディングに関する質問です)。また、このドメインに精通しているより多くの人々にリーチします。
Gilles-PhilippePaillé19年

@Gilles-PhilippePaillé問題を表すコードを追加しました。私がする必要があるのは、アクティベーションで一部のパーツを修正することだけです。更新された回答を確認してください。
GensaGames

1
ポリシーの勾配を導き出すために、同じタイプのアレンジメントの実際の例を示した参考記事を示します。うまくいけば、詳細に学習できます:medium.com/@thechrisyoon/…
ムハンマドウスマン

@MuhammadUsman。情報をありがとう。私はそのソースを赤にします。現時点では明確でフォームの例ですが、アクティベーションをからsoftmaxに変更していsignmoidます。これは、上記の例で私がしなければならない唯一のことです。
GensaGames

2
@JasonChiaシグモイド[0, 1]は、正のアクションの確率として解釈できる範囲の実数を出力します(たとえば、CartPoleで右折します)。次に、負のアクション(左折)の確率は1 - sigmoidです。この確率の合計は1です。はい、これは標準のポールカード環境です。
Pavel Tyshevskyi

回答:


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メソッドの目的は、損失関数の勾配を計算することです。重み。詳細を省いて、適切な勾配は(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シグモイドグラデーションの消失問題のために省略しました。
Pavel Tyshevskyi

ここで重要なのは、重みを変更する方向を示すことです。の場合action = 1、にprobs近づけ1て、重みを増やします(正の勾配)。の場合action=0、にprobs近づけたいため0、重みを減らします(負の勾配)。
Pavel Tyshevskyi

1
いずれにしても、上記の変更はまったく機能しません。ファイル全体を共有できますか?同時に、私は明確なサンプルを作りたいと思っています。この場合、問題が消えるのを気にしません。そして、(action - probs)それは同じワイトを変えるもう一つの方法です。
GensaGames
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.