ошибка при реализации входного конвейера тензорного потока с tf.data - PullRequest
4 голосов
/ 06 марта 2019

У меня проблема с реализацией входного конвейера с новым классом тензорного потока tf.data.

В частности, когда я включаю операцию свертки в предварительную обработку - которую я добавляю в конвейер с помощью метода map- Я получаю следующую ошибку

tensorflow.python.framework.errors_impl.UnimplementedError: Generic conv implementation only supports NHWC tensor format for now.
 [[{{node conv_debug}} = Conv2D[T=DT_FLOAT, data_format="NCHW", dilations=[1, 1, 1, 1], padding="SAME", strides=[1, 1, 1, 1], use_cudnn_on_gpu=true](conv_debug-0-TransposeNHWCToNCHW-LayoutOptimizer, ArithmeticOptimizer/FoldMultiplyIntoConv_scaled_conv_debug_Const)]]

Когда я исключаю свертку из конвейера, все работает как положено.

Я прилагаю ниже минимальный код, необходимый для воспроизведения проблемы.

Протестировано с 3 конфигурациями:

  • Tensorflow 1.12.0, CUDA 10.0, CUDnn 7.4.1, получил ошибку.
  • Tensorflow 1.11.0, CUDA 9.0, CUDnn 7.3.1, получил ошибку.
  • Tensorflow 1.8.0, CUDA 8.0, CUDnn 6.0, работает .

Я делаю это неправильно или это такпроблема, связанная с CUDA / CUDnn?

Спасибо!

import numpy as np
import tensorflow as tf

image_height, image_width = 100, 200

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


def serialize_to_record(record_name, label, image):
        """Create a data record and store it"""
        writer = tf.python_io.TFRecordWriter(record_name)
        image_raw = image.tostring() 
        label_raw = label
        sample = tf.train.Example(features=tf.train.Features(feature={
            'image_raw': _bytes_feature(image_raw),
            'label_raw': _bytes_feature(label_raw)}))        
        writer.write(sample.SerializeToString())
        writer.close()
        return


def _dataset_parser(record):
    """Read and deserialize a tensorflow record"""
    parsed = tf.parse_single_example(record,
        features={'image_raw': tf.FixedLenFeature([], tf.string),
                  'label_raw': tf.FixedLenFeature([], tf.string)})
    image_ = tf.decode_raw(parsed['image_raw'], tf.uint8)
    image_.set_shape(image_height * image_width * 3)
    image_ = tf.reshape(image_, (image_height, image_width, 3))
    image = tf.cast(image_, tf.float32) / 255.0
    label = parsed['label_raw']

    return {'image': image, 'label': label}


def _dataset_preprocessor(datum):
    """dummy preprocessor consisting of a convolution with a random kernel"""
    image = datum['image']
    kernel = np.random.rand(5, 5, 3, 3)
    kernel_tf = tf.constant(kernel, dtype=tf.float32)
    image = tf.expand_dims(image, axis=0)
    image = tf.nn.conv2d(image, kernel_tf, [1, 1, 1, 1], padding='SAME', name='conv_debug')
    image = tf.squeeze(image, axis=0)
    datum['image'] = image
    return datum


def _dataset_operator(record):
    """define a sequence of operation to run on the dataset"""
    datum = _dataset_parser(record)
    datum = _dataset_preprocessor(datum)
    return datum


def _dataset_operator_noconv(record):
    """define a sequence of operation to run on the dataset"""
    datum = _dataset_parser(record)
    return datum


if __name__ == '__main__':

    # create a random tensor
    image = (255.0 * np.random.rand(image_height, image_width, 3)).astype(np.uint8)
    record_path = 'example.tfrecord'

    # store a tf record to disk
    serialize_to_record(record_path, label='example', image=image)

    # build a dummy dataset of copies of the generated image
    N = 32
    dataset_filenames = [record_path for n in range(N)]
    dataset = tf.data.TFRecordDataset(dataset_filenames)

    # add parser and preprocessor to the pipeline
    include_convolution_to_pipeline = True
    if include_convolution_to_pipeline:
        dataset = dataset.map(_dataset_operator)
    else:
        dataset = dataset.map(_dataset_operator_noconv)

    # complete pipeline for iteratively visiting the dataset in batches of 8 samples
    dataset = dataset.shuffle(buffer_size=100)
    dataset = dataset.batch(8)
    dataset = dataset.repeat()
    iterator = dataset.make_initializable_iterator()
    next_data = iterator.get_next()

    # init session and go for the first batch
    sess = tf.Session()
    sess.run(iterator.initializer)
    next_data_ = sess.run(next_data)

    print('***')

1 Ответ

1 голос
/ 06 марта 2019

Как указано в сообщении об ошибке, для операции свертки требуется формат данных NCHW. Независимо от того, какой формат данных вы хотите, ему все равно нужен batch_size как одно из измерений. Но вы пытаетесь применить функцию карты до пакетирования. Обычно это не стандартный порядок, но если вам нужна свертка, вам нужно применить функцию карты после пакета.

dataset = dataset.map(_dataset_operator)
dataset = dataset.shuffle(buffer_size=100)
dataset = dataset.batch(8)
dataset = dataset.map(_dataset_operator)
dataset = dataset.repeat()
...