[PYTHON] Correction de la graine aléatoire avec TensorFlow

Grosso modo

Contexte

Lors de l'implémentation du code d'apprentissage automatique dans TensorFlow, nous utilisons souvent des nombres pseudo-aléatoires (ci-après simplement «nombres aléatoires») pour l'initialisation du poids et ainsi de suite. Par conséquent, le résultat change à chaque fois que le code est ré-exécuté et il n'est pas possible de faire la distinction entre le changement du résultat dû à des changements de données et de paramètres et le changement de résultat dû à des nombres aléatoires. Les nombres aléatoires sont générés sur la base d'une valeur appelée "graine", qui, sauf indication contraire, utilise une valeur par défaut quelque peu variable (souvent une heure ou un ID de processus). TensorFlow fournit également un moyen de corriger la graine aléatoire, mais j'étais un peu inquiet pour son comportement, alors j'ai essayé de l'organiser.

En plus de TensorFlow, nous discuterons également de la correction des graines aléatoires dans le module random et le package NumPy.

version

Le contenu de cet article est basé sur les versions suivantes:

module aléatoire

Dans le module standard Python random, vous pouvez définir la graine aléatoire avec la fonction random.seed. Le code expérimental est le suivant.

seed_random.py


import random
random.seed(0)
print("1:", random.random())
print("2:", random.random())
print("3:", random.random())
random.seed(0)
print("4:", random.random())
print("5:", random.random())
print("6:", random.random())

Le résultat lors de l'exécution 3 fois est le suivant. La même valeur est sortie chaque fois qu'une graine de nombre aléatoire est définie ou exécutée.

$ python3 seed_random.py
1: 0.8444218515250481
2: 0.7579544029403025
3: 0.420571580830845
4: 0.8444218515250481
5: 0.7579544029403025
6: 0.420571580830845
$ python3 seed_random.py
1: 0.8444218515250481
2: 0.7579544029403025
3: 0.420571580830845
4: 0.8444218515250481
5: 0.7579544029403025
6: 0.420571580830845
$ python3 seed_random.py
1: 0.8444218515250481
2: 0.7579544029403025
3: 0.420571580830845
4: 0.8444218515250481
5: 0.7579544029403025
6: 0.420571580830845

Forfait NumPy

Dans le package NumPy, vous pouvez définir la graine aléatoire avec la fonction numpy.random.seed. Le code expérimental est le suivant.

seed_numpy.py


import numpy as np
np.random.seed(0)
print("1:", np.random.rand(3))
print("2:", np.random.rand(3))
print("3:", np.random.rand(3))
np.random.seed(0)
print("4:", np.random.rand(3))
print("5:", np.random.rand(3))
print("6:", np.random.rand(3))

Le résultat lors de l'exécution 3 fois est le suivant. La même valeur est sortie chaque fois qu'une graine de nombre aléatoire est définie ou exécutée.

$ python3 seed_numpy.py
1: [ 0.5488135   0.71518937  0.60276338]
2: [ 0.54488318  0.4236548   0.64589411]
3: [ 0.43758721  0.891773    0.96366276]
4: [ 0.5488135   0.71518937  0.60276338]
5: [ 0.54488318  0.4236548   0.64589411]
6: [ 0.43758721  0.891773    0.96366276]
$ python3 seed_numpy.py
1: [ 0.5488135   0.71518937  0.60276338]
2: [ 0.54488318  0.4236548   0.64589411]
3: [ 0.43758721  0.891773    0.96366276]
4: [ 0.5488135   0.71518937  0.60276338]
5: [ 0.54488318  0.4236548   0.64589411]
6: [ 0.43758721  0.891773    0.96366276]
$ python3 seed_numpy.py
1: [ 0.5488135   0.71518937  0.60276338]
2: [ 0.54488318  0.4236548   0.64589411]
3: [ 0.43758721  0.891773    0.96366276]
4: [ 0.5488135   0.71518937  0.60276338]
5: [ 0.54488318  0.4236548   0.64589411]
6: [ 0.43758721  0.891773    0.96366276]

Package TensorFlow

Dans le package TensorFlow, vous pouvez définir la graine aléatoire avec la fonction tensorflow.set_random_seed ou l'argument seed de l'opérateur aléatoire. Il existe deux types de graines aléatoires dans TensorFlow appelés «niveau graphique» et «niveau opération». Vous devez également faire attention à l'ordre des paramètres, et vous devez définir les valeurs aléatoires "après avoir créé le graphique" et "avant de générer l'opérateur".

Référence: Constantes, séquences et valeurs aléatoires --tf.set_random_seed (seed)

Un exemple qui fonctionne comme prévu

Le code expérimental est le suivant.

seed_tensorflow1.py


import tensorflow as tf
with tf.Graph().as_default():
    tf.set_random_seed(0)
    rand_op1 = tf.random_normal([3])
    rand_op2 = tf.random_normal([3], seed=1)
    print("session1")
    with tf.Session() as sess1:
        print("op1-1:", sess1.run(rand_op1))
        print("op1-2:", sess1.run(rand_op1))
        print("op2-1:", sess1.run(rand_op2))
        print("op2-2:", sess1.run(rand_op2))
    print("session2")
    with tf.Session() as sess2:
        print("op1-1:", sess2.run(rand_op1))
        print("op1-2:", sess2.run(rand_op1))
        print("op2-1:", sess2.run(rand_op2))
        print("op2-2:", sess2.run(rand_op2))

Le résultat lors de l'exécution 3 fois est le suivant.

$ python3 seed_tensorflow1.py
session1
op1-1: [-1.40955448 -0.53668278 -0.56523788]
op1-2: [-1.07107699  0.4139019   2.29180121]
op2-1: [ 0.68034536  0.8777824  -0.64773595]
op2-2: [-1.21607268  0.95542693 -0.16866584]
session2
op1-1: [-1.40955448 -0.53668278 -0.56523788]
op1-2: [-1.07107699  0.4139019   2.29180121]
op2-1: [ 0.68034536  0.8777824  -0.64773595]
op2-2: [-1.21607268  0.95542693 -0.16866584]
$ python3 seed_tensorflow1.py
session1
op1-1: [-1.40955448 -0.53668278 -0.56523788]
op1-2: [-1.07107699  0.4139019   2.29180121]
op2-1: [ 0.68034536  0.8777824  -0.64773595]
op2-2: [-1.21607268  0.95542693 -0.16866584]
session2
op1-1: [-1.40955448 -0.53668278 -0.56523788]
op1-2: [-1.07107699  0.4139019   2.29180121]
op2-1: [ 0.68034536  0.8777824  -0.64773595]
op2-2: [-1.21607268  0.95542693 -0.16866584]
$ python3 seed_tensorflow1.py
session1
op1-1: [-1.40955448 -0.53668278 -0.56523788]
op1-2: [-1.07107699  0.4139019   2.29180121]
op2-1: [ 0.68034536  0.8777824  -0.64773595]
op2-2: [-1.21607268  0.95542693 -0.16866584]
session2
op1-1: [-1.40955448 -0.53668278 -0.56523788]
op1-2: [-1.07107699  0.4139019   2.29180121]
op2-1: [ 0.68034536  0.8777824  -0.64773595]
op2-2: [-1.21607268  0.95542693 -0.16866584]

Ne fonctionne pas comme prévu Exemple 1: définir une valeur de départ aléatoire avant de créer un graphique

Voici un exemple de définition d'une graine aléatoire avant de créer un graphique. Le code expérimental est le suivant.

seed_tensorflow2.py


import tensorflow as tf
tf.set_random_seed(0) #Définir une graine aléatoire avant de créer un graphique
with tf.Graph().as_default():
    rand_op1 = tf.random_normal([3])
    rand_op2 = tf.random_normal([3], seed=1)
    with tf.Session() as sess1:
        print("op1-1:", sess1.run(rand_op1))
        print("op1-2:", sess1.run(rand_op1))
        print("op2-1:", sess1.run(rand_op2))
        print("op2-2:", sess1.run(rand_op2))

Le résultat lors de l'exécution 3 fois est le suivant. Rand_op2, qui définit la graine de nombre aléatoire au niveau de l'opération, renvoie la même valeur trois fois, mais rand_op1 renvoie une valeur différente trois fois.

$ python3 seed_tensorflow2.py
op1-1: [ 0.22292495  0.67142487  0.80927771]
op1-2: [-1.11188841  0.57819426  0.19088539]
op2-1: [-0.81131822  1.48459876  0.06532937]
op2-2: [ 0.55171245 -0.13107552 -0.04481386]
$ python3 seed_tensorflow2.py
op1-1: [-0.96930581  1.48854125  0.52752507]
op1-2: [ 0.91646689  0.85830265 -0.18069462]
op2-1: [-0.81131822  1.48459876  0.06532937]
op2-2: [ 0.55171245 -0.13107552 -0.04481386]
$ python3 seed_tensorflow2.py
op1-1: [ 0.79890805  1.35702407 -0.12329593]
op1-2: [ 1.69212222  0.22590902 -0.73435217]
op2-1: [-0.81131822  1.48459876  0.06532937]
op2-2: [ 0.55171245 -0.13107552 -0.04481386]

Ne fonctionne pas comme prévu Exemple 2: définir une graine aléatoire après avoir généré un opérateur aléatoire

Voici un exemple de définition d'une graine de nombre aléatoire après avoir généré un opérateur de nombre aléatoire. Le code expérimental est le suivant.

seed_tensorflow3.py


import tensorflow as tf
with tf.Graph().as_default():
    rand_op1 = tf.random_normal([3])
    rand_op2 = tf.random_normal([3], seed=1)
    tf.set_random_seed(0) #Définir la graine de nombre aléatoire après avoir généré un opérateur de nombre aléatoire
    with tf.Session() as sess:
        print("op1-1:", sess.run(rand_op1))
        print("op1-2:", sess.run(rand_op1))
        print("op2-1:", sess.run(rand_op2))
        print("op2-2:", sess.run(rand_op2))

Le résultat lors de l'exécution 3 fois est le suivant. Semblable à l'exemple ci-dessus, rand_op2, qui définit la graine de nombre aléatoire au niveau de l'opération, renvoie la même valeur trois fois, mais rand_op1 renvoie une valeur différente trois fois.

$ python3 seed_tensorflow3.py
op1-1: [ 0.03802272  1.69988739 -0.59952497]
op1-2: [ 0.62614048  0.07537607 -1.19501412]
op2-1: [-0.81131822  1.48459876  0.06532937]
op2-2: [ 0.55171245 -0.13107552 -0.04481386]
$ python3 seed_tensorflow3.py
op1-1: [ 1.02020776  1.70896292  0.45571503]
op1-2: [-0.46230376 -1.22950804  0.51038951]
op2-1: [-0.81131822  1.48459876  0.06532937]
op2-2: [ 0.55171245 -0.13107552 -0.04481386]
$ python3 seed_tensorflow3.py
op1-1: [ 1.31134415 -1.12688231  0.1805287 ]
op1-2: [-0.57391566  0.94440365 -1.07441545]
op2-1: [-0.81131822  1.48459876  0.06532937]
op2-2: [ 0.55171245 -0.13107552 -0.04481386]

Autre

Ce ne sont pas des informations confirmées, mais il semble que ce ne sera pas la même valeur même si vous définissez une graine aléatoire lors de l'exécution sur GPU.

Référence: Mentionnez que les réductions GPU ne sont pas déterministes dans la documentation · Problème n ° 2732 · tensorflow / tensorflow

Merci

Nous avons reçu des informations très utiles de M. Hirai, un autre groupe d'étude sur TensorFlow. Merci ici.

Recommended Posts

Correction de la graine aléatoire avec TensorFlow
Graine aléatoire corrigée dans TensorFlow et Numpy Un peu différent
Marche aléatoire en Python
[TensorFlow 2.x (tf.keras)] Correction de la graine aléatoire pour améliorer la reproductibilité
Forêt aléatoire équilibrée en python
Clipping et normalisation dans TensorFlow
Utiliser Random Forest avec Python
Choix aléatoire pondéré en python
Assurer la reproductibilité avec tf.keras dans Tensorflow 2.3
Tester avec des nombres aléatoires en Python
Essayez la visualisation d'incorporation ajoutée dans TensorFlow 0.12
Correction d'Apscheduler fonctionnant deux fois dans Flask
Résumé des différentes opérations dans Tensorflow
installer tensorflow dans un environnement anaconda + python3.5
Comment exécuter du code TensorFlow 1.0 en 2.0
Recherche de semences aléatoires dans l'apprentissage automatique
Créer une chaîne aléatoire en Python