Основы глубокого обучения - страница 16
Операции в TensorFlow
Мы уже упомянули о некоторых операциях в контексте инициализации переменных, но в TensorFlow доступны и многие другие. Они выражают абстрактные трансформации, которые применяются к тензорам в графе вычислений. Операции могут иметь атрибуты, которые либо заданы изначально, либо вводятся в процессе работы. Например, атрибут может описывать ожидаемые типы входных данных (добавление тензоров типа float32 или int32). Операциям, как и переменным, может присваиваться имя для простоты обращения на графе вычислений. Они состоят из одного или более ядер, которые содержат специфичные для устройств реализации.
Например, операция может иметь отдельные ядра для CPU и GPU, поскольку на GPU ее реализация более эффективна. Это справедливо для многих действий с матрицами в TensorFlow.
Общий обзор типов доступных операций приведен в таблице 3.1, взятой из оригинальной технической документации TensorFlow[26].
Таблица 3.1.Общая таблица операций в TensorFlow
Тензоры-заполнители
Теперь, обладая солидными познаниями в области переменных и операций в TensorFlow, мы имеем практически полное описание компонентов графа вычислений этой библиотеки. Не хватает представлений о том, как обеспечить ввод данных в глубокую модель при обучении и тестировании. Переменной недостаточно: она инициализируется лишь однажды. Нам нужен компонент, который мы будем загружать каждый раз при запуске графа вычислений.
TensorFlow решает эту проблему при помощи так называемого заполнителя[27]. Его можно использовать в операциях так же, как и все обычные переменные и тензоры TensorFlow, и он реализуется следующим образом:
x = tf.placeholder(tf.float32, name="x", shape=[None, 784])
W = tf.Variable(tf.random_uniform([784,10], -1, 1), name="W")
multiply = tf.matmul(x, W)
Здесь мы определяем заполнитель, где x — мини-пакет данных, сохраненных как float32. Можно отметить, что в x 784 столбца, то есть каждый образец данных имеет 784 измерения. Для x не определено число строк. Это значит, что он может быть инициализирован произвольным количеством образцов данных. Можно и отдельно умножать каждый из них на W, но представление всего мини-пакета в виде тензора позволяет вычислить результаты для всех образцов данных параллельно. В результате i-я строка тензора multiply соответствует W, умноженному на i-й образец данных.
Как и переменные, которые нужно инициализировать при первом построении графа вычислений, заполнители нужно наполнять каждый раз при запуске графа (или подграфа). Подробнее об этом мы поговорим в следующем разделе.
Сессии в TensorFlow
Программа TensorFlow взаимодействует с графом вычислений в рамках сессии[28]. В ходе сессии TensorFlow происходит создание изначального графа, а также инициализация всех переменных и запуск графа вычислений. Для анализа этих элементов рассмотрим простой скрипт на Python:
import tensorflow as tf
from read_data import get_minibatch()
x = tf.placeholder(tf.float32, name="x", shape=[None, 784])
W = tf.Variable(tf.random_uniform([784, 10], -1, 1), name="W")
b = tf.Variable(tf.zeros([10]), name="biases")
output = tf.matmul(x, W) + b
init_op = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init_op)
feed_dict = {"x": get_minibatch()}
sess.run(output, feed_dict=feed_dict)
Первые четыре строчки после оператора импорта описывают граф вычислений, который строится в ходе сессии, когда она будет создана. Этот граф (без операций инициализации переменных) изображен на рис. 3.2. Затем мы инициализируем переменные, используя сессию для запуска соответствующей операции — sess.run(init_op). Наконец, мы можем запустить подграф, вновь обратившись к sess.run, но уже передав на вход тензор или список тензоров, которые мы хотим вычислить, и feed_dict, который вводит необходимые данные в заполнители.