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)
.
.
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 softmax
ke 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.
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.
Saya perlu mengambil Gradien fungsi Log Kebijakan saya (yang hanya berupa bobot dan sigmoid
aktivasi).
softmax
menjadisignmoid
. Itu hanya satu hal yang perlu saya lakukan pada contoh di atas.[0, 1]
yang dapat diartikan sebagai kemungkinan tindakan positif (belok kanan di CartPole, misalnya). Maka probabilitas tindakan negatif (belok kiri) adalah1 - sigmoid
. Jumlah dari probabilitas ini adalah 1. Ya, ini adalah lingkungan kartu tiang standar.Jawaban:
Masalahnya dengan
grad
metode.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
grad
metode ini adalah untuk menghitung gradien dari fungsi kehilangan wrt. beban. Menyelamatkan detail, gradien yang tepat diberikan oleh(probs - action) * state
dalam terminologi program Anda. Hal terakhir adalah menambahkan tanda minus - kami ingin memaksimalkan negatif dari fungsi kerugian.grad
Metode yang tepat sebagai berikut:Perubahan lain yang mungkin ingin Anda tambahkan adalah untuk meningkatkan tingkat belajar.
LEARNING_RATE = 0.0001
danNUM_EPISODES = 5000
akan menghasilkan plot berikut:Konvergensi akan jauh lebih cepat jika bobot diinisialisasi menggunakan distribusi Gaussian dengan mean nol dan varians kecil:
MEMPERBARUI
Menambahkan kode lengkap untuk mereproduksi hasil:
sumber
sigmoid
. Tetapi gradien Anda sebagai jawaban tidak ada hubungannya dengan gradien saya. Baik?(action - probs) * sigmoid_grad(probs)
, tetapi saya dihilangkansigmoid_grad
karena masalah menghilang dengan gradien sigmoid.action = 1
, kita inginprobs
lebih dekat dengan1
, meningkatkan bobot (gradien positif). Jikaaction=0
, kita inginprobs
lebih dekat0
, maka mengurangi bobot (gradien negatif).(action - probs)
itu hanyalah cara lain untuk mengubah bobot yang sama.