Je lance un programme d'apprentissage par renforcement dans un environnement de gym (BipedalWalker-v2) implémenté dans tensorflow. J'ai défini manuellement la graine aléatoire de l'environnement, tensorflow et numpy comme suit
os.environ['PYTHONHASHSEED']=str(42) random.seed(42) np.random.seed(42) tf.set_random_seed(42) env = gym.make('BipedalWalker-v2') env.seed(0) config = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1) config.gpu_options.allow_growth = True sess = tf.Session(config=config) # run the graph with sess
Cependant, j'obtiens des résultats différents chaque fois que j'exécute mon programme (sans changer de code). Pourquoi les résultats ne sont-ils pas cohérents et que dois-je faire si je veux obtenir le même résultat?
Les seuls endroits auxquels je peux penser peuvent introduire un caractère aléatoire (autres que les réseaux de neurones) sont
tf.truncated_normal
pour générer du bruit aléatoire epsilon
afin d'implémenter la couche bruyante np.random.uniform
pour sélectionner au hasard des échantillons dans la mémoire tampon de relecture Je remarque également que les scores que j'obtiens sont assez cohérents dans les 10 premiers épisodes, mais commencent ensuite à différer. D'autres choses telles que les pertes montrent également une tendance similaire mais ne sont pas les mêmes en numérique.
J'ai également défini "PYTHONHASHSEED" et utilise un processeur à thread unique comme @ jaypops96 décrit, mais ne peut toujours pas reproduire le résultat. Le code a été mis à jour dans le bloc de code ci-dessus
3 Réponses :
Il semble que les réseaux de neurones tensorflow introduisent un caractère aléatoire pendant l'entraînement qui n'est pas contrôlé par une graine aléatoire numpy. Le caractère aléatoire semble provenir au moins d'opérations de hachage python et d'opérations parallélisées s'exécutant dans un ordre non contrôlé.
J'ai réussi à obtenir une reproductibilité à 100% en utilisant un NN keras-tensorflow, en suivant les étapes de configuration de cette réponse: Comment obtenir des résultats reproductibles dans les keras
plus précisément, j'ai utilisé la formulation proposée par @Poete Maudit dans ce lien.
Leur clé était de définir des valeurs de départ aléatoires UP FRONT, pour numpy, python et tensorflow, puis aussi de faire fonctionner tensorflow sur un processeur à un seul thread dans une session spécialement configurée.
Voici le code que j'ai utilisé, mis à jour très légèrement à partir du lien que j'ai publié.
print('Running in 1-thread CPU mode for fully reproducible results training a CNN and generating numpy randomness. This mode may be slow...') # Seed value # Apparently you may use different seed values at each stage seed_value= 1 # 1. Set `PYTHONHASHSEED` environment variable at a fixed value import os os.environ['PYTHONHASHSEED']=str(seed_value) seed_value += 1 # 2. Set `python` built-in pseudo-random generator at a fixed value import random random.seed(seed_value) seed_value += 1 # 3. Set `numpy` pseudo-random generator at a fixed value import numpy as np np.random.seed(seed_value) seed_value += 1 # 4. Set `tensorflow` pseudo-random generator at a fixed value import tensorflow as tf tf.set_random_seed(seed_value) # 5. Configure a new global `tensorflow` session session_conf = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1) sess = tf.Session(graph=tf.get_default_graph(), config=session_conf) tf.keras.backend.set_session(sess) #rest of code...
Merci pour votre réponse :-). J'ai fait la configuration exacte comme vous l'avez décrit, sauf que je n'utilise pas de keras. Cependant, je ne peux toujours pas reproduire le même résultat.
Eh bien, cela peut être un peu différent puisque vous utilisez uniquement TF et non Keras, mais quelques notes: (1) essayez de définir les graines aléatoires avant de faire TOUT autre chose dans le code, et assurez-vous de les définir dans l'ordre exact que je spécifié. @Poete Maudit a souligné qu'il était important de les faire d'abord et dans cet ordre exact. (2) il semble que votre code n'ait pas d'analogue à ma ligne "tf.keras.backend.set_session (sess)" - vous configurez la session mais ne configurez jamais le backend tensorflow pour utiliser cette session. essayer de trouver quelque chose de comparable à ma ligne dans la documentation tensorflow?
Merci. J'ai réorganisé mon code pour qu'il soit cohérent avec le vôtre, mais je trouve toujours des résultats différents. Au fait, j'écris mon code dans tensorflow donc j'utilise la session pour exécuter le graphe tensorflow directement au lieu de l'utiliser comme sauvegarde
Hmm alors je suis peut-être à court d'idées. Vous exécutez le code que j'ai publié comme toute première chose dans votre script? comme, avant toute autre importation ou quoi que ce soit? D'autres personnes postant ont souligné que ces graines doivent être définies avant que TOUT autre ne se produise dans votre code. peut-être même devrait-il se produire lorsque vous démarrez la session d'interprétation si vous utilisez l'interpréteur ...? Juste une dernière pensée.
Peut-être pouvez-vous essayer de régler le nombre de threads de parallélisme à 1. J'ai le même problème: la perte est devenue différente à la septième décimale à partir du deuxième épisode. Cela a été corrigé lorsque j'ai défini
tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
Je suggère de vérifier si votre graphe TensorFlow contient des opérations non déterministes. Par exemple, reduction_sum
avant TensorFlow 1.2 était l'une de ces opérations. Ces opérations ne sont pas déterministes car l'addition et la multiplication en virgule flottante sont non associatives (l'ordre dans lequel les nombres à virgule flottante sont ajoutés ou multipliés affecte le résultat) et parce que ces opérations ne garantissent pas que leurs entrées sont ajoutées ou multipliées dans le même ordre à chaque fois . Voir également cette question . P >
EDIT (20 septembre 2020): Le référentiel GitHub framework-determinism code >
contient plus d'informations sur les sources de non-déterminisme dans les frameworks d'apprentissage automatique, en particulier TensorFlow.
Utilisez-vous
env.action_space.sample
ou quelque chose de similaire n'importe où? Cela pourrait le faire. De plus, si votre agent utilise un caractère aléatoire dans son graphique (ce qui n'est pas rare, pour rendre l'agent plus robuste), vous obtiendrez des résultats variables.@aedificatori Merci pour votre suggestion, j'ai vérifié mon code et mis à jour la question. Je commence à conjecturer s'il s'agit de la perte de précision ou de quelque chose de similaire?
Bien que l'apprentissage par renforcement puisse être quelque peu ridicule lorsqu'il s'agit de naviguer dans sa variété d'erreurs, la perte de précision est probablement encore trop petite pour être un problème (peut-être de quelques ordres de grandeur, à moins que vous n'ayez des erreurs d'arrondi ou de virgule flottante, que vous 'reconnaîtrais probablement d'emblée). Je pourrais vous recommander de tester Tensorflow et Numpy individuellement pour vous assurer que vos graines sont utilisées correctement. Donc, pour Numpy, à quelques endroits de votre programme, imprimez simplement un nombre aléatoire. Pour Tensorflow, même chose, mais vous devrez l'extraire de votre graphique si vous n'utilisez pas EagerExecution.
Vous devez ajouter une valeur de départ constante à toutes les opérations qui acceptent la valeur de départ comme argument, comme
tf.nn.dropout
,tf.contrib.layers.xavier_initializer
, etc. Il semble quetf.set_random_seed
ne fasse pas correctement son travail.Je suggère de vérifier si votre graphique TensorFlow contient des opérations non déterministes. Notamment,
reduction_sum
est l'une de ces opérations. Ces opérations ne sont pas déterministes car l'addition et la multiplication en virgule flottante sont non associatives (l'ordre dans lequel les nombres à virgule flottante sont ajoutés ou multipliés affecte le résultat) et parce que ces opérations ne garantissent pas que leurs entrées sont ajoutées ou multipliées dans le même ordre à chaque fois . Je ne connais pas une liste complète des opérations TensorFlow non déterministes.@PeterO, merci de partager ces informations précieuses!
Ce message est lié et plusieurs réponses valent la peine en train de lire.