def my_network(input):
W_1 = tf.Variable(tf.random_uniform([784, 100], -1, 1), name="W_1")
b_1 = tf.Variable(tf.zeros([100]), name="biases_1")
output_1 = tf.matmul(input, W_1) + b_1
W_2 = tf.Variable(tf.random_uniform([100, 50], -1, 1), name="W_2")
b_2 = tf.Variable(tf.zeros([50]), name="biases_2")
output_2 = tf.matmul(output_1, W_2) + b_2
W_3 = tf.Variable(tf.random_uniform([50, 10], -1, 1), name="W_3")
b_3 = tf.Variable(tf.zeros([10]), name="biases_3")
output_3 = tf.matmul(output_2, W_3) + b_3
# printing names
print "Printing names of weight parameters"
print W_1.name, W_2.name, W_3.name
print "Printing names of bias parameters"
print b_1.name, b_2.name, b_3.name
return output_3
Эта сеть включает шесть переменных, описывающих три слоя. Поэтому, чтобы использовать ее несколько раз, мы пробуем заключить ее в компактную функцию вроде my_network, к которой можно обращаться несколько раз. Но если мы попытаемся использовать эту сеть с двумя разными входными параметрами, получится нечто неожиданное:
In [1]: i_1 = tf.placeholder(tf.float32, [1000, 784], name="i_1")
In [2]: my_network(i_1)
Printing names of weight parameters
W_1:0 W_2:0 W_3:0
Printing names of bias parameters
biases_1:0 biases_2:0 biases_3:0
Out[2]:
In [1]: i_2 = tf.placeholder(tf.float32, [1000, 784], name="i_2")
In [2]: my_network(i_2)
Printing names of weight parameters
W_1_1:0 W_2_1:0 W_3_1:0
Printing names of bias parameters
biases_1_1:0 biases_2_1:0 biases_3_1:0
Out[2]:
Если приглядеться, во втором обращении к my_network используются не те переменные, что в первом (имена различны). Мы создали второй набор переменных! Чаще мы хотим не создавать копию, а повторно использовать модель и ее переменные. Оказывается, в этом случае не стоит использовать tf.Variable. Нужно применить более сложную схему именования, которая использует область видимости переменных TensorFlow.
Механизмы области видимости переменных TensorFlow по большей части контролируются двумя функциями.
tf.get_variable(, , )
Проверяет, существует ли переменная с этим именем, выбирает ее, если та существует, или создает ее при помощи формы и функции инициализации, если ее еще не существует [29].
tf.variable_scope()
Управляет пространством имен и определяет область видимости tf.get_variable [30].
Попытаемся четче переписать my_network при помощи области видимости переменных TensorFlow.
Новые названия переменных включают пространство имен, например layer1/W, layer2/b и т. д.:
def layer(input, weight_shape, bias_shape):
weight_init = tf.random_uniform_initializer(minval=-1, maxval=1)
bias_init = tf.constant_initializer(value=0)
W = tf.get_variable("W", weight_shape initializer=weight_init)
b = tf.get_variable("b", bias_shape initializer=bias_init)
return tf.matmul(input, W) + b
def my_network(input):
with tf.variable_scope("layer_1"):
output_1 = layer(input, [784, 100], [100])
with tf.variable_scope("layer_2"):
output_2 = layer(output_1, [100, 50], [50])
with tf.variable_scope("layer_3"):
output_3 = layer(output_2, [50, 10], [10])
return output_3
Попробуем дважды обратиться к my_network, как мы сделали в предыдущем фрагменте кода:
In [1]: i_1 = tf.placeholder(tf.float32, [1000, 784], name="i_1")
In [2]: my_network(i_1)
Out[2]:
In [1]: i_2 = tf.placeholder(tf.float32, [1000, 784], name="i_2")
In [2]: my_network(i_2)
ValueError: Over-sharing: Variable layer_1/W already exists…
В отличие от tf.Variable, команда tf.get_variable проверяет, что переменная с соответствующим именем еще не создана. По умолчанию совместное использование запрещено (из соображений безопасности!), но если мы хотим его решить в области видимости, то должны прописать это прямо:
with tf.variable_scope("shared_variables") as scope:
i_1 = tf.placeholder(tf.float32, [1000, 784], name="i_1")
my_network(i_1)
scope.reuse_variables()
i_2 = tf.placeholder(tf.float32, [1000, 784], name="i_2")
my_network(i_2)
Это позволяет сохранить модульность, не запрещая совместное использование переменных. К тому же схема именования становится проще и гораздо удобнее.
Управление моделями на CPU и GPU
TensorFlow позволяет при необходимости пользоваться несколькими вычислительными устройствами для обучения модели. Поддерживаемые устройства представлены строковыми идентификаторами, что обычно выглядит так:
"/cpu:0"
CPU нашей машины.
"/gpu:0"
Первый GPU нашей машины (если есть).
"/gpu:1"
Второй GPU нашей машины (если есть).
Если у операции есть ядра CPU и GPU и разрешено использование GPU, TensorFlow автоматически будет выбирать вариант для GPU. Чтобы посмотреть, какие устройства использует граф вычислений, мы можем инициализировать сессию TensorFlow, установив параметр log_device_placement в значение True:
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
Если мы хотим использовать конкретное устройство, можно его выбрать с помощью конструкции with tf.device [31]. Но если оно недоступно, возникнет ошибка. Нужно, чтобы TensorFlow нашла другое доступное устройство, если выбранное не существует; можно передать флаг allow_soft_placement в переменную сессии таким образом [32]:
with tf.device(‘/gpu:2'):
a = tf.constant([1.0, 2.0, 3.0, 4.0], shape=[2, 2], name='a')
b = tf.constant([1.0, 2.0], shape=[2, 1], name='b')
c = tf.matmul(a, b)
sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True, log_device_placement=True))
sess.run(c)
TensorFlow также позволяет строить модели, которые используют несколько GPU. Они создаются в виде башни, как показано на рис. 3.3.
Читать дальше
Конец ознакомительного отрывка
Купить книгу