Модули Keras: типы и примеры / keras 7
Модули Keras предоставляют различные классы и алгоритмы глубокого обучения. Дальше о них и пойдет речь.
Модули Keras
В Keras представлены следующие модули:
- Бэкенд
- Утилиты
- Обработка изображений
- Последовательная последовательности
- Обработка текста
- Обратный вызов
Модуль бэкенда в Keras
Keras — это высокоуровневый API, который не заостряет внимание на вычислениях на бэкенде. Однако он позволяет пользователям изучать свой бэкенд и делать изменения на этом уровне. Для этого есть специальный модуль.
Его конфигурация по умолчанию хранится в файле $Home/keras/keras.json .
Он выглядит вот так:
"image_data_format": "channels_last", "epsilon": 1e-07, "floatx": "float32", "backend": "tensorflow" >
Можно дописать код, совместимый с этим бэкендом.
from Keras import backend as K b=K.random_uniform_variable(shape=(3,4),low=0,high=1) c=K.random_uniform_variable(shape=(3,4),mean=0,scale=1) d=K.random_uniform_variable(shape=(3,4),mean=0,scale=1) a=b + c * K.abs(d) c=K.dot(a,K.transpose(b)) a=K.sum(b,axis=1) a=K.softmax(b) a=K.concatenate([b,c],axis=1)
Модуль утилит в Keras
Этот модуль предоставляет утилиты для операций глубокого обучения. Вот некоторые из них.
HDF5Matrix
Для преобразования входящих данных в формат HDF5.
from.utils import HDF5Matrix data=HDF5Matrix('data.hdf5','data')
to_categorical
Для унитарной кодировки (one hot encoding) векторов класса.
from keras.utils import to_categorical labels = [0,1,2,3,4,5] to_categorical(labels)
print_summary
Для вывода сводки по модели.
from keras.utils import print_summary print_summary(model)
Модуль обработки изображений в Keras
Содержит методы для конвертации изображений в массивы NumPy. Также есть функции для представления данных.
Класс ImageDataGenerator
Используется для дополнения данных в реальном времени.
keras.preprocessing.image.ImageDataGenerator(featurewise_center, samplewise_center, featurewise_std_normalization, samplewise_std_normalization, zca_whitening, zca_epsilon=1e-06, rotation_range=0, width_shift_range=0.0, height_shift_range=0.0, brightness_range, shear_range=0.0, zoom_range=0.0, channel_shift_range=0.0, fill_mode='nearest', cval=0.0, horizontal_flip, vertical_flip)
Методы ImageDataGenerator
apply_transform:
Для применения изменений к изображению
apply_transform(x, transform_parameters)
flow
Для генерации серий дополнительных данных.
flow(x, y, batch_size=32, shuffle, sample_weight, seed, save_to_dir, save_prefix='', save_format='png', subset)
standardize
Для нормализации входящего пакета.
standardize(x)
Модуль обработки последовательности
Методы для генерации основанных на времени данных из ввода. Также есть функции для представления данных.
TimeseriesGenerator
Для генерации временных данных.
keras.preprocessing.sequence.TimeseriesGenerator(data, targets, length, sampling_rate, stride, start_index, end_index)
skipgrams
Конвертирует последовательность слов в кортежи слов.
keras.preprocessing.sequence.skipgrams(sequence, vocabulary_size, window_size=4, negative_samples=1.0, shuffle, categorical, sampling_table, seed)
Модуль предварительной обработки текста
Методы для конвертации текста в массивы NumPy. Есть также методы для подготовки данных.
Tokenizer
Используется для конвертации основного текста в векторы.
keras.preprocessing.text.Tokenizer(num_words, filters='!"#$%&()*+,-./:;?@[\\]^_`<|>~\t\n', lower, split=' ', char_level, oov_token=, document_count=0)
one_hot
Для кодировки текста в список слов.
keras.preprocessing.text.one_hot(text, n, filters='!"#$%&()*+,-./:;?@[\\]^_`<|>~\t\n', lower, split=' ')
text_to_word_sequence
Для конвертации текста в последовательность слов.
keras.preprocessing.text.text_to_word_sequence(text, filters='!"#$%&()*+,-./:;?@[\\]^_`<|>~\t\n', lower, split=' ')
Модуль обратного вызова
Предоставляет функции обратного вызова. Используется для изучения промежуточных результатов.
Callback
Для создания новых обратных вызовов.
keras.callbacks.callbacks.Callback()
BaseLogger
Для вычисления среднего значения метрик.
keras.callbacks.callbacks.BaseLogger(stateful_metrics)
History
Для записи событий.
keras.callbacks.callbacks.History()
ModelCheckpoint
Для сохранения модели после каждого временного промежутка.
keras.callbacks.callbacks.ModelCheckpoint(filepath, monitor='val_loss', verbose=0, save_best_only, save_weights_only, mode='auto', period=1)
Выводы
Теперь вы знакомы с разными модулями Keras и знаете, для чего они нужны.
Основные слои
keras.layers.Dense(units, activation=None, use_bias=True, kernel_initializer=’glorot_uniform’, bias_initializer=’zeros’, kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)
Просто обычный плотно связанный слой NN.
Dense реализует операцию: output = activation(dot(input, kernel) + bias), где активация — это функция активации по элементам, переданная в качестве аргумента активации, кернел — это матрица весов, созданная слоем, а смещение — это вектор смещения, созданный слоем (применимо только в случае, если use_bias — True).
Замечание: если вход в слой имеет ранг больше 2, то он сглаживается перед исходным точечным продуктом с кернелом
Пример
# как первый слой в последовательной модели:
model.add(Dense(32, input_shape=(16,)))# теперь модель будет принимать в качестве входных массивов фигуры (*, 16)# и выходных массивов фигуры (*, 32)
# после первого слоя, больше не нужно указывать# размер входного сигнала:
Аргументы
- units: положительное целое число, размерность выходного пространства.
- activation: используемая функция активации (см. активации). Если ничего не указывать, активация не применяется (т.е. «линейная» активация: a(x) = x).
- use_bias: Булева, использует ли слой вектор смещения.
- kernel_initializer: Инициализатор для матрицы весов кернела (см. инициализаторы).
- bias_initializer: Инициализатор для вектора смещения (см. инициализаторы).
- kernel_regularizer: Функция регулялизатора, применяемая к матрице весов кернела (см. регуляризатор).
- bias_regularizer: Функция регуляризатора применяется к вектору смещения (см. регуляризатор).
- activity_regularized: Функция регулялизатора применяется к выходу слоя (его «активация»). (см. регуляризатор).
- kernel_constraint: Функция ограничения, применяемая к матрице весов кернела (см. ограничения).
- bias_constraint: Функция ограничения, применяемая к вектору смещения
- Переведено с помощью www.DeepL.com/Translator (бесплатная версия) (см ограничения).
Форма ввода
тензор nD с формой: (batch_size, …, input_dim). Наиболее распространенная ситуация — 2D-ввод с формой (batch_size, input_dim).
Форма вывода
тензор nD с формой: (размер партии, …, units). Например, для 2D-входа с формой (batch_size, input_dim) выход будет иметь форму (batch_size, units).
Activation
Применяет функцию активации к выводу.
Аргументы
- activation: название используемой функции активации (см.: активации), или альтернатива: Theano или TensorFlow..
Форма ввода
Произвольно. Используйте ключевой аргумент input_shape (кортеж целых чисел, не включает ось отсчета) при использовании этого слоя в качестве первого слоя в модели.
Форма вывода
Та же форма, что и при вводе.
Dropout
keras.layers.Dropout(rate, noise_shape=None, seed=None)
Применяет исключение (дропаут) на вводе.
Dropout состоит в случайной установке доли единиц ввода в 0 при каждом обновлении во время обучения, что помогает предотвратить переобучение (оверфиттинг).
Аргументы
- rate: плавает между 0 и 1. Доля входных блоков для исключения.
- noise_shape: 1D целочисленный тензор, представляющий собой форму двоичной маски выпадения, которая будет умножаться на вход. Например, если у ваших входов есть форма (batch_size, timesteps, features) и вы хотите, чтобы маска отсева была одинаковой для всех таймсестов, вы можете использовать noise_shape=(batch_size, 1, features).
- seed: Python целое число для использования в качестве случайного сида (seed).
Ссылки
- Дропаут: Простой способ предотвратить оверфиттинг нейронных сетей.
Flatten
keras.layers.Flatten(data_format=None)
Выравнивает вход. Не влияет на размер партии.
Аргументы
- data_format: Строка, одна из channel_last (по умолчанию) или channels_first. Порядок следования размеров на входах. Назначение данного аргумента — сохранить упорядочение весов при переключении модели с одного формата данных на другой. channels_last соответствует входам с формой (пакет, …, каналы), а channels_first соответствует входам с формой (пакет, каналы, …). По умолчанию значением параметра image_data_format, найденным в конфигурационном файле Keras, является ~/.keras/keras.json. Если вы никогда не устанавливали его, то это будет «channels_last».
Пример
model.add(Conv2D(64, (3, 3),
input_shape=(3, 32, 32), padding=’same’,))# теперь: model.output_shape == (None, 64, 32, 32)
model.add(Flatten())# теперь: model.output_shape == (None, 65536)
Input
Input() используется для инстанцирования тензора Keras..
Тензор Keras — это объект тензора из подложки (Theano, TensorFlow или CNTK), который мы дополняем определенными атрибутами, позволяющими построить модель Keras, просто зная входы и выходы модели.
Например, если a, b и c — тензоры Кераса, то можно сделать: model = Model(input=[a, b], output=c].
Добавлены атрибуты Кераса: Форма Кераса: Кортеж интегральной формы, распространяемый через умозаключение формы Keras-сайд. _keras_history: Из этого слоя можно рекурсивно извлечь весь граф слоя.
Аргументы
- shape: Кортеж формы (целое число), без учета размера партии. Например, shape=(32,) указывает на то, что ожидаемым входом будут партии по 32-мерным векторам.
- batch_shape: Кортеж формы (целое число), включая размер партии. Например, batch_shape=(10, 32) указывает, что ожидаемым входом будут партии с 10 32-мерными векторами. batch_shape=(None, 32) указывает, что партии с произвольным количеством 32-мерных векторов.
- name: Необязательная строка имени для слоя. Должна быть уникальной в модели (не используйте одно и то же имя дважды). Она будет автоматически сгенерирована, если не будет предоставлена.
- dtype: Тип данных, ожидаемый на входе, в виде строки (float32, float64, int32…)
- sparse: Булева, указывающая, является ли создаваемый держатель разреженным.
- tensor: Дополнительный существующий тензор для обертывания в входной слой. При установке этого параметра слой не будет создавать тензор-платформу..
Возврат
Пример
# это логистическая регрессия в Keras. #
y = Dense(16, activation=’softmax’)(x)
model = Model(x, y)
Reshape
Реформирует выход в определенную форму.
Аргументы
- target_shape: Целевая форма. Кортеж целых чисел. Не включает ось партии.
Форма ввода
Произвольно, хотя все размеры в форме входа должны быть зафиксированы. Используйте ключевой аргумент input_shape (кортеж целых чисел, не включает ось партии) при использовании этого слоя в качестве первого слоя в модели.
Форма вывода
Пример
# как первый слой в последовательной модели.
model.add(Reshape((3, 4), input_shape=(12,)))# now: model.output_shape == (None, 3, 4)# примечание: `None` — это измерение партии.
# как промежуточный слой в последовательной модели.
model.add(Reshape((6, 2)))# теперь: model.output_shape == (None, 6, 2)
# также поддерживает умозаключение формы, используя `-1` в качестве измерения.
model.add(Reshape((-1, 2, 2)))# теперь: model.output_shape == (None, 3, 2, 2)
Permute
Сохраняет размеры входного сигнала в соответствии с заданным образцом.
Полезно, например, для соединения RNN и свёртков.
Пример
model.add(Permute((2, 1), input_shape=(10, 64)))# теперь: model.output_shape == (None, 64, 10)# примечание: `None` — измерение партии
Аргументы
- dims: Кортеж целых чисел. Шаблон простановки, не включает в себя размерность образцов. Индексирование начинается с 1. Например, (2, 1) перебирает первое и второе измерение входного параметра.
Форма ввода
Произвольно. Используйте ключевой аргумент input_shape (кортеж целых чисел, не включает ось отсчета) при использовании этого слоя в качестве первого слоя в модели.
Форма вывода
То же самое, что и Форма ввода, но с измененным порядком размеров в соответствии с заданной деталью.
RepeatVector
Повторяет ввод n раз.
Пример
model.add(Dense(32, input_dim=32))# now: model.output_shape == (None, 32)# примечание: `None` — это измерение партии.
model.add(RepeatVector(3))# теперь: model.output_shape == (None, 3, 32)
Аргументы
- n: целое число, коэффициент повторения.
Форма ввода
2D тензор формы (num_samples, features).
Форма вывода
3D тензор формы (num_samples, n, features).
Lambda
keras.layers.Lambda(function, output_shape=None, mask=None, Arguments=None)
Обертывает произвольное выражение как объект Слоя.
Примеры
# добавить слой x -> x^2
model.add(Lambda(lambda x: x ** 2))
# добавьте слой, который возвращает конкатенцию# положительной части входа и # противоположной отрицательной части.
def antirectifier(x):
x -= K.mean(x, axis=1, keepdims=True)
x = K.l2_normalize(x, axis=1)
return K.concatenate([pos, neg], axis=1)
def antirectifier_output_shape(input_shape):
assert len(shape) == 2 # только для 2D тензоров
return tuple(shape)
# добавьте слой, возвращающий произведение Адамара# и сумму из двух входных тензоров.
def hadamard_product_sum(tensors):
out1 = tensors[0] * tensors[1]
out2 = K.sum(out1, axis=-1)
return [out1, out2]
def hadamard_product_sum_output_shape(input_shapes):
assert shape1 == shape2 # в противном случае произведение Адамара невозможно
return [tuple(shape1), tuple(shape2[:-1])]
layer = Lambda(hadamard_product_sum, hadamard_product_sum_output_shape)
x_hadamard, x_sum = layer([x1, x2])
Аргументы
- function: Функция, которая должна быть оценена. В качестве первого аргумента принимает входной тензор или список тензоров.
- output_shape: Ожидаемая форма выхода из функции. Актуально только при использовании Theano. Может быть кортежом или функцией. Если кортеж кортежа, то он указывает только первое измерение вперед; размер образца принимается либо как вход: output_shape = (input_shape[0], ) + output_shape, либо как вход None и размер образца также None: output_shape = (None, ) + output_shape Если функция, то она указывает всю фигуру как функцию формы вывода: output_shape = f(input_shape)
- mask: Либо None (указывая на отсутствие маскировки), либо Тензор, указывающий на входную маску для встраивания..
- arguments: необязательный словарь ключевых слов для передачи в функцию.
Форма ввода
Произвольно. Используйте ключевой аргумент input_shape (кортеж целых чисел, не включает ось отсчета) при использовании этого слоя в качестве первого слоя в модели.
Форма вывода
Указывается аргументом output_shape (или auto-inferred при использовании TensorFlow или CNTK).
ActivityRegularization
Слой, который применяет обновление к входной деятельности, основанной на функции затрат.
Аргументы
- l1: L1 коэффициент регуляризации (положительный флоут).
- l2: L2 коэффициент регуляризации (положительный флоут).
Форма ввода
Произвольно. Используйте ключевой аргумент input_shape (кортеж целых чисел, не включает ось отсчета) при использовании этого слоя в качестве первого слоя в модели.
Форма вывода
Та же форма, что и при вводе.
Masking
Маскирует последовательность, используя значение маски для пропуска таймфреймов.
Если все возможности для заданного временного отрезка равны значению mask_value, то временной отрезок будет замаскирован (пропущен) во всех последующих слоях (до тех пор, пока они поддерживают маскировку).
Если какой-либо последующий слой не поддерживает маскировку, но получает такую входную маску, то исключение будет поднято.
Пример
Рассмотрим массив данных Numpy x формы (образцы, временные интервалы, возможности), который будет передан в LSTM слой. Вы хотите маскировать образец #0 в timestep #3, и образец #2 в timestep #5, потому что вам не хватает возможностей для этих примеров timesteps. Вы можете это сделать:
- установить x[0, 3, :] = 0. и x[2, 5, :] = 0.
- вставьте слой Masking со значением mask_value=0. перед слоем LSTM:
model.add(Masking(mask_value=0., input_shape=(timesteps, features)))
Аргументы
- mask_value: Или None, или пропустить значение маски.
SpatialDropout1D
Пространственная 1D версия Dropout.
Эта версия выполняет ту же функцию, что и Dropout, однако вместо отдельных элементов выпадают целые карты 1D-функций. Если соседние кадры на картах объектов сильно коррелированы (как это обычно бывает в ранних слоях свертки), то регулярное отсеивание не приводит к регуляризации активаций, а в противном случае просто приводит к снижению эффективности обучения. В этом случае, SpatialDropout1D будет способствовать независимости между картами объектов и должен использоваться вместо этого..
Аргументы
- rate: флоут между 0 и 1. доля входных блоков для исключения.
Форма ввода
3D тензор с формой: (samples, timesteps, channels)
Форма вывода
То же, что и при вводе
Ссылки
- Эффективная локализация объектов с помощью свёрточных сетей
SpatialDropout2D
keras.layers.SpatialDropout2D(rate, data_format=None)
Пространственная 2D версия Dropout.
Эта версия выполняет ту же функцию, что и Dropout, однако вместо отдельных элементов выпадают целые карты 2D-функций. Если смежные пиксели на картах объектов сильно коррелированы (как это обычно бывает в ранних слоях свертки), то регулярное отсеивание не приводит к регуляризации активаций, а в противном случае просто приводит к снижению эффективности обучения. В этом случае, SpatialDropout2D будет способствовать независимости между картами объектов и должен использоваться вместо них.
Аргументы
- rate: флоут между 0 и 1. доля входных блоков для падения.
- data_format: ‘channels_first’ или ‘channels_last’. В режиме ‘channels_first’ размерность каналов (глубина) находится на индексе 1, в режиме ‘channels_last’ — на индексе 3. По умолчанию она равна значению image_data_format, найденному в вашем конфигурационном файле Keras по адресу ~/.keras/keras.json. Если вы никогда не устанавливали его, то это будет «channels_last».
Форма ввода
4D тензор с формов: (samples, channels, rows, cols) если data_format=’channels_first’ или 4D тензор с формов: (samples, rows, cols, channels) если data_format=’channels_last’.
Форма вывода
То же, что и при вводе
Ссылки
- Эффективная локализация объектов с помощью свёрточных сетей
SpatialDropout3D
keras.layers.SpatialDropout3D(rate, data_format=None)
Пространственная 3D версия Dropout.
Эта версия выполняет ту же функцию, что и Dropout, однако она удаляет целые карты 3D-функций вместо отдельных элементов. Если соседние воксели на картах объектов сильно коррелированы (как это обычно бывает в ранних слоях свертки), то регулярное отсеивание не приводит к регуляризации активаций, а в противном случае просто приводит к снижению эффективности обучения. В этом случае, SpatialDropout3D будет способствовать независимости между картами объектов и должен использоваться вместо них.
Аргументы
- rate: флоут между 0 и 1. доля входных блоков для исключения.
- data_format: ‘channels_first’ или ‘channels_last’. В режиме ‘channels_first’ размерность каналов (глубина) находится на индексе 1, в режиме ‘channels_last’ — на индексе 4. По умолчанию она равна значению image_data_format, найденному в вашем конфигурационном файле Keras по адресу ~/.keras/keras.json. Если вы никогда не устанавливали его, то это будет «channels_last».
Форма ввода
5D тензор с формой: (samples, channels, dim1, dim2, dim3) если data_format=’channels_first’ или тензор с формой: (samples, dim1, dim2, dim3, channels) если data_format=’channels_last’.
Форма вывода
То же, что и при вводе
Ссылки
- Эффективная локализация объектов с помощью свёрточных сетей
Обзор Keras для TensorFlow
tf.keras является реализацией TensorFlow спецификации Keras API. Это высокоуровневый API для построения и обучения моделей включающий первоклассную поддержку для TensorFlow-специфичной функциональности, такой как eager execution, конвейеры tf.data , и Estimators. tf.keras делает использование TensorFlow проще не жертвуя при этом гибкостью и, производительностью.
Для начала, импортируйте tf.keras как часть установки вашей TensorFlow:
from __future__ import absolute_import, division, print_function, unicode_literals import tensorflow as tf from tensorflow import keras
tf.keras может выполнять любой Keras-совместимый код, но имейте ввиду:
- Версия tf.keras в последнем релизе TensorFlow может отличаться от последней версии keras в PyPI. Проверьте tf.keras.__version__ .
- Когда сохраняете веса моделей, tf.keras делает это по умолчанию в формате checkpoint. Передайте параметр save_format=’h5′ для использования HDF5 (или добавьте к имени файла расширение .h5 ).
Постройте простую модель
Последовательная модель
В Keras, вы собираете слои (layers) для построения моделей (models). Модель это (обычно) граф слоев. Наиболее распространенным видом модели является стек слоев: модель tf.keras.Sequential .
Построим простую полносвязную сеть (т.е. многослойный перцептрон):
from tensorflow.keras import layers model = tf.keras.Sequential() # Добавим к модели полносвязный слой с 64 узлами: model.add(layers.Dense(64, activation='relu')) # Добавим другой слой: model.add(layers.Dense(64, activation='relu')) # Добавим слой softmax с 10 выходами: model.add(layers.Dense(10, activation='softmax'))
Настройте слои
Доступно много разновидностей слоев tf.keras.layers . Большинство из них используют общий конструктор аргументов:
- activation : Установка функции активации для слоя. В этом параметре указывается имя встроенной функции или вызываемый объект. У параметра нет значения по умолчанию.
- kernel_initializer и bias_initializer : Схемы инициализации создающие веса слоя (ядро и сдвиг). В этом параметре может быть имя или вызываемый объект. По умолчанию используется инициализатор «Glorot uniform» .
- kernel_regularizer и bias_regularizer : Схемы регуляризации добавляемые к весам слоя (ядро и сдвиг), такие как L1 или L2 регуляризации. По умолчанию регуляризация не устанавливается.
# Создадим слой с сигмоидой: layers.Dense(64, activation='sigmoid') # Или: layers.Dense(64, activation=tf.keras.activations.sigmoid) # Линейный слой с регуляризацией L1 с коэфициентом 0.01 примененной к матрице ядра: layers.Dense(64, kernel_regularizer=tf.keras.regularizers.l1(0.01)) # Линейный слой с регуляризацией L2 с коэффициентом 0.01 примененной к вектору сдвига: layers.Dense(64, bias_regularizer=tf.keras.regularizers.l2(0.01)) # Линейный слой с ядром инициализированным случайной ортогональной матрицей: layers.Dense(64, kernel_initializer='orthogonal') # Линейный слой с вектором сдвига инициализированным значениями 2.0: layers.Dense(64, bias_initializer=tf.keras.initializers.Constant(2.0))
Обучение и оценка
Настройка обучения
После того как модель сконструирована, настройте процесс ее обучения вызовом метода compile :
model = tf.keras.Sequential([ # Добавляем полносвязный слой с 64 узлами к модели: layers.Dense(64, activation='relu', input_shape=(32,)), # Добавляем другой: layers.Dense(64, activation='relu'), # Добавляем слой softmax с 10 выходами: layers.Dense(10, activation='softmax')]) model.compile(optimizer=tf.keras.optimizers.Adam(0.01), loss='categorical_crossentropy', metrics=['accuracy'])
tf.keras.Model.compile принимает три важных аргумента:
- optimizer : Этот объект определяет процедуру обучения. Передайте в него экземпляры оптимизатора из модуля tf.keras.optimizers , такие как tf.keras.optimizers.Adam или tf.keras.optimizers.SGD . Если вы просто хотите использовать параметры по умолчанию, вы также можете указать оптимизаторы ключевыми словами, такими как ‘adam’ или ‘sgd’ .
- loss : Это функция которая минимизируется в процессе обучения. Среди распространенных вариантов среднеквадратичная ошибка ( mse ), categorical_crossentropy , binary_crossentropy . Функции потерь указываются по имени или передачей вызываемого объекта из модуля tf.keras.losses .
- metrics : Используются для мониторинга обучения. Это строковые имена или вызываемые объекты из модуля tf.keras.metrics .
- Кроме того, чтобы быть уверенным, что модель обучается и оценивается eagerly, проверьте что вы передали компилятору параметр run_eagerly=True
# Сконфигурируем модель для регрессии со среднеквадратичной ошибкой. model.compile(optimizer=tf.keras.optimizers.Adam(0.01), loss='mse', # mean squared error metrics=['mae']) # mean absolute error # Сконфигурируем модель для категориальной классификации. model.compile(optimizer=tf.keras.optimizers.RMSprop(0.01), loss=tf.keras.losses.CategoricalCrossentropy(), metrics=[tf.keras.metrics.CategoricalAccuracy()])
Обучение на данных NumPy
Для небольших датасетов используйте помещающиеся в память массивы NumPy для обучения и оценки модели. Модель «обучается» на тренировочных данных, используя метод `fit`:
import numpy as np data = np.random.random((1000, 32)) labels = np.random.random((1000, 10)) model.fit(data, labels, epochs=10, batch_size=32)
tf.keras.Model.fit принимает три важных аргумента:
- epochs : Обучение разбито на *эпохи*. Эпоха это одна итерация по всем входным данным (это делается небольшими партиями).
- batch_size : При передаче данных NumPy, модель разбивает данные на меньшие блоки (batches) и итерирует по этим блокам во время обучения. Это число указывает размер каждого блока данных. Помните, что последний блок может быть меньшего размера если общее число записей не делится на размер партии.
- validation_data : При прототипировании модели вы хотите легко отслеживать её производительность на валидационных данных. Передача с этим аргументом кортежа входных данных и меток позволяет модели отображать значения функции потерь и метрики в режиме вывода для передаваемых данных в конце каждой эпохи.
import numpy as np data = np.random.random((1000, 32)) labels = np.random.random((1000, 10)) val_data = np.random.random((100, 32)) val_labels = np.random.random((100, 10)) model.fit(data, labels, epochs=10, batch_size=32, validation_data=(val_data, val_labels))
Обучение с использованием наборов данных tf.data
Используйте Datasets API для масштабирования больших баз данных или обучения на нескольких устройствах. Передайте экземпляр `tf.data.Dataset` в метод fit :
# Создает экземпляр учебного датасета: dataset = tf.data.Dataset.from_tensor_slices((data, labels)) dataset = dataset.batch(32) model.fit(dataset, epochs=10)
Поскольку Dataset выдает данные пакетами, этот кусок кода не требует аргумента batch_size .
Датасеты могут быть также использованы для валидации:
dataset = tf.data.Dataset.from_tensor_slices((data, labels)) dataset = dataset.batch(32) val_dataset = tf.data.Dataset.from_tensor_slices((val_data, val_labels)) val_dataset = val_dataset.batch(32) model.fit(dataset, epochs=10, validation_data=val_dataset)
Оценка и предсказание
Методы tf.keras.Model.evaluate и tf.keras.Model.predict могут использовать данные NumPy и tf.data.Dataset .
Вот так можно оценить потери в режиме вывода и метрики для предоставленных данных:
# С массивом Numpy data = np.random.random((1000, 32)) labels = np.random.random((1000, 10)) model.evaluate(data, labels, batch_size=32) # С датасетом dataset = tf.data.Dataset.from_tensor_slices((data, labels)) dataset = dataset.batch(32) model.evaluate(dataset)
А вот как предсказать вывод последнего уровня в режиме вывода для предоставленных данных в виде массива NumPy:
Построение сложных моделей
The Functional API
Модель tf.keras.Sequential это простой стек слоев с помощью которого нельзя представить произвольную модель. Используйте Keras functional API для построения сложных топологий моделей, таких как:
- Модели с несколькими входами,
- Модели с несколькими выходами,
- Модели с общими слоями (один и тот же слой вызывается несколько раз),
- Модели с непоследовательными потоками данных (напр. остаточные связи).
- Экземпляр слоя является вызываемым и возвращает тензор.
- Входные и выходные тензоры используются для определения экземпляра tf.keras.Model
- Эта модель обучается точно так же как и `Sequential` модель.
inputs = tf.keras.Input(shape=(32,)) # Возвращает входной плейсхолдер # Экземпляр слоя вызывается на тензор и возвращает тензор. x = layers.Dense(64, activation='relu')(inputs) x = layers.Dense(64, activation='relu')(x) predictions = layers.Dense(10, activation='softmax')(x)
Создайте экземпляр модели с данными входами и выходами.
model = tf.keras.Model(inputs=inputs, outputs=predictions) # Шаг компиляции определяет конфигурацию обучения. model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001), loss='categorical_crossentropy', metrics=['accuracy']) # Обучение за 5 эпох model.fit(data, labels, batch_size=32, epochs=5)
Сабклассинг моделей
Создайте полностью настраиваемую модель с помощью сабклассинга tf.keras.Model и определения вашего собственного прямого распространения. Создайте слои в методе __init__ и установите их как атрибуты экземпляра класса. Определите прямое распространение в методе call .
Сабклассинг модели особенно полезен когда включен eager execution, поскольку он позволяет написать прямое распространение императивно.
Примечание: если вам нужно чтобы ваша модель всегда выполнялась императивно, вы можете установить dynamic=True когда вызываете конструктор super .
Ключевой момент: Используйте правильный API для работы. Хоть сабклассинг модели обеспечивает гибкость, за нее приходится платить большей сложностью и большими возможностями для пользовательских ошибок. Если это возможно выбирайте functional API.
Следующий пример показывает сабклассированную модель tf.keras.Model использующую пользовательское прямое распространение, которое не обязательно выполнять императивно:
class MyModel(tf.keras.Model): def __init__(self, num_classes=10): super(MyModel, self).__init__(name='my_model') self.num_classes = num_classes # Определим свои слои тут. self.dense_1 = layers.Dense(32, activation='relu') self.dense_2 = layers.Dense(num_classes, activation='sigmoid') def call(self, inputs): # Определим тут свое прямое распространение, # с использованием ранее определенных слоев (в `__init__`). x = self.dense_1(inputs) return self.dense_2(x)
Создайте экземпляр класса новой модели:
model = MyModel(num_classes=10) # Шаг компиляции определяет конфигурацию обучения. model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001), loss='categorical_crossentropy', metrics=['accuracy']) # Обучение за 5 эпох. model.fit(data, labels, batch_size=32, epochs=5)
Пользовательские слои
Создайте пользовательский слой сабклассингом tf.keras.layers.Layer и реализацией следующих методов:
- __init__ : Опционально определите подслои которые будут использоваться в этом слое.
- * build : Создайте веса слоя. Добавьте веса при помощи метода add_weight
- call : Определите прямое распространение.
- Опционально, слой может быть сериализован реализацией метода get_config и метода класса from_config .
class MyLayer(layers.Layer): def __init__(self, output_dim, **kwargs): self.output_dim = output_dim super(MyLayer, self).__init__(**kwargs) def build(self, input_shape): # Создадим обучаемую весовую переменную для этого слоя. self.kernel = self.add_weight(name='kernel', shape=(input_shape[1], self.output_dim), initializer='uniform', trainable=True) def call(self, inputs): return tf.matmul(inputs, self.kernel) def get_config(self): base_config = super(MyLayer, self).get_config() base_config['output_dim'] = self.output_dim return base_config @classmethod def from_config(cls, config): return cls(**config)
Создайте модель с использованием вашего пользовательского слоя:
model = tf.keras.Sequential([ MyLayer(10), layers.Activation('softmax')]) # Шаг компиляции определяет конфигурацию обучения model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001), loss='categorical_crossentropy', metrics=['accuracy']) # Обучение за 5 эпох. model.fit(data, labels, batch_size=32, epochs=5)
Колбеки
Колбек это объект переданный модели чтобы кастомизировать и расширить ее поведение во время обучения. Вы можете написать свой пользовательский колбек или использовать встроенный tf.keras.callbacks который включает в себя:
tf.keras.callbacks.ModelCheckpoint : Сохранение контрольных точек модели за регулярные интервалы.
tf.keras.callbacks.LearningRateScheduler : Динамичное изменение шага обучения.
tf.keras.callbacks.EarlyStopping : Остановка обучения в том случае когда результат при валидации перестает улучшаться.
tf.keras.callbacks.TensorBoard: Мониторинг поведения модели с помощью
TensorBoard
Для использования tf.keras.callbacks.Callback , передайте ее методу модели fit :
callbacks = [ # Остановить обучение если `val_loss` перестанет улучшаться в течение 2 эпох tf.keras.callbacks.EarlyStopping(patience=2, monitor='val_loss'), # Записать логи TensorBoard в каталог `./logs` directory tf.keras.callbacks.TensorBoard(log_dir='./logs') ] model.fit(data, labels, batch_size=32, epochs=5, callbacks=callbacks, validation_data=(val_data, val_labels))
Сохранение и восстановление
Сохранение только значений весов
Сохраните и загрузите веса модели с помощью tf.keras.Model.save_weights :
model = tf.keras.Sequential([ layers.Dense(64, activation='relu', input_shape=(32,)), layers.Dense(10, activation='softmax')]) model.compile(optimizer=tf.keras.optimizers.Adam(0.001), loss='categorical_crossentropy', metrics=['accuracy'])
# Сохраним веса в файл TensorFlow Checkpoint model.save_weights('./weights/my_model') # Восстановим состояние модели # для этого необходима модель с такой же архитектурой. model.load_weights('./weights/my_model')
По умолчанию веса модели сохраняются в формате TensorFlow checkpoint. Веса могут быть также сохранены в формате Keras HDF5 (значение по умолчанию для универсальной реализации Keras):
# Сохранение весов в файл HDF5 model.save_weights('my_model.h5', save_format='h5') # Восстановление состояния модели model.load_weights('my_model.h5')
Сохранение только конфигурации модели
Конфигурация модели может быть сохранена — это сериализует архитектуру модели без всяких весов. Сохраненная конфигурация может восстановить и инициализировать ту же модель, даже без кода определяющего исходную модель. Keras поддерживает форматы сериализации JSON и YAML:
# Сериализация модели в формат JSON json_string = model.to_json() json_string
import json import pprint pprint.pprint(json.loads(json_string))
Восстановление модели (заново инициализированной) из JSON:
fresh_model = tf.keras.models.model_from_json(json_string)
Сериализация модели в формат YAML требует установки `pyyaml` перед тем как импортировать TensorFlow:
yaml_string = model.to_yaml() print(yaml_string)
Восстановление модели из YAML:
fresh_model = tf.keras.models.model_from_yaml(yaml_string)
Внимание: сабклассированные модели не сериализуемы, потому что их архитектура определяется кодом Python в теле метода `call`.
Сохранение всей модели в один файл
Вся модель может быть сохранена в файл содержащий значения весов, конфигурацию модели, и даже конфигурацию оптимизатора. Это позволит вам установить контрольную точку модели и продолжить обучение позже с точно того же положения даже без доступа к исходному коду.
# Создадим простую модель model = tf.keras.Sequential([ layers.Dense(10, activation='softmax', input_shape=(32,)), layers.Dense(10, activation='softmax') ]) model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) model.fit(data, labels, batch_size=32, epochs=5) # Сохраним всю модель в файл HDF5 model.save('my_model.h5') # Пересоздадим в точности эту модель включая веса и оптимизатор. model = tf.keras.models.load_model('my_model.h5')
Eager execution
Eager execution — это императивное программирование среда которая выполняет операции немедленно. Это не требуется для Keras, но поддерживается tf.keras и полезно для проверки вашей программы и отладки.
Все строящие модели API `tf.keras` совместимы eager execution. И хотя могут быть использованы `Sequential` и functional API, eager execution особенно полезно при сабклассировании модели и построении пользовательских слоев — эти API требуют от вас написание прямого распространения в виде кода (вместо API которые создают модели путем сборки существующих слоев).
Распределение
Множественные GPU
tf.keras модели можно запускать на множестве GPU с использованием tf.distribute.Strategy . Этот API обеспечивает распределенное обучение на нескольких GPU практически без изменений в существующем коде.
На данный момент, tf.distribute.MirroredStrategy единственная поддерживаемая стратегия распределения. MirroredStrategy выполняет репликацию в графах с
синхронным обучением используя all-reduce на одной машине. Для использования ` distribute.Strategy `, вложите инсталляцию оптимизатора, конструкцию и компиляцию модели в ` Strategy ` ` .scope() `, затем обучите модель.
Следующий пример распределяет tf.keras.Model между множеством GPU на одной машине.
Сперва определим модель внутри области распределенной стратегии:
strategy = tf.distribute.MirroredStrategy() with strategy.scope(): model = tf.keras.Sequential() model.add(layers.Dense(16, activation='relu', input_shape=(10,))) model.add(layers.Dense(1, activation='sigmoid')) optimizer = tf.keras.optimizers.SGD(0.2) model.compile(loss='binary_crossentropy', optimizer=optimizer) model.summary()
Затем обучим модель на данных как обычно:
x = np.random.random((1024, 10)) y = np.random.randint(2, size=(1024, 1)) x = tf.cast(x, tf.float32) dataset = tf.data.Dataset.from_tensor_slices((x, y)) dataset = dataset.shuffle(buffer_size=1024).batch(32) model.fit(dataset, epochs=1)
После проверки перевод появится также на сайте Tensorflow.org. Если вы хотите поучаствовать в переводе документации сайта Tensorflow.org на русский, обращайтесь в личку или комментарии. Любые исправления и замечания приветствуются.
- keras
- tensorflow
- машинное обучение
- глубокое обучение
- Python
- Big Data
- Машинное обучение
- Искусственный интеллект
- TensorFlow
Библиотеки для глубокого обучения: Keras
Привет, Хабр! Мы уже говорили про Theano и Tensorflow (а также много про что еще), а сегодня сегодня пришло время поговорить про Keras.
Изначально Keras вырос как удобная надстройка над Theano. Отсюда и его греческое имя — κέρας, что значит «рог» по-гречески, что, в свою очередь, является отсылкой к Одиссее Гомера. Хотя, с тех пор утекло много воды, и Keras стал сначала поддерживать Tensorflow, а потом и вовсе стал его частью. Впрочем, наш рассказ будет посвящен не сложной судьбе этого фреймворка, а его возможностям. Если вам интересно, добро пожаловать под кат.
Начать стоит от печки, то есть с оглавления.
- [Установка]
- [Бэкенды]
- [Практический пример]
- [Данные]
- [Модель]
- [Sequential API]
- [Functional API]
- [Tensorboard]
Установка
Установка Keras чрезвычайно проста, т.к. он является обычным питоновским пакетом:
pip install keras
Теперь мы можем приступить к его разбору, но сначала поговорим про бэкенды.
ВНИМАНИЕ: Чтобы работать с Keras, у вас уже должен быть установлен хотя бы один из фреймворков — Theano или Tensorflow.
Бэкенды
Бэкенды — это то, из-за чего Keras стал известен и популярен (помимо прочих достоинств, которые мы разберем ниже). Keras позволяет использовать в качестве бэкенда разные другие фреймворки. При этом написанный вами код будет исполняться независимо от используемого бэкенда. Начиналась разработка, как мы уже говорили, с Theano, но со временем добавился Tensorflow. Сейчас Keras по умолчанию работает именно с ним, но если вы хотите использовать Theano, то есть два варианта, как это сделать:
-
Отредактировать файл конфигурации keras.json, который лежит по пути $HOME/.keras/keras.json (или %USERPROFILE%\.keras\keras.json в случае операционных систем семейства Windows). Нам нужно поле backend :
KERAS_BACKEND=theano python -c "from keras import backend" Using Theano backend.
Стоит отметить, что сейчас ведется работа по написанию биндингов для CNTK от Microsoft, так что через некоторое время появится еще один доступный бэкенд. Следить за этим можно здесь.
Также существует MXNet Keras backend, который пока не обладает всей функциональностью, но если вы используете MXNet, вы можете обратить внимание на такую возможность.
Еще существует интересный проект Keras.js, дающий возможность запускать натренированные модели Keras из браузера на машинах, где есть GPU.
Так что бэкенды Keras ширятся и со временем захватят мир! (Но это неточно.)
Практический пример
В прошлых статьях много внимания было уделено описанию работы классических моделей машинного обучения на описываемых фреймворках. Кажется, теперь мы можем взять в качестве примера [не очень] глубокую нейронную сеть.
Данные
Обучение любой модели в машинном обучении начинается с данных. Keras содержит внутри несколько обучающих датасетов, но они уже приведены в удобную для работы форму и не позволяют показать всю мощь Keras. Поэтому мы возьмем более сырой датасет. Это будет датасет 20 newsgroups — 20 тысяч новостных сообщений из групп Usenet (это такая система обмена почтой родом из 1990-х, родственная FIDO, который, может быть, чуть лучше знаком читателю) примерно поровну распределенных по 20 категориям. Мы будем учить нашу сеть правильно распределять сообщения по этим новостным группам.
from sklearn.datasets import fetch_20newsgroups newsgroups_train = fetch_20newsgroups(subset='train') newsgroups_test = fetch_20newsgroups(subset='test')
Вот пример содержания документа из обучающей выборки:
newsgroups_train[‘data’][0]
From: lerxst@wam.umd.edu (where’s my thing)
Subject: WHAT car is this!?
Nntp-Posting-Host: rac3.wam.umd.edu
Organization: University of Maryland, College Park
Lines: 15I was wondering if anyone out there could enlighten me on this car I saw
the other day. It was a 2-door sports car, looked to be from the late 60s/
early 70s. It was called a Bricklin. The doors were really small. In addition,
the front bumper was separate from the rest of the body. This is
all I know. If anyone can tellme a model name, engine specs, years
of production, where this car is made, history, or whatever info you
have on this funky looking car, please e-mail.- IL
— brought to you by your neighborhood Lerxst —-
Препроцессинг
Keras содержит в себе инструменты для удобного препроцессинга текстов, картинок и временных рядов, иными словами, самых распространенных типов данных. Сегодня мы работаем с текстами, поэтому нам нужно разбить их на токены и привести в матричную форму.
tokenizer = Tokenizer(num_words=max_words) tokenizer.fit_on_texts(newsgroups_train["data"]) # теперь токенизатор знает словарь для этого корпуса текстов x_train = tokenizer.texts_to_matrix(newsgroups_train["data"], mode='binary') x_test = tokenizer.texts_to_matrix(newsgroups_test["data"], mode='binary')
На выходе у нас получились бинарные матрицы вот таких размеров:
x_train shape: (11314, 1000) x_test shape: (7532, 1000)
Первое число — количество документов в выборке, а второе — размер нашего словаря (одна тысяча в этом примере).
Еще нам понадобится преобразовать метки классов к матричному виду для обучения с помощью кросс-энтропии. Для этого мы переведем номер класса в так называемый one-hot вектор, т.е. вектор, состоящий из нулей и одной единицы:
y_train = keras.utils.to_categorical(newsgroups_train["target"], num_classes) y_test = keras.utils.to_categorical(newsgroups_test["target"], num_classes)
На выходе получим также бинарные матрицы вот таких размеров:
y_train shape: (11314, 20) y_test shape: (7532, 20)
Как мы видим, размеры этих матриц частично совпадают с матрицами данных (по первой координате — числу документов в обучающей и тестовой выборках), а частично — нет. По второй координате у нас стоит число классов (20, как следует из названия датасета).
Все, теперь мы готовы учить нашу сеть классифицировать новости!
Модель
Модель в Keras можно описать двумя основными способами:
Sequential API
Первый — последовательное описание модели, например, вот так:
model = Sequential() model.add(Dense(512, input_shape=(max_words,))) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(num_classes)) model.add(Activation('softmax'))
model = Sequential([ Dense(512, input_shape=(max_words,)), Activation('relu'), Dropout(0.5), Dense(num_classes), Activation('softmax') ])
Functional API
Некоторое время назад появилась возможность использовать функциональное API для создания модели — второй способ:
a = Input(shape=(max_words,)) b = Dense(512)(a) b = Activation('relu')(b) b = Dropout(0.5)(b) b = Dense(num_classes)(b) b = Activation('softmax')(b) model = Model(inputs=a, outputs=b)
Принципиального отличия между способами нет, выбирайте, какой вам больше по душе.
Класс Model (и унаследованный от него Sequential ) имеет удобный интерфейс, позволяющий посмотреть, какие слои входят в модель — model.layers , входы — model.inputs , и выходы — model.outputs .Также очень удобный метод отображения и сохранения модели — model.to_yaml .
Под спойлером его вывод для нашей модели.
backend: tensorflow class_name: Model config: input_layers: - [input_4, 0, 0] layers: - class_name: InputLayer config: batch_input_shape: !!python/tuple [null, 1000] dtype: float32 name: input_4 sparse: false inbound_nodes: [] name: input_4 - class_name: Dense config: activation: linear activity_regularizer: null bias_constraint: null bias_initializer: class_name: Zeros config: <> bias_regularizer: null kernel_constraint: null kernel_initializer: class_name: VarianceScaling config: kernel_regularizer: null name: dense_10 trainable: true units: 512 use_bias: true inbound_nodes: - - - input_4 - 0 - 0 - <> name: dense_10 - class_name: Activation config: inbound_nodes: - - - dense_10 - 0 - 0 - <> name: activation_9 - class_name: Dropout config: inbound_nodes: - - - activation_9 - 0 - 0 - <> name: dropout_5 - class_name: Dense config: activation: linear activity_regularizer: null bias_constraint: null bias_initializer: class_name: Zeros config: <> bias_regularizer: null kernel_constraint: null kernel_initializer: class_name: VarianceScaling config: kernel_regularizer: null name: dense_11 trainable: true units: !!python/object/apply:numpy.core.multiarray.scalar - !!python/object/apply:numpy.dtype args: [i8, 0, 1] state: !!python/tuple [3, name: dense_11 - class_name: Activation config: inbound_nodes: - - - dense_11 - 0 - 0 - <> name: activation_10 name: model_1 output_layers: - [activation_10, 0, 0] keras_version: 2.0.2
Это позволяет сохранять модели в человеко-читаемом виде, а также инстанциировать модели из такого описания:
from keras.models import model_from_yaml yaml_string = model.to_yaml() model = model_from_yaml(yaml_string)
Важно отметить, что модель, сохраненная в текстовом виде (кстати, возможно сохранение также и в JSON) не содержит весов. Для сохранения и загрузки весов используйте функции save_weights и load_weights соответственно.
Визуализация модели
Нельзя обойти стороной визуализацию. Keras имеет встроенную визуализацию для моделей:
from keras.utils import plot_model plot_model(model, to_file='model.png', show_shapes=True)
Этот код сохранит под именем model.png вот такую картинку:
Здесь мы дополнительно отобразили размеры входов и выходов для слоев. None , идущий первым в кортеже размеров — это размерность батча. Т.к. стоит None , то батч может быть произвольным.
Если вы захотите отобразить ее в jupyter -ноутбуке, вам нужен немного другой код:
from IPython.display import SVG from keras.utils.vis_utils import model_to_dot SVG(model_to_dot(model, show_shapes=True).create(prog='dot', format='svg'))
Важно отметить, что для визуализации нужен пакет graphviz, а также питоновский пакет pydot . Есть тонкий момент, что для корректной работы визуализации пакет pydot из репозитория не пойдет, нужно взять его обновленную версию pydot-ng .
pip install pydot-ng
Пакет graphviz в Ubuntu ставится так (в других дистрибутивах Linux аналогично):
apt install graphviz
На MacOS (используя систему пакетов HomeBrew):
brew install graphviz
Инструкцию установки на Windows можно посмотреть здесь.
Подготовка модели к работе
Итак, мы сформировали нашу модель. Теперь нужно подготовить ее к работе:
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
Что означают параметры функции compile ? loss — это функция ошибки, в нашем случае — это перекрестная энтропия, именно для нее мы подготавливали наши метки в виде матриц; optimizer — используемый оптимизатор, здесь мог бы быть обычный стохастический градиентный спуск, но Adam показывает лучшую сходимость на этой задаче; metrics — метрики, по которым считается качество модели, в нашем случае — это точность (accuracy), то есть доля верно угаданных ответов.
Custom loss
Несмотря на то, что Keras содержит большинство популярных функций ошибки, для вашей задачи может потребоваться что-то уникальное. Чтобы сделать свой собственный loss , нужно немного: просто определить функцию, принимающую векторы правильных и предсказанных ответов и выдающую одно число на выход. Для тренировки сделаем свою функцию расчета перекрестной энтропии. Чтобы она чем-то отличалась, введем так называемый clipping — обрезание значений вектора сверху и снизу. Да, еще важное замечание: нестандартный loss может быть необходимо описывать в терминах нижележащего фреймворка, но мы можем обойтись средствами Keras.
from keras import backend as K epsilon = 1.0e-9 def custom_objective(y_true, y_pred): '''Yet another cross-entropy''' y_pred = K.clip(y_pred, epsilon, 1.0 - epsilon) y_pred /= K.sum(y_pred, axis=-1, keepdims=True) cce = categorical_crossentropy(y_pred, y_true) return cce
Здесь y_true и y_pred — тензоры из Tensorflow, поэтому для их обработки используются функции Tensorflow.
Для использования другой функции потерь достаточно изменить значения параметра loss функции compile , передав туда объект нашей функции потерь (в питоне функции — тоже объекты, хотя это уже совсем другая история):
model.compile(loss=custom_objective, optimizer='adam', metrics=['accuracy'])
Обучение и тестирование
Наконец, пришло время для обучения модели:
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_split=0.1)
Метод fit делает именно это. Он принимает на вход обучающую выборку вместе с метками — x_train и y_train , размером батча batch_size , который ограничивает количество примеров, подаваемых за раз, количеством эпох для обучения epochs (одна эпоха — это один раз полностью пройденная моделью обучающая выборка), а также тем, какую долю обучающей выборки отдать под валидацию — validation_split .
Возвращает этот метод history — это история ошибок на каждом шаге обучения.
И наконец, тестирование. Метод evaluate получает на вход тестовую выборку вместе с метками для нее. Метрика была задана еще при подготовке к работе, так что больше ничего не нужно. (Но мы укажем еще размер батча).
score = model.evaluate(x_test, y_test, batch_size=batch_size)
Callbacks
Нужно также сказать несколько слов о такой важной особенности Keras, как колбеки. Через них реализовано много полезной функциональности. Например, если вы тренируете сеть в течение очень долгого времени, вам нужно понять, когда пора остановиться, если ошибка на вашем датасете перестала уменьшаться. По-английски описываемая функциональность называется «early stopping» («ранняя остановка»). Посмотрим, как мы можем применить его при обучении нашей сети:
from keras.callbacks import EarlyStopping early_stopping=EarlyStopping(monitor='value_loss') history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_split=0.1, callbacks=[early_stopping])
Проведите эксперимент и проверьте, как быстро сработает early stopping в нашем примере?
Tensorboard
Еще в качестве колбека можно использовать сохранение логов в формате, удобном для Tensorboard (о нем разговор был в статье про Tensorflow, вкратце — это специальная утилита для обработки и визуализации информации из логов Tensorflow).
from keras.callbacks import TensorBoard tensorboard=TensorBoard(log_dir='./logs', write_graph=True) history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_split=0.1, callbacks=[tensorboard])
После того, как обучение закончится (или даже в процессе!), вы можете запустить Tensorboard , указав абсолютный путь к директории с логами:
tensorboard --logdir=/path/to/logs
Там можно посмотреть, например, как менялась целевая метрика на валидационной выборке:
(Кстати, тут можно заметить, что наша сеть переобучается.)
Продвинутые графы
Теперь рассмотрим построение чуть более сложного графа вычислений. У нейросети может быть множество входов и выходов, входные данные могут преобразовываться разнообразными отображениями. Для переиспользования частей сложных графов (в частности, для transfer learning ) имеет смысл описывать модель в модульном стиле, позволяющем удобным образом извлекать, сохранять и применять к новым входным данным куски модели.
Наиболее удобно описывать модель, смешивая оба способа — Functional API и Sequential API , описанные ранее.
Рассмотрим этот подход на примере модели Siamese Network. Схожие модели активно используются на практике для получения векторных представлений, обладающих полезными свойствами. Например, подобная модель может быть использована для того, чтобы выучить такое отображение фотографий лиц в вектор, что вектора для похожих лиц будут близко друг к другу. В частности, этим пользуются приложения поиска по изображениям, такие как FindFace.
Иллюстрацию модели можно видеть на диаграмме:
Здесь функция G превращает входную картинку в вектор, после чего вычисляется расстояние между векторами для пары картинок. Если картинки из одного класса, расстояние нужно минимизировать, если из разных — максимизировать.
После того, как такая нейросеть будет обучена, мы сможем представить произвольную картинку в виде вектора G(x) и использовать это представление либо для поиска ближайших изображений, либо как вектор признаков для других алгоритмов машинного обучения.
Будем описывать модель в коде соответствующим образом, максимально упростив извлечение и переиспользование частей нейросети.
Сначала определим на Keras функцию, отображающую входной вектор.
def create_base_network(input_dim): seq = Sequential() seq.add(Dense(128, input_shape=(input_dim,), activation='relu')) seq.add(Dropout(0.1)) seq.add(Dense(128, activation='relu')) seq.add(Dropout(0.1)) seq.add(Dense(128, activation='relu')) return seq
Обратите внимание: мы описали модель с помощью Sequential API , однако обернули ее создание в функцию. Теперь мы можем создать такую модель, вызвав эту функцию, и применить ее с помощью Functional API ко входным данным:
base_network = create_base_network(input_dim) input_a = Input(shape=(input_dim,)) input_b = Input(shape=(input_dim,)) processed_a = base_network(input_a) processed_b = base_network(input_b)
Теперь в переменных processed_a и processed_b лежат векторные представления, полученные путем применения сети, определенной ранее, к входным данным.
Нужно посчитать между ними расстояния. Для этого в Keras предусмотрена функция-обертка Lambda , представляющая любое выражение как слой ( Layer ). Не забудьте, что мы обрабатываем данные в батчах, так что у всех тензоров всегда есть дополнительная размерность, отвечающая за размер батча.
from keras import backend as K def euclidean_distance(vects): x, y = vects return K.sqrt(K.sum(K.square(x - y), axis=1, keepdims=True)) distance = Lambda(euclidean_distance)([processed_a, processed_b])
Отлично, мы получили расстояние между внутренними представлениями, теперь осталось собрать входы и расстояние в одну модель.
model = Model([input_a, input_b], distance)
Благодаря модульной структуре мы можем использовать base_network отдельно, что особенно полезно после обучения модели. Как это можно сделать? Посмотрим на слои нашей модели:
>>> model.layers [, , , ]
Видим третий объект в списке типа models.Sequential . Это и есть модель, отображающая входную картинку в вектор. Чтобы ее извлечь и использовать как полноценную модель (можно дообучать, валидировать, встраивать в другой граф) достаточно всего лишь вытащить ее из списка слоев:
>>> embedding_model = model.layers[2] >>> embedding_model.layers [, , , , ]
Например для уже обученной на данных MNIST сиамской сети с размерностью на выходе base_model , равной двум, можно визуализировать векторные представления следующим образом:
Загрузим данные и приведем картинки размера 28×28 к плоским векторам.
(x_train, y_train), (x_test, y_test) = mnist.load_data() x_test = x_test.reshape(10000, 784)
Отобразим картинки с помощью извлеченной ранее модели:
embeddings = embedding_model.predict(x_test)
Теперь в embeddings лежат двумерные вектора, их можно изобразить на плоскости:
Полноценный пример сиамской сети можно увидеть здесь.
Заключение
Вот и все, мы сделали первые модели на Keras! Надеемся, что предоставляемые им возможности заинтересовали вас, так что вы будете его использовать в своей работе.
Пришло время обсудить плюсы и минусы Keras. К очевидным плюсам можно отнести простоту создания моделей, которая выливается в высокую скорость прототипирования. Например, авторы недавней статьи про спутники использовали именно Keras. В целом этот фреймворк становится все более и более популярным:
Keras за год догнал Torch, который разрабатывается уже 5 лет, судя по упоминаниям в научных статьях. Кажется, своей цели — простоты использования — Франсуа Шолле (François Chollet, автор Keras) добился. Более того, его инициатива не осталась незамеченной: буквально через несколько месяцев разработки компания Google пригласила его заниматься этим в команде, разрабатывающей Tensorflow. А также с версии Tensorflow 1.2 Keras будет включен в состав TF (tf.keras).
Также надо сказать пару слов о недостатках. К сожалению, идея Keras о универсальности кода выполняется не всегда: Keras 2.0 поломал совместимость с первой версией, некоторые функции стали называться по-другому, некоторые переехали, в общем, история похожа на второй и третий python. Отличием является то, что в случае Keras была выбрана только вторая версия для развития. Также код Keras работает на Tensorflow пока медленнее, чем на Theano (хотя для нативного кода фреймворки, как минимум, сравнимы).
В целом, можно порекомендовать Keras к использованию, когда вам нужно быстро составить и протестировать сеть для решения конкретной задачи. Но если вам нужны какие-то сложные вещи, вроде нестандартного слоя или распараллеливания кода на несколько GPU, то лучше (а подчас просто неизбежно) использовать нижележащий фреймворк.
Практически весь код из статьи есть в виде одного ноутбука здесь. Также очень рекомендуем вам документацию по Keras: keras.io, а так же официальные примеры, на которых эта статья во многом основана.
Пост написан в сотрудничестве с Wordbearer.