Récemment, je suis accro au renforcement de l'apprentissage. Après tout, c'est un homme qui veut tenir un bâton lors de l'apprentissage par renforcement. Donc, je présenterai le CartPole </ font> d'OpenAI Gym après la dernière fois.
Article précédent Je veux escalader une montagne avec un apprentissage amélioré
En ce qui concerne l'apprentissage Q mentionné dans l'article précédent, cette fois, j'aimerais utiliser une méthode appelée SARSA. Revoyons. Mise à jour de la valeur de comportement de l'état Q dans l'apprentissage par renforcement,
Est effectué pour chaque transition d'état. La différence entre l'apprentissage SARSA et Q est de savoir comment déterminer ce $ G_ {t} $.
Pour ** Q learning ** </ font>
Pour ** SARSA ** </ font>
Ici, $ a_ {t + 1} ^ {\ pi} $ indique l'action lorsque l'action suivante est sélectionnée selon la politique dans l'état $ s_ {t + 1} $. Ce que nous pouvons voir de ce qui précède, c'est que Q learning utilise max pour mettre à jour la valeur, c'est-à-dire qu'il s'agit d'une méthode d'apprentissage ** optimiste ** qui se met à jour en utilisant la valeur d'état maximale pouvant être obtenue. En revanche, SARSA prend en compte les actions suivantes, ce qui en fait une manière plus ** réaliste ** de déterminer les stratégies. Cette fois, nous les comparerons également.
Si vous maintenez ce bâton debout pendant une longue période (200 pas), il sera effacé. Il y a quatre états donnés, ** la position du chariot, la vitesse du chariot, l'angle du pôle et la vitesse angulaire du pôle **. Les actions se limitent à pousser le chariot vers la gauche: 0 et à pousser vers la droite: 1. L'angle du poteau est incliné de 12 degrés ou plus, ou l'endurance est de 200 pas.
Tout d'abord, importez la bibliothèque.
import gym
from gym import logger as gymlogger
gymlogger.set_level(40) #error only
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
import math
import glob
import io
import base64
Définit une classe SARSA qui implémente l'apprentissage.
class SARSA:
def __init__(self, env):
self.env = env
self.env_low = self.env.observation_space.low #État minimum
self.env_high = self.env.observation_space.high #État valeur maximale
tmp = [7,7,7,7] #Divisez l'état en 7 états
self.env_dx = [0,0,0,0]
self.env_dx[0] = (self.env_high[0] - self.env_low[0]) / tmp[0]
self.env_dx[1] = (self.env_high[1] - self.env_low[1]) / tmp[1]
self.env_dx[2] = (self.env_high[2] - self.env_low[2]) / tmp[2]
self.env_dx[3] = (self.env_high[3] - self.env_low[3]) / tmp[3]
self.q_table = np.zeros((tmp[0],tmp[1],tmp[2],tmp[3],2)) #Initialisation de la fonction de valeur d'état
def get_status(self, _observation): #État discriminatoire
s1 = int((_observation[0] - self.env_low[0])/self.env_dx[0]) #Passez dans l'un des sept états
if _observation[1] < -1.5: #Classer par vous-même
s2 = 0
elif -1.5 <= _observation[1] < - 1:
s2 = 1
elif -1 <= _observation[1] < -0.5:
s2 = 2
elif -0.5 <= _observation[1] < 0.5:
s2 = 3
elif 0.5 <= _observation[1] < 1.5:
s2 = 4
elif 1.5 <= _observation[1] < 2:
s2 = 5
elif 2 <= _observation[1]:
s2 = 6
s3 = int((_observation[2] - self.env_low[2])/self.env_dx[2]) #Passez dans l'un des sept états
if _observation[3] < -1: #Classer par vous-même
s4 = 0
elif -1 <= _observation[3] < -0.7:
s4 = 1
elif -0.7 <= _observation[3] < -0.6:
s4 = 2
elif -0.6 <= _observation[3] < -0.5:
s4 = 3
elif -0.5 <= _observation[3] < -0.4:
s4 = 4
elif -0.4 <= _observation[3] < -0.4:
s4 = 5
else:
s4 = 6
return s1, s2, s3, s4
def policy(self, s, epi): #Sélectionnez une action dans les états
epsilon = 0.5 * (1 / (epi + 1))
if np.random.random() <= epsilon:
return np.random.randint(2) #Choisissez au hasard
else:
s1, s2, s3, s4 = self.get_status(s)
return np.argmax(self.q_table[s1][s2][s3][s4]) #Sélectionnez l'action avec la valeur d'action la plus élevée
def learn(self, time = 200, alpha = 0.5, gamma = 0.99): #Apprenez autant de fois que le temps
log = [] #Enregistrez la récompense totale pour chaque épisode
t_log = [] #Enregistrez le nombre de pas par épisode
for j in range(time+1):
t = 0 #Nombre d'étapes
total = 0 #Récompense totale
s = self.env.reset()
done = False
while not done:
t += 1
a = self.policy(s, j)
next_s, reward, done, _ = self.env.step(a)
reward = t/10 #Plus vous endurez longtemps, plus vous obtenez de récompenses
if done:
if t < 195:
reward -= 1000 #Pénalités pour non-endurance
else:
reward = 1000 #Donnez plus de récompenses en cas de succès
total += reward
s1, s2, s3, s4 = self.get_status(next_s)
G = reward + gamma * self.q_table[s1][s2][s3][s4][self.policy(next_s, j)] #Calcul de la récompense cumulée
s1, s2, s3, s4 = self.get_status(s)
self.q_table[s1][s2][s3][s4][a] += alpha*(G - self.q_table[s1][s2][s3][s4][a]) #Mise à jour Q
s = next_s
t_log.append(t)
log.append(total)
if j %1000 == 0:
print(str(j) + " ===total reward=== : " + str(total))
return plt.plot(t_log)
def show(self): #Afficher les résultats d'apprentissage
s = self.env.reset()
img = self.env.render()
done = False
t = 0
while not done:
t += 1
a = self.policy(s, 10000)
s, _, done, _ = self.env.step(a)
self.env.render()
print(t)
self.env.reset()
self.env.close()
Voilà où j'ai trébuché. Chez init, je me prépare à disperser chacun des quatre états avec env_dx, mais j'ai un problème ici. Si vous regardez attentivement la référence, La zone variable de la valeur de vitesse est ** inf **. Oui, ** c'est infini! **
Dans ce cas, la valeur de env_dx devient également infinie et la dispersion des valeurs continues ne fonctionne pas. Donc,
from random import random
env.step(random.randint(2))
Nous avons effectué plusieurs fois et observé des variations de la vitesse du chariot puis de la vitesse angulaire de la perche. Puis,
if _observation[1] < -1.5: #La vitesse du chariot
s2 = 0
elif -1.5 <= _observation[1] < - 1:
s2 = 1
elif -1 <= _observation[1] < -0.5:
s2 = 2
elif -0.5 <= _observation[1] < 0.5:
s2 = 3
elif 0.5 <= _observation[1] < 1.5:
s2 = 4
elif 1.5 <= _observation[1] < 2:
s2 = 5
elif 2 <= _observation[1]:
s2 = 6
if _observation[3] < -1: #Vitesse angulaire du pôle
s4 = 0
elif -1 <= _observation[3] < -0.7:
s4 = 1
elif -0.7 <= _observation[3] < -0.6:
s4 = 2
elif -0.6 <= _observation[3] < -0.5:
s4 = 3
elif -0.5 <= _observation[3] < -0.4:
s4 = 4
elif -0.4 <= _observation[3] < -0.4:
s4 = 5
else:
s4 = 6
J'ai réalisé que je pouvais le classer comme ça.
Apprenez comme ça. C'est environ 3000 fois et je peux me le permettre.
env = gym.make('CartPole-v0')
agent = SARSA(env)
agent.learn(time = 3000)
Le changement du nombre d'étapes est comme ça.
Maintenant, vérifions l'animation avec ```agent.show () `` `.
C'est assez stable et a une grande durabilité. Je suis heureux d'être un ** homme **.
Comparons l'apprentissage Q et SARSA dans cet environnement. Apprentissage G en Q
G = reward + gamma * max(self.q_table[s1][s2][s3][s4])
Faire. Quand j'essaye d'apprendre avec ça, La stabilité de la convergence semble meilleure avec SARSA. Si vous êtes un homme, regardez la réalité comme SARSA. Oui.
Dans cet environnement, je me suis demandé si la dispersion des États était la partie la plus difficile. Il semble que DQN soit né pour résoudre ce problème. La prochaine fois, je pense que je vais essayer de construire un DQN. à plus!
Recommended Posts