variable get_variable tensorflow

tensorflow - tf get_variable



¿Cuál es la diferencia del alcance del nombre y un alcance variable en el tensorflow? (7)

¿Cuáles son las diferencias entre estas funciones?

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

Devuelve un administrador de contexto para definir una operación que crea variables. Este administrador de contexto valida que los valores dados son del mismo gráfico, asegura que ese gráfico es el gráfico predeterminado y empuja un ámbito de nombre y un ámbito variable.

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

Devuelve un administrador de contexto para usar al definir una operación de Python. Este administrador de contexto valida que los valores dados provienen del mismo gráfico, asegura que ese gráfico sea el gráfico predeterminado e inserta un ámbito de nombre.

tf.name_scope(name)

Wrapper para Graph.name_scope() usando el gráfico predeterminado. Ver Graph.name_scope() para más detalles.

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

Devuelve un contexto para el alcance variable. El alcance variable permite crear nuevas variables y compartir las ya creadas al tiempo que proporciona comprobaciones para no crear o compartir por accidente. Para obtener más información, consulte el Cómo de alcance variable, aquí solo presentamos algunos ejemplos básicos.


Comencemos con una breve introducción al intercambio de variables. Es un mecanismo en TensorFlow que permite compartir variables a las que se accede en diferentes partes del código sin pasar referencias a la variable.

El método tf.get_variable se puede usar con el nombre de la variable como argumento para crear una nueva variable con dicho nombre o recuperar la que se creó anteriormente. Esto es diferente de usar el constructor tf.Variable que creará una nueva variable cada vez que se llame (y potencialmente agregará un sufijo al nombre de la variable si ya existe una variable con dicho nombre).

Es para el propósito del mecanismo de intercambio variable que se introdujo un tipo separado de alcance (alcance variable).

Como resultado, terminamos teniendo dos tipos diferentes de ámbitos:

Ambos ámbitos tienen el mismo efecto en todas las operaciones, así como en las variables creadas con tf.Variable . tf.Variable , es decir, el ámbito se agregará como un prefijo a la operación o al nombre de la variable.

Sin embargo, tf.get_variable ignora el alcance del nombre. Podemos ver eso en el siguiente ejemplo:

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 única forma de colocar una variable a la que se accede mediante tf.get_variable en un ámbito es utilizar un ámbito variable, como en el siguiente ejemplo:

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

Esto nos permite compartir fácilmente variables en diferentes partes del programa, incluso dentro de diferentes ámbitos de nombre:

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

ACTUALIZAR

A partir de la versión r0.11, op_scope y variable_op_scope están en deprecated y se reemplazan por name_scope y variable_scope .


Desde la última sección de esta página de la documentación de tensorflow: Nombres de operaciones en tf.variable_scope()

[...] cuando lo hacemos with tf.variable_scope("name") , esto abre implícitamente un tf.name_scope("name") . Por ejemplo:

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

Los ámbitos de nombre se pueden abrir además de un ámbito variable, y luego solo afectarán los nombres de las operaciones, pero no las 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"

Al abrir un ámbito variable utilizando un objeto capturado en lugar de una cadena, no alteramos el ámbito del nombre actual para las operaciones.


En cuanto a la API r0.11, op_scope y variable_op_scope están en deprecated . name_scope y variable_scope se pueden anidar:

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''


Hagámoslo simple: solo use tf.variable_scope . Citando a un desarrollador de TF :

Actualmente, recomendamos que todos usen variable_scope y no usen name_scope excepto el código interno y las bibliotecas.

Además del hecho de que la funcionalidad de variable_scope básicamente extiende las de name_scope , considere cómo no juegan tan bien juntos:

with tf.name_scope(''foo''): with tf.variable_scope(''bar''): x = tf.get_variable(''x'', shape=()) x2 = tf.square(x**2, name=''x2'') print(x.name) # bar/x:0 print(x2.name) # foo/bar/x2:0

Al apegarse a variable_scope solo evita algunos dolores de cabeza debido a este tipo de incompatibilidad.


Los espacios de nombres son una forma de organizar nombres para variables y operadores de manera jerárquica (por ejemplo, "scopeA / scopeB / scopeC / op1")

  • tf.name_scope crea un espacio de nombres para operadores en el gráfico predeterminado.
  • tf.variable_scope crea un espacio de nombres para variables y operadores en el gráfico predeterminado.

  • tf.op_scope igual que tf.name_scope , pero para el gráfico en el que se crearon las variables especificadas.

  • tf.variable_op_scope igual que tf.variable_scope , pero para el gráfico en el que se crearon las variables especificadas.

Los enlaces a las fuentes anteriores ayudan a desambiguar este problema de documentación.

Este ejemplo muestra que todos los tipos de ámbitos definen espacios de nombres para variables y operadores con las siguientes diferencias:

  1. Los ámbitos definidos por tf.variable_op_scope o tf.variable_scope son compatibles con tf.get_variable (ignora otros dos ámbitos)
  2. tf.op_scope y tf.variable_op_scope solo seleccionan un gráfico de una lista de variables especificadas para crear un alcance. Aparte de su comportamiento igual a tf.name_scope y tf.variable_scope consecuencia
  3. tf.variable_scope y variable_op_scope agregan inicializador especificado o predeterminado.

Puede pensarlos como dos grupos: variable_op_scope y op_scope toman un conjunto de variables como entrada y están diseñadas para crear operaciones. La diferencia está en cómo afectan la creación de variables con 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

observe el nombre de la variable v en los dos ejemplos.

lo mismo para tf.name_scope y 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

Puede leer más sobre el alcance variable en el tutorial . Una pregunta similar se hizo antes en .


Tanto variable_op_scope como op_scope ahora están en desuso y no deberían usarse en absoluto.

Con respecto a los otros dos, también tuve problemas para comprender la diferencia entre tf.variable_scope y tf.name_scope (se veían casi iguales) antes de intentar visualizar todo creando un ejemplo simple:

import tensorflow as tf def scoping(fn, scope1, scope2, vals): with fn(scope1): a = tf.Variable(vals[0], name=''a'') b = tf.get_variable(''b'', initializer=vals[1]) c = tf.constant(vals[2], name=''c'') with fn(scope2): d = tf.add(a * b, c, name=''res'') print ''/n ''.join([scope1, a.name, b.name, c.name, d.name]), ''/n'' return d d1 = scoping(tf.variable_scope, ''scope_vars'', ''res'', [1, 2, 3]) d2 = scoping(tf.name_scope, ''scope_name'', ''res'', [1, 2, 3]) with tf.Session() as sess: writer = tf.summary.FileWriter(''logs'', sess.graph) sess.run(tf.global_variables_initializer()) print sess.run([d1, d2]) writer.close()

Aquí creo una función que crea algunas variables y constantes y las agrupa en ámbitos (según el tipo que proporcioné). En esta función, también imprimo los nombres de todas las variables. Después de eso, ejecuto el gráfico para obtener valores de los valores resultantes y guardar archivos de eventos para investigarlos en TensorBoard. Si ejecuta esto, obtendrá lo siguiente:

scope_vars scope_vars/a:0 scope_vars/b:0 scope_vars/c:0 scope_vars/res/res:0 scope_name scope_name/a:0 b:0 scope_name/c:0 scope_name/res/res:0

Verá un patrón similar si abre TensorBoard (como ve que b está fuera del scope_name rectangular):

Esto te da la respuesta :

Ahora ve que tf.variable_scope() agrega un prefijo a los nombres de todas las variables (sin importar cómo las cree), operaciones, constantes. Por otro lado, tf.name_scope() ignora las variables creadas con tf.get_variable() porque supone que usted sabe qué variable y en qué ámbito desea usar.

Una buena documentación sobre Compartir variables le dice que

tf.variable_scope() : administra los espacios de nombres para los nombres pasados ​​a tf.get_variable() .

La misma documentación proporciona más detalles sobre cómo funciona Variable Scope y cuándo es útil.