В курсе “Программирование глубоких нейронных сетей на Python” долгое время в качестве бэкенда для Keras использовалась библиотека Theano. К сожалению, недавно было объявлено, что разработка Theano прекращается и следующая версия Theano 1.0 будет последней. Библиотека TensorFlow, напротив, очень быстро развивается и завоевывает популярность. Это не удивительно, учитывая что за TensorFlow стоит компания Google. В связи с этими изменениями я решил перевести все примеры из курса с Theano на TensorFlow. С 10.11.2017 все примеры на странице курса и в репозитории GitHub с исходными кодами используют TensorFlow.

Чем бэкенды Keras отличаются друг от друга

Theano и TensorFlow используются в курсе не напрямую, а в качестве бэкенда для Keras. Поэтому изменения в связи с переходом на TensorFlow небольшие. Два бэкенда очень похожи, отличаются они только форматом хранения изображений.

Как мы помним, изображение в Keras представляется трехмерными тензорами (на всякий случай напомню, что тензор – это многомерная матрица). Две размерности тензора соответствуют размеру изображения, а третья – количеству каналов с цветами. Например, изображения в наборе данных MNIST в оттенках серого имеют размер 28х28 с одним каналом для интенсивности пикселов. А изображения в CIFAR-10 цветные, их размер 32х32 плюс три канала для красного, зеленого и синего цветов (в формате RGB).

Разница между TensorFlow и Theano заключается в порядке хранения информации об изображении. В Theano сначала указывается количество каналов, а затем размерность изображения. В TensorFlow наоборот, сначала размер изображения, а затем количество каналов. Порядок размерности изображений указывается в конфигурационном файле keras.json (хранится в домашнем каталоге пользователя, в подкаталоге .keras). Пример конфигурационного файла для TensorFlow:

    {
        "floatx": "float32",
        "epsilon": 1e-07,
        "image_data_format": "channels_last",
        "backend": "tensorflow"
    }

В поле backend указано tensorflow, а в поле image_data_format (формат данных об изображении) – channels_last (размерность каналов идет последней).

Для Theano конфигурационный файл выглядит следующим образом:

    {
        "floatx": "float32",
        "epsilon": 1e-07,
        "image_data_format": "channels_first",
        "backend": "theano"
    }

Бэкенд theano, формат данных об изображении – channels_first (количество каналов на первом месте).

Следует отметить, что можно менять image_data_format независимо от бэкенда. Например, можно использовать TensorFlow и прописать в image_data_format значение channels_first. Работать будет, но значительно медленнее. У меня производительность при такой комбинации снизилась в три раза.

Таким образом, при смене бэкенда изменения будет только если вы работаете с изображениями и только в той части, где указывается размерность изображений. Ничего другого менять не нужно.

Как указывать размерность изображений для разных бэкендов

Размерность изображений необходимо указывать для первого слоя сверточной нейронной сети. В качестве примера давайте рассмотрим распознавание объектов из набора данных CIFAR-10. Код для создания первого слоя сверточной нейронной сети при использовании TensorFlow будет выглядеть следующим образом:

model.add(Conv2D(32, (3, 3), padding='same',
                 input_shape=(32, 32, 3), activation='relu'))

Здесь нас интересует размерность изображения input_shape=(32, 32, 3). Количество каналов идет после размера изображения.

Для Theano первый слой сверточной сети задается так:

model.add(Conv2D(32, (3, 3), padding='same',
                input_shape=(3, 32, 32), activation='relu')

В input_shape сначала указывается количество каналов, а затем размерность изображения.

Можно написать программу таким образом, чтобы размерность изображения задавалась правильным образом для разных бэкендов. Вот один из возможных вариантов:

from keras import backend as K

if K.image_data_format() == 'channels_first':
    input_shape = (3, 32, 32)
else:
    input_shape = (32, 32, 3)

В учебных примерах я так не пишу, чтобы не усложнять материал. Но если вы разрабатываете более-менее серьезную программу, то лучше рассчитывать, что ее могут запускать на разных бэкендах.

Все остальное, связанное с различиями в размерности изображений, делается автоматически. Предварительно обученные нейронные сети в Keras есть как для TensorFlow, так и для Theano (за небольшим исключением). Средства предварительной обработки изображений также автоматически определяют тип бэкенда. Например, мы можем загрузить изображение для анализа следующим образом:

from keras.preprocessing import image

img = image.load_img('plane.jpg', target_size=(32, 32))

Класс image определит используемый бэкенд и автоматически выберет подходящий порядок размерности тензора с изображением.

Как перейти на TensorFlow

Заменить бэкенд в Keras с Theano на TensorFlow достаточно просто. Для этого нужно:

  1. Установить TensorFlow. Вот инструкция по установке TensorFlow совместно с Keras в Anaconda.
  2. Изменить конфигурационный файл keras.json, в котором указать нужный бэкенд и порядок хранения изображений:

     {
         "floatx": "float32",
         "epsilon": 1e-07,
         "image_data_format": "channels_last",
         "backend": "tensorflow"
     }
    
  3. Если вы работаете с изображениями, то необходимо изменить размерность по примеру в предыдущем разделе. В противном случае менять программу не понадобится. Для образца можно использовать примеры кода из репозитория курса.

Заключение

Начиная с 10.11.2017 все примеры кода курса на сайте и в репозитории переведены на TensorFlow. Новые примеры будут только на TensorFlow.

TensorFlow содержит большое количество удобных инструментов. Например, TensorBoard позволяет визуализировать процесс обучения глубоких нейронных сетей. Мы обязательно рассмотрим TensorBoard и другие полезные инструменты TensorFlow более подробно.

Пишите в комментариях, получилось ли у вас перейти на TensorFlow и на какие особенности Keras вы при этом натолкнулись.