13

Что такое пример использования TFRecord TensorFlow с моделью Keras и tf.session.run(), сохраняя набор данных в тензорах w/queue runners?Как сделать TensorFlow + Keras быстро с помощью набора данных TFRecord?

Ниже приведен фрагмент кода, который работает, но необходимы следующие улучшения:

  • Используйте Model API
  • указать вход()
  • Загрузите набора данных из TFRecord
  • пробежать (например, с помощью queuerunner)

Адрес этой страницы: домашнее животное, есть несколько TODO линий указывает на то, что нужно:

from keras.models import Model 
import tensorflow as tf 
from keras import backend as K 
from keras.layers import Dense, Input 
from keras.objectives import categorical_crossentropy 
from tensorflow.examples.tutorials.mnist import input_data 

sess = tf.Session() 
K.set_session(sess) 

# Can this be done more efficiently than placeholders w/ TFRecords? 
img = tf.placeholder(tf.float32, shape=(None, 784)) 
labels = tf.placeholder(tf.float32, shape=(None, 10)) 

# TODO: Use Input() 
x = Dense(128, activation='relu')(img) 
x = Dense(128, activation='relu')(x) 
preds = Dense(10, activation='softmax')(x) 
# TODO: Construct model = Model(input=inputs, output=preds) 

loss = tf.reduce_mean(categorical_crossentropy(labels, preds)) 

# TODO: handle TFRecord data, is it the same? 
mnist_data = input_data.read_data_sets('MNIST_data', one_hot=True) 

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(loss) 

sess.run(tf.global_variables_initializer()) 

# TODO remove default, add queuerunner 
with sess.as_default(): 
    for i in range(1000): 
     batch = mnist_data.train.next_batch(50) 
     train_step.run(feed_dict={img: batch[0], 
            labels: batch[1]}) 
    print(loss.eval(feed_dict={img: mnist_data.test.images, labels: mnist_data.test.labels})) 

Почему этот вопрос актуальным?

  • Для высокой подготовки производительности, не возвращаясь к питону
  • Keras will soon be part of tensorflow
  • Продемонстрировать Keras Модель() классы может принимать тензоры для правильного ввода данных ,

Вот некоторые стартером информация для семантического примере задачи сегментации:

+0

https://github.com/tensorflow/tensorflow/issues/8787 будет работать для полной поддержки этой функциональности, кроме быстрого исправления, предусмотренного в принятом ответе. –

+0

обновленный запрос на тягу https://github.com/fchollet/keras/pull/6928 –

ответ

4

TFRecords поддерживаются с использованием внешних потерь. Вот основные линии построения внешней потери:

# tf yield ops that supply dataset images and labels 
x_train_batch, y_train_batch = read_and_decode_recordinput(...) 

# create a basic cnn 
x_train_input = Input(tensor=x_train_batch) 
x_train_out = cnn_layers(x_train_input) 

model = Model(inputs=x_train_input, outputs=x_train_out) 
loss = keras.losses.categorical_crossentropy(y_train_batch, x_train_out) 
model.add_loss(loss) 

model.compile(optimizer='rmsprop', loss=None) 

Вот пример для Keras 2. Он работает после применения небольшого участка #7060:

'''MNIST dataset with TensorFlow TFRecords. 

Gets to 99.25% test accuracy after 12 epochs 
(there is still a lot of margin for parameter tuning). 
''' 
import os 
import copy 
import time 

import numpy as np 

import tensorflow as tf 
from tensorflow.python.ops import data_flow_ops 
from keras import backend as K 
from keras.models import Model 
from keras.layers import Dense 
from keras.layers import Dropout 
from keras.layers import Flatten 
from keras.layers import Input 
from keras.layers import Conv2D 
from keras.layers import MaxPooling2D 
from keras.callbacks import EarlyStopping 
from keras.callbacks import TensorBoard 
from keras.objectives import categorical_crossentropy 
from keras.utils import np_utils 
from keras.utils.generic_utils import Progbar 
from keras import callbacks as cbks 
from keras import optimizers, objectives 
from keras import metrics as metrics_module 

from keras.datasets import mnist 

if K.backend() != 'tensorflow': 
    raise RuntimeError('This example can only run with the ' 
         'TensorFlow backend for the time being, ' 
         'because it requires TFRecords, which ' 
         'are not supported on other platforms.') 


def images_to_tfrecord(images, labels, filename): 
    def _int64_feature(value): 
     return tf.train.Feature(int64_list=tf.train.Int64List(value=[value])) 

    def _bytes_feature(value): 
     return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value])) 

    """ Save data into TFRecord """ 
    if not os.path.isfile(filename): 
     num_examples = images.shape[0] 

     rows = images.shape[1] 
     cols = images.shape[2] 
     depth = images.shape[3] 

     print('Writing', filename) 
     writer = tf.python_io.TFRecordWriter(filename) 
     for index in range(num_examples): 
      image_raw = images[index].tostring() 
      example = tf.train.Example(features=tf.train.Features(feature={ 
       'height': _int64_feature(rows), 
       'width': _int64_feature(cols), 
       'depth': _int64_feature(depth), 
       'label': _int64_feature(int(labels[index])), 
       'image_raw': _bytes_feature(image_raw)})) 
      writer.write(example.SerializeToString()) 
     writer.close() 
    else: 
     print('tfrecord %s already exists' % filename) 


def read_and_decode_recordinput(tf_glob, one_hot=True, classes=None, is_train=None, 
           batch_shape=[1000, 28, 28, 1], parallelism=1): 
    """ Return tensor to read from TFRecord """ 
    print 'Creating graph for loading %s TFRecords...' % tf_glob 
    with tf.variable_scope("TFRecords"): 
     record_input = data_flow_ops.RecordInput(
      tf_glob, batch_size=batch_shape[0], parallelism=parallelism) 
     records_op = record_input.get_yield_op() 
     records_op = tf.split(records_op, batch_shape[0], 0) 
     records_op = [tf.reshape(record, []) for record in records_op] 
     progbar = Progbar(len(records_op)) 

     images = [] 
     labels = [] 
     for i, serialized_example in enumerate(records_op): 
      progbar.update(i) 
      with tf.variable_scope("parse_images", reuse=True): 
       features = tf.parse_single_example(
        serialized_example, 
        features={ 
         'label': tf.FixedLenFeature([], tf.int64), 
         'image_raw': tf.FixedLenFeature([], tf.string), 
        }) 
       img = tf.decode_raw(features['image_raw'], tf.uint8) 
       img.set_shape(batch_shape[1] * batch_shape[2]) 
       img = tf.reshape(img, [1] + batch_shape[1:]) 

       img = tf.cast(img, tf.float32) * (1./255) - 0.5 

       label = tf.cast(features['label'], tf.int32) 
       if one_hot and classes: 
        label = tf.one_hot(label, classes) 

       images.append(img) 
       labels.append(label) 

     images = tf.parallel_stack(images, 0) 
     labels = tf.parallel_stack(labels, 0) 
     images = tf.cast(images, tf.float32) 

     images = tf.reshape(images, shape=batch_shape) 

     # StagingArea will store tensors 
     # across multiple steps to 
     # speed up execution 
     images_shape = images.get_shape() 
     labels_shape = labels.get_shape() 
     copy_stage = data_flow_ops.StagingArea(
      [tf.float32, tf.float32], 
      shapes=[images_shape, labels_shape]) 
     copy_stage_op = copy_stage.put(
      [images, labels]) 
     staged_images, staged_labels = copy_stage.get() 

     return images, labels 


def save_mnist_as_tfrecord(): 
    (X_train, y_train), (X_test, y_test) = mnist.load_data() 
    X_train = X_train[..., np.newaxis] 
    X_test = X_test[..., np.newaxis] 
    images_to_tfrecord(images=X_train, labels=y_train, filename='train.mnist.tfrecord') 
    images_to_tfrecord(images=X_test, labels=y_test, filename='test.mnist.tfrecord') 


def cnn_layers(x_train_input): 
    x = Conv2D(32, (3, 3), activation='relu', padding='valid')(x_train_input) 
    x = Conv2D(64, (3, 3), activation='relu')(x) 
    x = MaxPooling2D(pool_size=(2, 2))(x) 
    x = Dropout(0.25)(x) 
    x = Flatten()(x) 
    x = Dense(128, activation='relu')(x) 
    x = Dropout(0.5)(x) 
    x_train_out = Dense(classes, 
         activation='softmax', 
         name='x_train_out')(x) 
    return x_train_out 


sess = tf.Session() 
K.set_session(sess) 

save_mnist_as_tfrecord() 

batch_size = 100 
batch_shape = [batch_size, 28, 28, 1] 
epochs = 3000 
classes = 10 
parallelism = 10 

x_train_batch, y_train_batch = read_and_decode_recordinput(
    'train.mnist.tfrecord', 
    one_hot=True, 
    classes=classes, 
    is_train=True, 
    batch_shape=batch_shape, 
    parallelism=parallelism) 

x_test_batch, y_test_batch = read_and_decode_recordinput(
    'test.mnist.tfrecord', 
    one_hot=True, 
    classes=classes, 
    is_train=True, 
    batch_shape=batch_shape, 
    parallelism=parallelism) 


x_batch_shape = x_train_batch.get_shape().as_list() 
y_batch_shape = y_train_batch.get_shape().as_list() 

x_train_input = Input(tensor=x_train_batch, batch_shape=x_batch_shape) 
x_train_out = cnn_layers(x_train_input) 
y_train_in_out = Input(tensor=y_train_batch, batch_shape=y_batch_shape, name='y_labels') 
cce = categorical_crossentropy(y_train_batch, x_train_out) 
train_model = Model(inputs=[x_train_input], outputs=[x_train_out]) 
train_model.add_loss(cce) 

train_model.compile(optimizer='rmsprop', 
        loss=None, 
        metrics=['accuracy']) 
train_model.summary() 

tensorboard = TensorBoard() 

# tensorboard disabled due to Keras bug 
train_model.fit(batch_size=batch_size, 
       epochs=epochs) # callbacks=[tensorboard]) 

train_model.save_weights('saved_wt.h5') 

K.clear_session() 

# Second Session, pure Keras 
(X_train, y_train), (X_test, y_test) = mnist.load_data() 
X_train = X_train[..., np.newaxis] 
X_test = X_test[..., np.newaxis] 
x_test_inp = Input(batch_shape=(None,) + (X_test.shape[1:])) 
test_out = cnn_layers(x_test_inp) 
test_model = Model(inputs=x_test_inp, outputs=test_out) 

test_model.load_weights('saved_wt.h5') 
test_model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) 
test_model.summary() 

loss, acc = test_model.evaluate(X_test, np_utils.to_categorical(y_test), classes) 
print('\nTest accuracy: {0}'.format(acc)) 

Я также работал, чтобы улучшить поддержка TFRecords в следующем выпуске и тянуть запрос:

  • #6928 Выход Op поддержка: Высокая производительность с большими объемами данных через TFRecords и RecordInput
  • #7102 Keras Входной Тензор API Design Предложение

Наконец, можно использовать tf.contrib.learn.Experiment для подготовки моделей Keras в TensorFlow.

+0

Я смог получить этот пример, работая с внешними потерями после включения PR https://github.com/fchollet/keras/pull/7060, чтобы исправить модуль generic_utils.py. –

+0

По какой-то причине 'data_flow_ops.RecordInput' возвращает только первую партию, тогда Keras думает, что эта эпоха завершена и перезапускается еще одна эпоха. Я не могу понять, почему. Я знаю, что вам сложно понять, что происходит, но есть ли у вас какие-либо предложения по отладке этого? Большое спасибо. Я уверен, что файл tfrecord, который я прошел, правильный (имеет более 60 тыс. Изображений). – NullSpace

+0

@NullSpace Это должен быть отдельный вопрос о стеке. С текущей keras мастер один шаг == одна эпоха, так что просто запустить многократно или попробуйте https://github.com/fchollet/keras/pull/7113. –

20

Я не использую формат tfrecord dataset, поэтому не буду спорить о плюсах и минусах, но я заинтересовался расширением Keras для поддержки того же.

github.com/indraforyou/keras_tfrecord - это хранилище. Кратко объясним основные изменения.

создание Dataset и загрузка

data_to_tfrecord и read_and_decodehere заботится о создании tfrecord набора данных и загрузки то же самое. Особое внимание должно быть уделено внедрению read_and_decode, иначе вы столкнетесь с загадочными ошибками во время обучения.

Инициализация и Keras модель

Теперь оба tf.train.shuffle_batch и Keras Input слой возвращается тензор. Но тот, который возвращается tf.train.shuffle_batch, не имеет метаданных, необходимых Keras внутри. Как оказалось, любой тензор можно легко превратить в тензор с метадатами keras, вызвав слой Input с параметром tensor.

Так что заботится о инициализации:

x_train_, y_train_ = ktfr.read_and_decode('train.mnist.tfrecord', one_hot=True, n_class=nb_classes, is_train=True) 

x_train_batch, y_train_batch = K.tf.train.shuffle_batch([x_train_, y_train_], 
               batch_size=batch_size, 
               capacity=2000, 
               min_after_dequeue=1000, 
               num_threads=32) # set the number of threads here 

x_train_inp = Input(tensor=x_train_batch) 

Теперь x_train_inp любой keras модель может быть разработана.

Training (простой)

Позволяет сказать train_out является выходным тензором модели keras. Вы можете легко написать собственный тренировочный цикл по строкам:

loss = tf.reduce_mean(categorical_crossentropy(y_train_batch, train_out)) 
train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss) 


# sess.run(tf.global_variables_initializer()) 
sess.run(tf.initialize_all_variables()) 

with sess.as_default(): 
    coord = tf.train.Coordinator() 
    threads = tf.train.start_queue_runners(sess=sess, coord=coord) 

    try: 
     step = 0 
     while not coord.should_stop(): 
     start_time = time.time() 

     _, loss_value = sess.run([train_op, loss], feed_dict={K.learning_phase(): 0}) 

     duration = time.time() - start_time 

     if step % 100 == 0: 
      print('Step %d: loss = %.2f (%.3f sec)' % (step, loss_value, 
                duration)) 
     step += 1 
    except tf.errors.OutOfRangeError: 
     print('Done training for %d epochs, %d steps.' % (FLAGS.num_epochs, step)) 
    finally: 
     coord.request_stop() 

    coord.join(threads) 
    sess.close() 

Training (keras стиль)

Одной из особенностей keras, что делает его таким прибыльным является обобщенный учебный механизм с функции обратного вызова.

Но для поддержки tfrecords обучения типа есть несколько изменений, которые нуждаются в fit функции

  • работает нить очереди
  • не подавая в пакетных данных через feed_dict
  • с поддержкой валидации становится сложнее, поскольку данные валидации также будут поступать через другой тензор, а другая модель должна быть создана внутренне с общими верхними слоями и тензором проверки, поданным другим считывателем tfrecord.

Но все это может быть легко поддержано другим параметром флага. Что делает вещи беспорядочными - это функции keras sample_weight и class_weight, они используются для взвешивания каждого образца и взвешивания каждого класса. Для этого в compile() keras создает заполнители (here), а также для нецелесообразно создавать заполнитель для целей (here), которые не нужны, в нашем случае метки уже подаются считывателями tfrecord. Эти заполнители должны быть загружены во время сеанса, что не нужно в наших cae.

Итак, принимая во внимание эти изменения, compile_tfrecord (here) и fit_tfrecord (here) являются продолжением compile и fit и акции говорят, 95% кода.

Они могут быть использованы следующим образом:

import keras_tfrecord as ktfr 

train_model = Model(input=x_train_inp, output=train_out) 
ktfr.compile_tfrecord(train_model, optimizer='rmsprop', loss='categorical_crossentropy', out_tensor_lst=[y_train_batch], metrics=['accuracy']) 

train_model.summary() 

ktfr.fit_tfrecord(train_model, X_train.shape[0], batch_size, nb_epoch=3) 
train_model.save_weights('saved_wt.h5') 

Вы можете улучшить код и тянуть запросы.

+0

wow выглядит фантастически! Возможно, стоит вопрос о вытаскивании в [keras-contrib] (https://github.com/farizrahman4u/keras-contrib), официальном репозитории keras upstream? Я попробую это, тогда я ожидаю, что награду за кредит + щедрость. Я также отредактировал ссылки, чтобы использовать хеш текущей версии keras, чтобы номера строк оставались правильными. –

+0

здесь [keras-contrib pull request # 27] (https://github.com/farizrahman4u/keras-contrib/pull/27) –

+0

Обновленный запрос на растяжение: https://github.com/fchollet/keras/pull/6928 –

 Смежные вопросы

  • Нет связанных вопросов^_^