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 нашей машины.
Первый GPU нашей машины (если есть).
Второй 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.
Рис. 3.3.Создание моделей для нескольких GPU в виде башни
Ниже приведен пример кода для нескольких GPU:
c = []
for d in [‘/gpu:0', ‘/gpu:1']:
with tf.device(d):
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. append(tf.matmul(a, b))
with tf.device(‘/cpu:0'):
sum = tf.add_n(c)
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
sess.run(sum)
Создание модели логистической регрессии в TensorFlow
Мы рассмотрели базовые понятия TensorFlow и можем построить простую модель для набора данных MNIST. Как вы, наверное, помните, наша цель — распознать рукописные цифры по черно-белым изображениям 28×28 единиц. Первая сеть, которую мы построим, реализует простой алгоритм машинного обучения — логистическую регрессию[33].
Логистическая регрессия — метод, с помощью которого мы можем вычислить вероятность того, что входные данные относятся к одному из целевых классов. Определим вероятность того, что данное изображение — 0, 1… или 9.
Наша модель использует матрицу W, которая представляет веса соединений в сети, и вектор b, соответствующий смещению, для вычисления того, принадлежит ли входящее значение x классу i, при помощи функции мягкого максимума (softmax), о которой мы уже говорили выше: