google - Quelle est la différence entre la portée du nom et une portée variable dans tensorflow?




tag manager (6)

Quelles sont les différences entre ces fonctions?

tf.variable_op_scope(values, name, default_name, initializer=None)

Renvoie un gestionnaire de contexte pour définir une opération qui crée des variables. Ce gestionnaire de contexte valide que les valeurs données proviennent du même graphe, s'assure que ce graphe est le graphe par défaut et pousse une portée de nom et une portée variable.

tf.op_scope(values, name, default_name=None)

Renvoie un gestionnaire de contexte à utiliser lors de la définition d'une opération Python. Ce gestionnaire de contexte valide que les valeurs données proviennent du même graphe, s'assure que ce graphe est le graphe par défaut et pousse une portée de nom.

tf.name_scope(name)

Wrapper pour Graph.name_scope() utilisant le graphique par défaut. Voir Graph.name_scope() pour plus de détails.

tf.variable_scope(name_or_scope, reuse=None, initializer=None)

Renvoie un contexte pour la portée variable. La portée variable permet de créer de nouvelles variables et de partager celles déjà créées tout en fournissant des vérifications pour ne pas créer ou partager par accident. Pour plus de détails, reportez-vous à la section étendue de la variable. Nous ne présentons ici que quelques exemples de base.


Answers

Dans la dernière section de cette page de la documentation tensorflow: Noms des ops dans tf.variable_scope()

[...] quand nous faisons with tf.variable_scope("name") , cela ouvre implicitement un tf.name_scope("name") . Par exemple:

with tf.variable_scope("foo"):
  x = 1.0 + tf.get_variable("v", [1])
assert x.op.name == "foo/add"

Les étendues de noms peuvent être ouvertes en plus d'une portée variable, puis elles affectent uniquement les noms des opérations, mais pas les variables.

with tf.variable_scope("foo"):
    with tf.name_scope("bar"):
        v = tf.get_variable("v", [1])
        x = 1.0 + v
assert v.name == "foo/v:0"
assert x.op.name == "foo/bar/add"

Lorsque vous ouvrez une portée variable à l'aide d'un objet capturé au lieu d'une chaîne, nous ne modifions pas la portée du nom actuel pour les opérations.


Namespaces est un moyen d'organiser les noms pour les variables et les opérateurs de manière hiérarchique (par exemple "scopeA / scopeB / scopeC / op1")

  • tf.name_scope crée un espace de noms pour les opérateurs dans le graphique par défaut.
  • tf.variable_scope crée un espace de noms pour les variables et les opérateurs dans le graphique par défaut.

  • tf.op_scope identique à tf.name_scope , mais pour le graphe dans lequel les variables spécifiées ont été créées.

  • tf.variable_op_scope identique à tf.variable_scope , mais pour le graphique dans lequel les variables spécifiées ont été créées.

Les liens vers les sources ci-dessus aident à désambiguïser ce problème de documentation.

Cet exemple montre que tous les types d'étendues définissent des espaces de noms pour les variables et les opérateurs avec les différences suivantes:

  1. Les étendues définies par tf.variable_op_scope ou tf.variable_scope sont compatibles avec tf.get_variable (elle ignore deux autres étendues)
  2. tf.op_scope et tf.variable_op_scope sélectionnez simplement un graphe d'une liste de variables spécifiées pour créer une portée. Autres que leur comportement égal à tf.name_scope et tf.variable_scope conséquence
  3. tf.variable_scope et variable_op_scope ajoutent un initialiseur spécifié ou par défaut.

Comme pour API r0.11, op_scope et variable_op_scope sont tous les deux deprecated . name_scope et variable_scope peuvent être imbriqués:

with tf.name_scope('ns'):
    with tf.variable_scope('vs'): #scope creation
        v1 = tf.get_variable("v1",[1.0])   #v1.name = 'vs/v1:0'
        v2 = tf.Variable([2.0],name = 'v2')  #v2.name= 'ns/vs/v2:0'
        v3 = v1 + v2       #v3.name = 'ns/vs/add:0'

Commençons par une courte introduction au partage de variables. C'est un mécanisme dans TensorFlow qui permet de partager des variables accédées dans différentes parties du code sans passer de références à la variable autour.

La méthode tf.get_variable peut être utilisée avec le nom de la variable comme argument pour créer une nouvelle variable avec ce nom ou récupérer celle qui a été créée auparavant. Ceci est différent de l'utilisation du constructeur tf.Variable qui va créer une nouvelle variable à chaque fois qu'elle est appelée (et éventuellement ajouter un suffixe au nom de la variable si une variable avec un tel nom existe déjà).

C'est aux fins du mécanisme de partage de variables qu'un type de portée distinct (portée variable) a été introduit.

Par conséquent, nous finissons par avoir deux types d'étendues différents:

Les deux étendues ont le même effet sur toutes les opérations ainsi que sur les variables créées à l'aide de tf.Variable , c'est-à-dire que la portée sera ajoutée en tant que préfixe à l'opération ou au nom de la variable.

Cependant, la portée du nom est ignorée par tf.get_variable . Nous pouvons voir cela dans l'exemple suivant:

with tf.name_scope("my_scope"):
    v1 = tf.get_variable("var1", [1], dtype=tf.float32)
    v2 = tf.Variable(1, name="var2", dtype=tf.float32)
    a = tf.add(v1, v2)

print(v1.name)  # var1:0
print(v2.name)  # my_scope/var2:0
print(a.name)   # my_scope/Add:0

La seule façon de placer une variable accédée à l'aide de tf.get_variable dans une étendue est d'utiliser une portée variable, comme dans l'exemple suivant:

with tf.variable_scope("my_scope"):
    v1 = tf.get_variable("var1", [1], dtype=tf.float32)
    v2 = tf.Variable(1, name="var2", dtype=tf.float32)
    a = tf.add(v1, v2)

print(v1.name)  # my_scope/var1:0
print(v2.name)  # my_scope/var2:0
print(a.name)   # my_scope/Add:0

Cela nous permet de partager facilement des variables entre différentes parties du programme, même dans des portées de noms différentes:

with tf.name_scope("foo"):
    with tf.variable_scope("var_scope"):
        v = tf.get_variable("var", [1])
with tf.name_scope("bar"):
    with tf.variable_scope("var_scope", reuse=True):
        v1 = tf.get_variable("var", [1])
assert v1 == v
print(v.name)   # var_scope/var:0
print(v1.name)  # var_scope/var:0

METTRE À JOUR

À partir de la version r0.11, op_scope et variable_op_scope sont tous deux deprecated et remplacés par name_scope et variable_scope .


Vous pouvez les considérer comme deux groupes: variable_op_scope et op_scope prennent un ensemble de variables en entrée et sont conçus pour créer des opérations. La différence réside dans la façon dont ils affectent la création de variables avec tf.get_variable :

def mysum(a,b,name=None):
    with tf.op_scope([a,b],name,"mysum") as scope:
        v = tf.get_variable("v", 1)
        v2 = tf.Variable([0], name="v2")
        assert v.name == "v:0", v.name
        assert v2.name == "mysum/v2:0", v2.name
        return tf.add(a,b)

def mysum2(a,b,name=None):
    with tf.variable_op_scope([a,b],name,"mysum2") as scope:
        v = tf.get_variable("v", 1)
        v2 = tf.Variable([0], name="v2")
        assert v.name == "mysum2/v:0", v.name
        assert v2.name == "mysum2/v2:0", v2.name
        return tf.add(a,b)

with tf.Graph().as_default():
    op = mysum(tf.Variable(1), tf.Variable(2))
    op2 = mysum2(tf.Variable(1), tf.Variable(2))
    assert op.name == 'mysum/Add:0', op.name
    assert op2.name == 'mysum2/Add:0', op2.name

Notez le nom de la variable v dans les deux exemples.

tf.name_scope pour tf.name_scope et tf.variable_scope :

with tf.Graph().as_default():
    with tf.name_scope("name_scope") as scope:
        v = tf.get_variable("v", [1])
        op = tf.add(v, v)
        v2 = tf.Variable([0], name="v2")
        assert v.name == "v:0", v.name
        assert op.name == "name_scope/Add:0", op.name
        assert v2.name == "name_scope/v2:0", v2.name

with tf.Graph().as_default():
    with tf.variable_scope("name_scope") as scope:
        v = tf.get_variable("v", [1])
        op = tf.add(v, v)
        v2 = tf.Variable([0], name="v2")
        assert v.name == "name_scope/v:0", v.name
        assert op.name == "name_scope/Add:0", op.name
        assert v2.name == "name_scope/v2:0", v2.name

Vous pouvez en savoir plus sur la portée variable dans le tutorial . Une question similaire a déjà été posée sur .


Réponse courte :

Transpose votre vecteur pred utilisant tf.transpose(pred) .

Réponse plus longue :

Le problème est que pred (les prédictions) et y (les étiquettes) ne sont pas de la même forme: l'une est un vecteur de ligne et l'autre un vecteur de colonne. Apparemment, lorsque vous leur appliquez une opération par éléments, vous obtenez une matrice, ce qui n'est pas ce que vous voulez.

La solution consiste à transposer le vecteur de prédiction en utilisant tf.transpose() pour obtenir un vecteur correct et donc une fonction de perte correcte. En fait, si vous définissez la taille du lot sur 1 dans votre exemple, vous verrez que cela fonctionne même sans le correctif, car la transposition d'un vecteur 1x1 est un no-op.

J'ai appliqué ce correctif à votre code exemple et observé le comportement suivant. Avant le correctif:

Epoch: 0245 cost= 84.743440580
[*]----------------------------
label value: 23 estimated value: [ 27.47437096]
label value: 50 estimated value: [ 24.71126747]
label value: 22 estimated value: [ 23.87785912]

Et après le correctif au même moment:

Epoch: 0245 cost= 4.181439120
[*]----------------------------
label value: 23 estimated value: [ 21.64333534]
label value: 50 estimated value: [ 48.76105118]
label value: 22 estimated value: [ 24.27996063]

Vous verrez que le coût est beaucoup plus bas et qu’il a effectivement appris la valeur 50. Vous devrez affiner le taux d’apprentissage pour améliorer vos résultats.





tensorflow