Ich versuche, ein sehr einfaches Beispiel für Policy Gradient aus dem Blog Andrej Karpathy zu erstellen . In diesem Artikel finden Sie ein Beispiel für CartPole und Policy Gradient mit Gewichtsliste und Softmax-Aktivierung. Hier ist mein neu erstelltes und sehr einfaches Beispiel für einen CartPole-Richtlinienverlauf, der perfekt funktioniert .
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)
.
.
Frage
Ich versuche es, fast das gleiche Beispiel, aber mit Sigmoid-Aktivierung (nur der Einfachheit halber). Das ist alles was ich tun muss. Schalten Sie die Aktivierung im Modell von softmax
auf sigmoid
. Welches sollte sicher funktionieren (basierend auf der Erklärung unten). Aber mein Policy Gradient-Modell lernt nichts und bleibt zufällig. Irgendein Vorschlag?
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)
Das Zeichnen des gesamten Lernens bleibt zufällig. Nichts hilft beim Einstellen von Hyperparametern. Unter dem Beispielbild.
Referenzen :
1) Deep Reinforcement Learning: Pong aus Pixeln
2) Eine Einführung in Policy Gradients mit Cartpole und Doom
3) Ableiten von Richtlinienverläufen und Implementieren von REINFORCE
4) Trick des Tages beim maschinellen Lernen (5): Log Derivative Trick 12
AKTUALISIEREN
Scheint, als ob die Antwort unten etwas Arbeit von der Grafik machen könnte. Aber es ist keine Protokollwahrscheinlichkeit und nicht einmal ein Gradient der Richtlinie. Und ändert den gesamten Zweck der RL-Verlaufsrichtlinie. Bitte überprüfen Sie die Referenzen oben. Nach dem Bild folgen wir der nächsten Aussage.
Ich muss einen Verlauf der Protokollfunktion meiner Richtlinie erstellen (dies sind lediglich Gewichte und sigmoid
Aktivierung).
softmax
auf zu ändernsignmoid
. Das ist nur eine Sache, die ich im obigen Beispiel tun muss.[0, 1]
, die als Wahrscheinlichkeit einer positiven Aktion interpretiert werden kann (biegen Sie beispielsweise in CartPole rechts ab). Dann ist die Wahrscheinlichkeit einer negativen Aktion (links abbiegen)1 - sigmoid
. Die Summe dieser Wahrscheinlichkeiten ist 1. Ja, dies ist eine Standard-Polkartenumgebung.Antworten:
Das Problem ist mit der
grad
Methode.Im ursprünglichen Code wurde Softmax zusammen mit der CrossEntropy-Verlustfunktion verwendet. Wenn Sie die Aktivierung auf Sigmoid umschalten, wird die richtige Verlustfunktion zu Binary CrossEntropy. Der Zweck der
grad
Methode besteht nun darin, den Gradienten der Verlustfunktion wrt zu berechnen. Gewichte. Wenn Sie die Details schonen , wird der richtige Gradient(probs - action) * state
in der Terminologie Ihres Programms angegeben. Das Letzte ist, ein Minuszeichen hinzuzufügen - wir wollen das Negativ der Verlustfunktion maximieren.Richtige
grad
Methode also:Eine weitere Änderung, die Sie möglicherweise hinzufügen möchten, ist die Erhöhung der Lernrate.
LEARNING_RATE = 0.0001
undNUM_EPISODES = 5000
wird das folgende Diagramm erzeugen:Die Konvergenz ist viel schneller, wenn die Gewichte unter Verwendung der Gaußschen Verteilung mit dem Mittelwert Null und der kleinen Varianz initialisiert werden:
AKTUALISIEREN
Vollständiger Code hinzugefügt, um die Ergebnisse zu reproduzieren:
quelle
sigmoid
. Aber Ihr Farbverlauf als Antwort sollte nichts mit meinem Farbverlauf zu tun haben. Recht?(action - probs) * sigmoid_grad(probs)
, aber ich habe essigmoid_grad
wegen des verschwindenden Problems mit dem Sigmoid-Verlauf weggelassen .action = 1
wirprobs
näher dran sein wollen1
, erhöhen wir die Gewichte (positiver Gradient). Wennaction=0
wirprobs
näher sein wollen0
, verringern wir die Gewichte (negativer Gradient).(action - probs)
es ist nur eine andere Möglichkeit, die gleichen Gewichte zu ändern.