Эффективный TensorFlow. Глава 3. Понимание областей видимости и случаев их использования

TensorFlow

Эта статья переведена с:«Прицелы и когда их использовать», Если есть какое-либо нарушение, пожалуйста, свяжитесь, чтобы удалить его, только для академических обменов, пожалуйста, не используйте его в коммерческих целях. Если есть какие-либо ошибки, пожалуйста, свяжитесь, чтобы указать.

В TensorFlow переменные и тензоры имеют атрибут имени, который идентифицирует их в символическом графе. Если вы не укажете имя при создании переменной или тензора, TensorFlow автоматически присвоит его вам:

a = tf.constant(1)
print(a.name)  # prints "Const:0"

b = tf.Variable(1)
print(b.name)  # prints "Variable:0"

Вы можете переопределить имя по умолчанию, указав его явно:

a = tf.constant(1, name="a")
print(a.name)  # prints "a:0"

b = tf.Variable(1, name="b")
print(b.name)  # prints "b:0"

TensorFlow представляет два разных контекстных менеджера для изменения имен тензоров и переменных. первыйtf.name_scope:

with tf.name_scope("scope"):
  a = tf.constant(1, name="a")
  print(a.name)  # prints "scope/a:0"

  b = tf.Variable(1, name="b")
  print(b.name)  # prints "scope/b:0"

  c = tf.get_variable(name="c", shape=[])
  print(c.name)  # prints "c:0"

Обратите внимание, что есть два способа определить новые переменные в TensorFlow, один из них — создатьtf.Variableвозражать или звонитьtf.get_variableметод. позвонить с новым именемtf.get_variableприведет к созданию новой переменной, но если переменная с таким же именем существует, будет возбуждено исключение ValueError, сообщающее нам, что повторное объявление переменной не разрешено.

tf.name_scopeОказывать воздействиеtf.VariableИмена тензоров и переменных, которые создаются, но не влияют на использованиеtf.get_variableсозданная переменная.

иtf.name_scopeразные,tf.variable_scopeтакже модифицирован для использованияtf.get_variableИмя созданной переменной:

with tf.variable_scope("scope"):
  a = tf.constant(1, name="a")
  print(a.name)  # prints "scope/a:0"

  b = tf.Variable(1, name="b")
  print(b.name)  # prints "scope/b:0"

  c = tf.get_variable(name="c", shape=[])
  print(c.name)  # prints "scope/c:0"
with tf.variable_scope("scope"):
  a1 = tf.get_variable(name="a", shape=[])
  a2 = tf.get_variable(name="a", shape=[])  # Disallowed

Но что, если мы действительно хотим повторно использовать ранее объявленную переменную? Область видимости переменных также предоставляет возможность сделать это:

with tf.variable_scope("scope"):
  a1 = tf.get_variable(name="a", shape=[])
with tf.variable_scope("scope", reuse=True):
  a2 = tf.get_variable(name="a", shape=[])  # OK

Это становится удобным при использовании встроенных слоев нейронной сети:

with tf.variable_scope('my_scope'):
  features1 = tf.layers.conv2d(image1, filters=32, kernel_size=3)
# Use the same convolution weights to process the second image:
with tf.variable_scope('my_scope', reuse=True):
  features2 = tf.layers.conv2d(image2, filters=32, kernel_size=3)

В качестве альтернативы вы можете поставитьreuseсвойство установлено наtf.AUTO_REUSE, эта операция указывает TensorFlow создать новую переменную, если переменной с таким именем не существует, и повторно использовать ее в противном случае:

with tf.variable_scope("scope", reuse=tf.AUTO_REUSE):
  features1 = tf.layers.conv2d(image1, filters=32, kernel_size=3)
  
with tf.variable_scope("scope", reuse=tf.AUTO_REUSE):
  features2 = tf.layers.conv2d(image2, filters=32, kernel_size=3)

Если вы хотите совместно использовать много переменных, отслеживание определения новых переменных и их повторное использование может быть громоздким и подверженным ошибкам.tf.AUTO_REUSEЭто упрощает задачу, но увеличивает риск совместного использования переменных, которые не должны использоваться совместно. Шаблоны TensorFlow — еще один способ решить эту проблему без риска:

conv3x32 = tf.make_template("conv3x32", lambda x: tf.layers.conv2d(x, 32, 3))
features1 = conv3x32(image1)
features2 = conv3x32(image2)  # Will reuse the convolution weights.

Вы можете преобразовать любую функцию в шаблон TensorFlow. Переменные, определенные внутри функции, объявляются при первом вызове шаблона, а при последующих вызовах они автоматически используются повторно.