C'est un jeu Atari qui est souvent utilisé dans l'évaluation de l'apprentissage par renforcement, mais il semble qu'une méthode au-delà des humains soit finalement apparue dans les 57 jeux. J'ai essayé de le mettre en œuvre immédiatement.
Le code créé dans cet article est ci-dessous.
Quant à la configuration, la première moitié est l'explication technique et la seconde moitié est l'explication de mise en œuvre.
Agent57 est une méthode d'apprentissage par renforcement de la série DQN. J'ai déjà écrit sur la technologie jusqu'à l'agent 57 de la série DQN, alors n'hésitez pas à me contacter.
Les 57 jeux d'Atari2600 sont souvent utilisés comme indicateurs de l'apprentissage par renforcement, mais finalement les 57 jeux ont révélé des méthodes d'apprentissage par renforcement qui dépassent les performances humaines. Il y avait des jeux tels que Montezuma's Revenge qui étaient difficiles à apprendre avec la méthode existante, mais Agent57 semble être capable d'apprendre correctement.
Vous trouverez ci-dessous une comparaison de chaque méthode citée dans l'article de Deep Mind.
Je pensais que F (ApeX) et G (R2D2) étaient incroyables, mais ce sont des performances écrasantes au-delà.
·référence Agent57: Outperforming the human Atari benchmark Atari Complete Conquest! Atari57 Qu'est-ce que l'Agent57 qui surpasse les humains dans tous les jeux!?
(Figure tirée de l'article de Deep Mind)
Cet article décrit NGU (Never Give Up) et Agent57.
Comme le montre la figure, l'agent 57 est une amélioration de la méthode DQN existante. J'espère que vous pourrez vous référer à mes articles passés pour le contenu qui vous intéresse sur les méthodes passées.
Le changement majeur dans NGU / Agent57 est qu'il se concentre sur l'exploration et l'exploitation, et introduit un mécanisme qui permet une exploration efficace même dans des environnements où les récompenses sont difficiles à obtenir. En plus de cela, diverses méthodes ont été adoptées, je voudrais donc les expliquer une par une.
NGU(Never Give Up)
Il y a un compromis entre l'exploration d'un territoire inconnu et l'obtention d'une récompense (exploitation) en apprentissage intensif. Il y avait un problème que la méthode existante ne pouvait pas bien apprendre dans les jeux où la récompense était rare (il a fallu beaucoup de temps pour obtenir la récompense). Par conséquent, NGU réalise une recherche efficace en ajoutant une récompense interne (récompense intrinsèque) à la récompense.
Les récompenses internes doivent remplir les trois conditions suivantes.
+1 Évitez de visiter le même état dans un épisode (renforcer)
·référence (Papier) Ne jamais abandonner: Apprendre les stratégies d'exploration dirigée [Ne jamais abandonner! Atari Renforcer l'apprentissage de la recherche sans abandonner même dans des environnements difficiles qui mène à une domination complète!](Https://ai-scholar.tech/articles/reinforcement-learning/never-give-up-ai- 394)
NGU définit les récompenses en ajoutant des récompenses internes (récompenses intrinsèques) à des récompenses externes (récompenses extrinsèques).
Où $ r ^ e_t $ est la récompense externe, $ r ^ i_t $ est la récompense interne et $ \ beta $ est la constante qui pondère la récompense interne. Ensuite, nous nous entraînerons en utilisant $ r_ {t} $ (récompense étendue) qui est la somme de ceux-ci.
Regardons les récompenses internes. (La figure est tirée du papier, et cette figure est appelée figure A ci-après)
Les récompenses internes sont créées à partir du module de nouveauté à vie (cadre vert sur le côté droit de la figure A) et de la mémoire d'épisode (cadre rouge sur le côté droit de la figure A).
Générez une valeur de $ \ alpha_t $ à partir du stockage à vie et $ r ^ {épisode} _t $ à partir du stockage des épisodes, et synthétisez-les comme suit.
Écrit en japonais, récompense interne = mémoire d'épisode x mémoire à vie.
Commençons par la section de la mémoire des épisodes.
Dans le département de la mémoire des épisodes, la récompense est décidée afin que le même état ne soit pas visité dans un épisode. Le flux global est le suivant. (Correspond au cadre rouge de la Fig. A)
La fonction intégrée et la valeur approximative du nombre de visites seront décrites plus loin. La mémoire des épisodes est initialisée au début d'un épisode. Cela semble déterminer le nombre de visites dans un épisode.
Les fonctions intégrées sont des fonctions de réseau neuronal qui génèrent des états contrôlables.
Cela ressemble à un simple réseau de neurones qui compresse simplement l'état actuel en p dimension. Le problème est l'apprentissage, qui est assimilé au réseau siamois comme suit.
(Cette figure est une figure détaillée sur le côté gauche de la figure A)
L'entrée est l'état précédent et l'état actuel, et la sortie est la probabilité que chaque action soit sélectionnée. En bref, c'est un réseau qui apprend quelle action a été effectuée à partir de la différence entre l'état précédent et l'état actuel.
Il semble que ce réseau n'apprenne que les états qui changent en relation avec le comportement.
Référence: [Apprentissage à distance] Explication approfondie du réseau siamois et de la perte de contraste
Le stockage de l'épisode ($ r ^ {épisode} _t $) est calculé en fonction du nombre de visites. Le nombre de visites est calculé en rapprochant la mémoire des épisodes et l'état actuel à l'aide de la méthode k-voisinage. Ce qui suit est une explication utilisant une formule.
Le stockage des épisodes ($ r ^ {épisode} _t $) est le suivant.
$ n (f (x_t)) $ est le nombre de visites. Le nombre de visites est estimé à l'aide de la fonction du noyau K et se présente comme suit.
c est une constante qui garantit un nombre minimum de pseudo visites. (c = 0,001) K est calculé par la méthode k-voisinage de l'état contrôlable en mémoire et de l'état contrôlable actuel.
$ \ Epsilon $ est une petite constante. ($ \ Epsilon $ = 0,001) d représente la distance euclidienne et $ d ^ 2_m $ représente la moyenne mobile de la distance euclidienne.
RND (Random Network Distillation) est utilisé pour la mémoire à vie.
·référence L'exploration par Random Network Distillation a été testée sur MountainCar. (Paper) Exploration by Random Network Distillation
Quant à l'explication du RND, quand on veut juger s'il s'agit d'un état inconnu dans un certain état, on compte généralement le nombre de visites et on pense que plus on a de visites, plus on connaît l'état. Cependant, RND a une idée de renversement. L'analogie du blog de référence était bonne, je vais donc l'utiliser, mais au RND, je préparerai d'abord une carte à gratter. Au début, la carte est recouverte de papier argenté, mais elle est progressivement grattée à chaque visite. RND est une méthode permettant de juger à quel point il est inconnu en regardant le degré de grattage.
Ensuite, comment réaliser cela est de préparer deux réseaux de neurones avec la même structure. (UN B) A quitte l'état initial et B apprend à approcher A. Cet apprentissage de B équivaut à l'acte de gratter du papier argenté. En conséquence, en comparant A et B, l'erreur est grande = l'endroit qui n'est pas recherché, et l'erreur est petite = l'endroit qui est bien recherché.
Revenons à la prémisse de l'apprentissage intensif. L'apprentissage Q est fondé sur un modèle probabiliste de MDP (processus de détermination de Markov). Pour faire simple, si vous effectuez une action dans un certain état, elle passera à un état aléatoire et vous recevrez une récompense fixe. (C'est un modèle général d'apprentissage par renforcement)
Cependant, dans NGU, des récompenses internes sont ajoutées, donc même si vous passez au même état, les récompenses changeront. Par conséquent, la NGU doit être considérée comme un modèle de POMDP (processus de détermination de Markov d'observation partielle), et non de MDP.
·référence [Processus décisionnel Markov (Wikipedia)](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%AB%E3%82%B3%E3%83%95%E6%B1% BA% E5% AE% 9A% E9% 81% 8E% E7% A8% 8B) [Processus de décision Markov d'observation partielle (Wikipedia)](https://ja.wikipedia.org/wiki/%E9%83%A8%E5%88%86%E8%A6%B3%E6%B8%AC%E3% 83% 9E% E3% 83% AB% E3% 82% B3% E3% 83% 95% E6% B1% BA% E5% AE% 9A% E9% 81% 8E% E7% A8% 8B)
Cependant, penser comme POMDP est beaucoup plus difficile que MDP, donc NGU a introduit deux solutions de contournement:
De plus, puisque l'action de recherche par la récompense interne est ajoutée directement à la récompense, l'action de recherche ne peut pas être facilement désactivée. Pour résoudre ce problème, NGU propose une méthode pour apprendre à la fois la récompense externe et le comportement exploratoire.
UVFA(Universal Value Function Approximators)
DQN estime généralement la valeur Q en prenant un certain état comme entrée. Ici, UVFA est une fonction de valeur qui généralise l'entrée en ajoutant non seulement l'état mais aussi l'objectif.
NGU utilise cet UVFA, mais au lieu de la cible, $ \ beta $ (taux de réflexion de récompense interne: taux de recherche) est entré. En faisant cela, nous proposons d'apprendre le comportement exploratoire en même temps. Si $ \ beta = 0 $, vous pouvez obtenir le résultat lorsque la recherche est désactivée, et si $ \ beta> 0 $, vous pouvez obtenir le résultat lorsque la recherche est activée.
·référence (Diapositive Deep Mind) Approximateurs de la fonction de valeur universelle (Papier) Approximateurs de la fonction de valeur universelle
Retrace
L'apprentissage Q utilise une méthode de recherche hors politique dans l'apprentissage TD. (À l'inverse, Sarsa est l'une des recherches sur la politique dans l'apprentissage TD.)
La différence est la référence à la valeur Q à mettre à jour, et dans le cas de hors politique, la politique n'est pas suivie. (Dans l'apprentissage Q, l'action avec la valeur Q maximale est sélectionnée) Dans le cas d'On-Policy, il est acquis conformément à la politique. (Par exemple, si vous effectuez une recherche avec ε-greedy, utilisez également ε-greedy comme destination de référence.)
Le problème avec Off-Policy est que la stratégie sur laquelle vous avez réellement agi (stratégie de comportement) et la stratégie que vous souhaitez apprendre (stratégie cible) sont différentes. Si cela est différent, les valeurs peuvent ne jamais converger (non sécurisé). Dans l'article de Retrace, il existe quatre méthodes pour résoudre ce problème (méthode existante 3). (2 + Retrace) est comparé et cela montre que Retrace est supérieur.
Pour faire simple, Retrace est une méthode de prédiction d'une stratégie basée sur les résultats passés et de contrôle de l'apprentissage par la différence. (Les coefficients utilisés pour contrôler l'apprentissage sont appelés coefficients de traces de coupe ($ c_s $))
NGU intègre Retrace.
·référence Renforcer l'apprentissage (10) que je n'entends plus: différence entre l'apprentissage Sarsa et Q Politique et non-politique de renforcement de l'apprentissage (Paper on Off-policy 1) Q (λ) with Off-Policy Corrections (Article 2 sur l'apprentissage hors politique) Apprentissage par différence temporelle hors politique avec approximation des fonctions (Deep Mind slide) Off-policy deep RL (Document de Retrace) Apprentissage sûr et efficace par renforcement hors politique (Diapositive japonaise du document Retrace) Apprentissage sûr et efficace du renforcement des politiques Bases de la théorie de l'apprentissage amélioré 2 [Review] UCL_RL Lecture05 Model Free Control
Le taux de remise ($ \ gamma $) dépend de $ \ beta $ (taux de réflexion de la récompense interne) et des changements. Si $ \ beta = 0 $, alors $ \ gamma = max $, et si $ \ beta = max $, alors $ \ gamma = min $. (Plus précisément, $ \ beta = 0 $ est $ \ gamma = 0.997 $, $ \ beta = max $ est $ \ gamma = 0.99 $)
Comme l'influence des récompenses externes est faible pendant l'exploration, il s'agit d'un taux d'actualisation pour l'ajustement.
Agent57
Nous avons pu réaliser une exploration efficace avec NGU, mais dans certains jeux, nous ne pouvions obtenir que le même score qu'une simple exploration aléatoire. En outre, l'un des inconvénients de NGU est qu'il recherche quel que soit le progrès de l'apprentissage.
Agent57 a proposé ce qui suit et les a améliorés.
(Paper) Agent57: Outperforming the Atari Human Benchmark
L'apprentissage pourrait être instable à NGU. Cela se produit lorsque les récompenses externes et internes ont des échelles différentes, ou lorsqu'une seule récompense réagit de manière excessive par rapport aux autres récompenses.
L'agent57 a émis l'hypothèse qu'il serait difficile d'apprendre la fonction de valeur comportementale lorsque la nature de la récompense était très différente entre les récompenses externes et internes, et a proposé un changement dans l'architecture de la fonction de valeur comportementale.
Plus précisément, la fonction de valeur d'action est définie dans $ Q (x, a, j; \ theta ^ e) $ pour l'apprentissage des récompenses externes et $ Q (x, a, j; \ theta ^ i) $ pour l'apprentissage des récompenses internes. Divisez et trouvez la valeur Q avec la formule suivante. (Il semble être basé sur l'opérateur Bellman transformé)
$ \ Beta_j $ est le taux de réflexion (taux de recherche) de la fonction de valeur interne, et h est la fonction d'opérateur de Belman?. h n'est pas très bien compris, mais il est identique à la fonction de remise à l'échelle de R2D2, et se présente comme suit.
NGU et Agent57 peuvent désormais définir le taux de recherche ($ \ beta_j $) à l'aide de récompenses internes.
Cependant, dans NGU, le taux de recherche était fixé pour chaque acteur. Par exemple, lorsque Actor a 4 ans, cela ressemble à ce qui suit. (La valeur est provisoire)
Acteur1: $ \ beta_j $ = 0 (pas de recherche) Acteur2: $ \ beta_j $ = 0,1 (recherche en quelque sorte) Acteur3: $ \ beta_j $ = 0,2 (chercher un peu) Acteur4: $ \ beta_j $ = 0.3 (recherche so-so)
Il est préférable d'utiliser une valeur élevée pour le taux de recherche au début de la formation, mais on s'attend à ce qu'il soit préférable d'utiliser une valeur faible à mesure que la formation progresse. Par conséquent, Agent57 a proposé un méta-contrôleur afin d'adopter une méthode de sélection d'un taux de recherche efficace.
Dans le méta-contrôleur, la sélection d'un taux de recherche efficace est assimilée à un problème de bandit multi-armé (problème MAB), dont la politique de recherche (acteur dans NGU) doit être sélectionnée pour une récompense maximale. Ceci est en train d'être résolu. (La récompense se réfère ici au total des récompenses externes non actualisées dans un épisode)
·référence Article que j'ai écrit plus tôt: [Renforcer l'apprentissage] Mettre en œuvre / expliquer et comparer plusieurs politiques de recherche (problème de bandit multi-armé) Théorie et algorithme du problème des bandits multi-armés Introduction au renforcement de l'apprentissage: problème de bandit multi-armé
Pour faire simple, le problème du MAB est le problème de la maximisation de la récompense lors de la sélection de plusieurs emplacements (bras) un certain nombre de fois. Par exemple, supposons que vous ayez 4 emplacements (A, B, C, D). Quelle est la meilleure façon de choisir le prix maximum après avoir choisi une machine à sous 100 fois? C'est le problème. Je ne connais pas la probabilité que les quatre machines à sous gagnent.
Dans un problème MAB général, la probabilité de gagner un prix est constante pour chaque créneau. (Cela ne change pas après la première décision) Cependant, avec Agent57, la probabilité d'obtenir une récompense (résultat de récompense) change. Par conséquent, le contrôleur méta est un peu conçu.
Agent57 utilise la méthode UCB comme algorithme pour les problèmes MAB. Cependant, comme la récompense change, la méthode UCB ne peut pas être appliquée telle quelle. Par conséquent, nous proposons de n'utiliser la méthode UCB que pour les derniers épisodes. C'est ce qu'on appelle dans l'article la méthode UCB à fenêtre coulissante. C'est la même chose que la méthode UCB sauf que vous ne voyez que les derniers épisodes.
Il est nécessaire de créer un réseau neuronal spécial dans lequel la structure du réseau au moment de l'apprentissage et la structure du réseau au moment de l'utilisation sont différentes. La première est la fonction intégrée pour l'acquisition de valeur.
Il n'y a aucune mention de la couche de traitement d'image dans le papier, et c'est le terme utilisé dans cet article. (Parce que le papier est basé sur l'entrée d'image)
Vient ensuite la fonction intégrée d'apprentissage.
Le code qui implémente la figure ci-dessus est le suivant.
input_sequence =Nombre de trames d'entrée
input_shape =Format d'entrée
nb_actions =Nombre d'actions
Fonction intégrée pour l'acquisition de valeur
c = input_ = Input(shape=(input_sequence,) + input_shape)
c = Conv2D(32, (8, 8), strides=(4, 4), padding="same", name="l0")(c)
c = Conv2D(64, (4, 4), strides=(2, 2), padding="same", name="l1")(c)
c = Conv2D(64, (3, 3), strides=(1, 1), padding="same", name="l2")(c)
c = Dense(32, activation="relu", name="l3")(c)
emb_model = Model(input_, c)
Fonction intégrée pour la formation
#Faire deux entrées
c1 = input1 = Input(shape=(input_sequence,) + input_shape)
c2 = input2 = Input(shape=(input_sequence,) + input_shape)
#Créez un réseau tout en partageant des poids
l = Conv2D(32, (8, 8), strides=(4, 4), padding="same", name="l0")
c1 = l(c1)
c2 = l(c2)
l = Conv2D(32, (4, 4), strides=(2, 2), padding="same", name="l1")
c1 = l(c1)
c2 = l(c2)
l = Conv2D(64, (3, 3), strides=(1, 1), padding="same", name="l2")
c1 = l(c1)
c2 = l(c2)
l = Dense(32, activation="relu", name="l3")
c1 = l(c1)
c2 = l(c2)
#Joindre
c = Concatenate()([c1, c2])
c = Dense(128, activation="relu")(c)
c = Dense(nb_actions, activation="softmax")(c)
emb_train_model = Model([input1, input2], c)
#optimiseur du papier
model.compile(
loss='mean_squared_error',
optimizer=Adam(lr=0.0005, epsilon=0.0001))
Bien qu'il s'agisse d'une fonction de perte, il n'y avait qu'une description dans l'article selon laquelle elle a été apprise par la méthode d'estimation la plus probable. (Peut-être…) Donc, pour le moment, l'erreur quadratique moyenne est utilisée.
·référence Technique TPU de Keras dans le noir: Comment transférer les coefficients d'un modèle à deux entrées et d'un modèle à une entrée l'un à l'autre Modèle multi-entrées multi-sorties (officiel Keras)
Vient ensuite le code qui copie les poids de emb_train_model vers emb_model.
def sync_embedding_model():
for i in range(4): #couche Tourner pendant quelques minutes
train_layer = emb_train_model.get_layer("l" + str(i))
val_layer = emb_model.get_layer("l" + str(i))
#Copier le poids
val_layer.set_weights(train_layer.get_weights())
Nous avons créé un excellent modèle avec des entrées disjointes et des poids partagés. .. ..
Il semble que ce soit à peine écrit dans le papier ... Pour le moment, l'intervalle de mise à jour de la cible Embeddings est écrit une fois par épisode. Qu'est-ce qu'une cible Embeddings ...
Pour le moment, la méthode d'apprentissage a été exécutée en utilisant le même exemple que l'apprentissage de la fonction de valeur d'action, et la synchronisation avec emb_train_model → emb_model a été définie sur une fois par épisode.
batch_size =Taille du lot
def forward(observation):
#Moment de l'apprentissage de chaque image
#Acquérir de l'expérience de manière aléatoire pour un lot à partir de la mémoire d'expérience
batchs = memory.sample(batch_size)
#Formater les données
state0_batch = [] #État précédent
state1_batch = [] #État suivant
emb_act_batch = []
for batch in batchs:
state0_batch.append(batchs["État précédent"])
state1_batch.append(batchs["État suivant"])
#L'action est une-Créer des données en tant que vecteur chaud
a = np_utils.to_categorical(
batchs["action"],
num_classes=nb_actions
)
emb_act_batch.append(a)
#entraînement
emb_train_model.train_on_batch(
[state0_batch, state1_batch], #Il y a deux entrées, l'état précédent et l'état suivant
emb_act_batch #L'enseignant est l'action
)
def backward(self, reward, terminal):
if terminal:
#Synchroniser à la fin de l'épisode
sync_embedding_model()
* Omettre numpy
Vous obtenez juste la valeur de emb_model.
state =État actuel
cont_state = emb_model.predict([state], batch_size=1)[0]
* Omettre numpy
Heureusement, le pseudo code a été écrit dans le papier pour le calcul ici. C'est comme suit lorsqu'il est exprimé par un pseudo-code de type python.
def calc_int_episode_reward(():
state =État actuel
k =Nombre dans la méthode k-voisinage(k=10)
epsilon = 0.001
c = 0.001
cluster_distance = 0.008
maximum_similarity = 8
#Obtenez un état contrôlable à partir de la fonction intégrée
cont_state = embedding_network.predict(state, batch_size=1)[0]
#Trouver tous les éléments dans la mémoire des épisodes et la distance euclidienne
euclidean_list = []
for mem_cont_state in int_episodic_memory:
euclidean = np.linalg.norm(mem_cont_state - cont_state)
euclidean_list.append(euclidean)
#Haut k
euclidean_list.sort()
euclidean_list = euclidean_list[:k]
#Distance euclidienne au carré
euclidean_list = np.asarray(euclidean_list) ** 2
#Obtenez la moyenne
ave = np.average(euclidean_list)
#Approximer le nombre de visites(Calcul de Σ dans la formule)
count = 0
for euclidean in euclidean_list:
d = euclidean / ave
#Il n'y a pas d'explication dans l'article, mais c'est écrit dans le pseudo code ...
#Une certaine distance se résume-t-elle à la distance la plus courte?
d -= cluster_distance
if d < euclidean_list[0]:
d = euclidean_list[0]
count += epsilon / (d+epsilon)
s = np.sqrt(count) + c
#Il n'y a aucune explication dans l'article ici non plus, mais certaines petites valeurs sont-elles arrondies à 0?
if s > maximum_similarity:
episode_reward = 0
else:
episode_reward = 1/s
#Ajout d'un état contrôlable à la mémoire des épisodes, pas dans le pseudo code du papier
int_episodic_memory.append(cont_state)
if len(int_episodic_memory) >= 30000:
int_episodic_memory.pop(0)
return episode_reward
Le modèle de RND est le suivant.
La sortie ne signifie pas grand-chose. Le code lorsqu'il existe une couche de traitement d'image est le suivant.
def build_rnd_model():
#Couche d'entrée
c = input = Input(shape=(input_sequence,) + input_shape)
#Couche de traitement d'image
c = Conv2D(32, (8, 8), strides=(4, 4), padding="same")(c)
c = Conv2D(64, (4, 4), strides=(2, 2), padding="same")(c)
c = Conv2D(64, (3, 3), strides=(1, 1), padding="same")(c)
# Dense
c = Dense(128)(c)
model = Model(input, c)
#perte, optimiseur du papier
model.compile(
loss='mean_squared_error',
optimizer=Adam(lr=0.0005, epsilon=0.0001))
return model
# train_le modèle est la cible_C'est un modèle proche de l'image
rnd_target_model = build_rnd_model()
rnd_train_model = build_rnd_model()
Je pense que c'est aussi rarement écrit dans le journal ... Il utilise le même exemple que l'apprentissage de la fonction de valeur d'action ainsi que de la fonction intégrée. (Je l'ai utilisé pour apprendre = je l'ai visité (mais c'est peut-être un peu suspect ...))
def forward(observation):
#Moment de l'apprentissage de chaque image
#Acquérir de l'expérience de manière aléatoire pour un lot à partir de la mémoire d'expérience
batchs = memory.sample(batch_size)
#Formater les données
state0_batch = [] #État précédent
state1_batch = [] #État suivant
for batch in batchs:
state0_batch.append(batchs["État précédent"])
state1_batch.append(batchs["État suivant"])
#Obtenez la valeur de la cible
rnd_target_val = rnd_target_model.predict(state1_batch, batch_size)
#entraînement
rnd_train_model.train_on_batch(state1_batch, rnd_target_val)
* Omettre numpy
En ce qui concerne la formule de calcul du stockage à vie, tout d'abord, l'erreur carrée de rnd_target_model et rnd_train_model est calculée.
Sur cette base, la section de mémoire à vie est calculée à l'aide de la formule suivante.
Où $ \ sigma_e $ est l'écart type de $ err (x_t) $ et $ \ mu_e $ est la moyenne de $ err (x_t) $.
L'écart type et la moyenne sont sortis ... Il n'y a pas de description dans l'article sur la façon de le calculer, mais pour le calculer, vous devez enregistrer les résultats antérieurs. Pour le moment, j'ai créé un tableau pour stocker $ err (x_t) $. Cependant, je fais une limite supérieure parce que ce sera un problème si elle est ajoutée à l'infini.
Ci-dessous le code.
#---Variables de calcul
rnd_err_vals = []
rnd_err_capacity = 10_000
#---Partie calcul
def calc_int_lifelong_reward():
state =État actuel
#Obtenez RND
rnd_target_val = rnd_target_model.predict(state, batch_size=1)[0]
rnd_train_val = rnd_train_model.predict(state, batch_size=1)[0]
#Donnez une erreur carrée
mse = np.square(rnd_target_val - rnd_train_val).mean()
rnd_err_vals.append(mse)
if len(rnd_err_vals) > rnd_err_capacity:
rnd_err_vals.pop(0)
#écart-type
sd = np.std(rnd_err_vals)
if sd == 0:
return 1
#moyenne
ave = np.average(rnd_err_vals)
# life long reward
lifelong_reward = 1 + (mse - ave)/sd
return lifelong_reward
La récompense interne est la formule suivante.
L = 5
episode_reward =Mémoire d'épisode
lifelong_reward =Département de la mémoire à vie
if lifelong_reward < 1:
lifelong_reward = 1
if lifelong_reward > L:
lifelong_reward = L
intrinsic_reward = episode_reward * lifelong_reward
La politique de recherche est représentée par une paire de taux de recherche (β) et de taux d'actualisation ($ \ gamma $) et est calculée par la formule suivante. Le taux d'actualisation est calculé différemment pour NGU et Agent57. (Je vais laisser les deux pour le moment)
La première est la formule de calcul du taux de recherche.
\beta_i = \left\{
\begin{array}{ll}
0 \qquad (i = 0) \\
\beta \qquad (i = N-1) \\
\bêta ・\sigma(10\frac{2i-(N-2)}{N-2}) \quad (otherwise)
\end{array}
\right.
$ \ Sigma $ est la fonction sigmoïde et $ \ beta $ est le taux de réflexion maximum.
def sigmoid(x, a=1):
return 1 / (1 + np.exp(-a * x))
def create_beta_list(N, max_beta=0.3):
beta_list = []
for i in range(N):
if i == 0:
b = 0
elif i == N-1:
b = max_beta
else:
b = 10 * (2*i-(N-2)) / (N-2)
b = max_beta * sigmoid(b)
beta_list.append(b)
return beta_list
Taux d'actualisation NGU.
def create_gamma_list_ngu(N, gamma_min=0.99, gamma_max=0.997):
if N == 1:
return [gamma_min]
if N == 2:
return [gamma_min, gamma_max]
gamma_list = []
for i in range(N):
g = (N - 1 - i)*np.log(1 - gamma_max) + i*np.log(1 - gamma_min)
g /= N - 1
g = 1 - np.exp(g)
gamma_list.append(g)
return gamma_list
Taux d'actualisation Agent57.
\gamma_j = \left\{
\begin{array}{ll}
\gamma0 \qquad (j=0) \\
\gamma1 + (\gamma0 - \gamma1)\sigma(10 \frac{2i-6}{6} ) \qquad (j \in (1,...,6)) \\
\gamma1 \qquad (j=7) \\
1-exp(\frac{(N-9)log(1-\gamma1) + (j-8)log(1-\gamma2)}{N-9}) \quad (otherwise)
\end{array}
\right.
def create_gamma_list_agent57(N, gamma0=0.9999, gamma1=0.997, gamma2=0.99):
gamma_list = []
for i in range(N):
if i == 1:
g = gamma0
elif 2 <= i and i <= 6:
g = 10*((2*i-6)/6)
g = gamma1 + (gamma0 - gamma1)*sigmoid(g)
elif i == 7:
g = gamma1
else:
g = (N-9)*np.log(1-gamma1) + (i-8)*np.log(1-gamma2)
g /= N-9
g = 1-np.exp(g)
gamma_list.append(g)
return gamma_list
Je soupçonne de comprendre ici ...
La figure ci-dessous est un modèle de la fonction de valeur comportementale de l'agent 57.
En bas à droite se trouve la description de [Action, Récompense externe, Récompense interne, Taux de recherche]. Cependant, il ne dit pas comment ajouter cela ...
Pour le moment, le taux de recherche est ajouté en tant que vecteur ohe-hot uniquement à la fonction de valeur d'action de la récompense interne comme indiqué ci-dessous. (Si vous saisissez la récompense interne ou externe telle quelle, vous n'apprendrez pas ...)
Ci-dessous le code. Seule la fonction de valeur d'action pour la récompense interne est décrite. (La partie avec le commentaire (UVFA) est la partie modifiée par UVFA)
from keras.utils import to_categorical
#Où créer un modèle pour la fonction Q
def build_actval_int_model():
#Couche d'entrée
c1 = input1 = Input(shape=(input_sequence,) + input_shape)
c2 = input1 = Input(shape=(policy_num,)) # (UVFA)ajouter à
#Couche de traitement d'image
c1 = Conv2D(32, (8, 8), strides=(4, 4), padding="same")(c1)
c1 = Conv2D(64, (4, 4), strides=(2, 2), padding="same")(c1)
c1 = Conv2D(64, (3, 3), strides=(1, 1), padding="same")(c1)
c = Concatenate()([c1, c2]) # (UVFA)ajouter à
# lstm
c = LSTM(512)(c)
# dueling network
c =Créer un modèle pour Dueling Network(c)
model = Model([input1, input2], c) # (UVFA)Changement
model.compile(loss=clipped_error_loss, optimizer=Adam(lr=0.0001, epsilon=0.0001))
return model
#Créer un modèle
actval_int_model = build_actval_int_model()
actval_int_model_target = build_actval_int_model()
#Chaque image
def forward(observation):
#Obtenir des données de lot
batchs = memory.sample()
#Formater les données
state0_batch = []
state1_batch = []
policy_batch = []
for batch in batchs:
state0_batch.append(batchs["État précédent"])
state1_batch.append(batchs["État suivant"])
#Première politique de découverte-chaud
t = to_categorical(batchs["Politique de découverte"], num_classes=policy_num)
policy_batch.append(t)
#L'entrée est la politique d'état et de découverte
state0_batch = [state0_batch, policy_batch]
state1_batch = [state1_batch, policy_batch]
#Exemple de définition de la valeur Q
state0_qvals = actval_int_model.predict(state0_batch, batch_size)
(State0 pour mise à jour_Calcul des qvals)
#Apprentissage
actval_int_model.train_on_batch(state0_batch, state0_qvals)
Le calcul de la valeur Q dans NGU est omis car il n'est plus dû à la division de la fonction de valeur d'action de l'Agent57. La formule de calcul de la valeur Q dans Agent57 est la suivante, qui est une combinaison de récompenses internes et externes.
def rescaling(x, epsilon=0.001):
if x == 0:
return 0
n = math.sqrt(abs(x)+1) - 1
return np.sign(x)*n + epsilon*x
def rescaling_inverse(x, epsilon=0.001):
if x == 0:
return 0
n = math.sqrt(1 + 4*epsilon*(abs(x)+1+epsilon)) - 1
return np.sign(x)*( n/(2*epsilon) - 1)
def get_qvals():
state =État actuel
policy_index =Politique de découverte
#Obtenez une valeur Q externe
qvals_ext = avtval_ext_model.predict(state, batch_size=1)[0]
#Première politique de découverte-hot
policy_onehot = to_categorical(policy_index, num_classes=policy_num)
#Obtenez la valeur Q interne
qvals_int = avtval_int_model.predict([state, policy_onehot], batch_size=1)[0]
#Taux de recherche
beta = int_beta_list[policy_index]
#Calculer la valeur Q
qvals = []
for i in range(nb_actions):
q_ext = rescaling_inverse(qvals_ext[i])
q_int = rescaling_inverse(qvals_int[i])
qval = rescaling(q_ext + beta * q_int)
qvals.append(qvals)
return qvals
Retrace
Comme je l'ai dit plus tôt, l'implémentation de Retrace est en attente (je ne comprends pas le contenu ...) Je décrirai les contenus que je ne comprends pas.
La fonction Retrace est:
$ \ pi $ est la politique cible et $ \ mu $ est la distribution de probabilité pour chaque action de la politique de comportement.
Cependant, dans DQN, la politique de recherche est complètement gourmande (ne sélectionnez que la valeur Q maximale), donc j'estime que la distribution de probabilité est de 1 pour l'action avec la valeur Q maximale et de 0 pour les autres. Dans ce cas, la molécule ne prendra que 0 ou 1, donc j'ai l'impression qu'elle sera toujours 0, mais ... orz
La politique de comportement sera probablement ε-gourmande, donc je pense que ce sera comme suit (?)
\mu(\alpha|s) = \left\{
\begin{array}{ll}
\epsilon/N + 1 - \epsilon \quad (argmax_{\alpha \in A} Q(s, \alpha)) \\
\epsilon/N \quad (otherwise)
\end{array}
\right.
Où N est le nombre d'actions.
Je n'ai pas complètement expliqué les détails tels que l'environnement LSTM, les files d'attente et le traitement parallèle. .. .. Le code source est ouvert au public, veuillez donc vérifier les détails ici.
Avec cela, je sens que j'ai atteint un objectif en tant qu'algorithme d'apprentissage par renforcement, mais je pense qu'il y a encore place à l'amélioration. Ce que je souhaite que vous amélioriez le plus, ce sont les spécifications requises. C'est le cas depuis R2D2, mais le nombre d'acteurs dans l'article est de 512. Mon PC a une limite de 2 et au plus 4 ... (bien qu'il puisse n'avoir qu'un seul processeur) J'attends avec impatience la prochaine nouvelle méthode.
Recommended Posts