Как реализовать скользящее окно последовательности изображений (2D-массив) в тензорном потоке? - PullRequest
0 голосов
/ 18 февраля 2019

Контекст

У нас есть данные, хранящиеся в .tfrecord файлах, X - это наши данные обучения> 40x40 серой шкалы и Y: метки.Эти изображения упорядочены в последовательности (порядок важен).Мы хотели бы ввести эти изображения с помощью Tensorflows Estimator API для обучения модели нейронной сети (например, LSTM) с различными размерами временного окна и смещениями с использованием GoogleML.

Вопрос

Как преобразовать входную строку объектов в последовательности определенной длины, например, поместить 1000 изображения в одну последовательность, а затем выполнить оконную обработку для этих последовательностей, например, получить окна 50 изображения, со смещением окна 25?

Текущее состояние

Нам удалось этого добиться (разреженный пример ниже) без первого преобразования в 1000 наборов длины, но затем в результате получаются окна, которые охватывают элемент 975 одногоустановить элемент 25 следующего, который нам не нужен . Нам нужны перекрывающиеся окна, которые охватывают от начала до конца каждого набора 1000 изображений, но не должны пересекать их границы.

import tensorflow as tf

# .tfrecord file consisting of data 'X' and labels 'Y'
dataset = tf.data.TFRecordDataset('.tfrecord file')

# define parse function for dataset.map function
def _parse_function(proto):
    # define constants for parsing
    image_size = 40
    num_channels = 1
    num_classes = 3


    # define your tfrecord feature keys and 
    # reshape 1D arrays into 2D arrays (images)
    keys_to_features = {'X': tf.FixedLenFeature([image_size, image_size, num_channels], tf.float32),  # image height, image width, num_channels
                    'Y': tf.FixedLenFeature([], tf.int64)}

    # Load one example
    parsed_features = tf.parse_single_example(proto, keys_to_features)

    # extract image and labels
    image = parsed_features['X']
    labels = tf.cast( parsed_features['Y'], tf.int32 )
    labels = tf.one_hot( labels, depth=num_classes )  # one hot encoding

    return image, labels

# reshape the data into parse format
dataset = dataset.map(_parse_function)

# define dataset parameters
window_size = 50
batch_size = 500
window_shift = int( window_size / 2 )  # 25

# implement sliding window 
dataset = dataset.window(size=window_size, shift=window_shift, drop_remainder=True ).flat_map( lambda x: x.batch(window_size) )

# batch the data
dataset = dataset.batch(batch_size)

# create an iterator
# iterator = dataset.make_one_shot_iterator().get_next()

Выше iterator вернется для X данные тензор формы (batch_size, window_size, image_height, image_width, количество каналов), в нашем случае (500, 50, 40, 40, 1) и Y в виде (500, 3) массива.

1 Ответ

0 голосов
/ 21 февраля 2019

Мне удалось сделать это, отфильтровав окна, которые пересекают границы.Когда у вас есть проанализированные объекты, примените управление окнами ко всему, затем рассчитайте, какие окна являются переполненными, и отфильтруйте их:

ds = tf.data.TFRecordDataset( filename )
ds = ds.map( _parse_function )

# apply windowing
ds = ds.window( size=50, shift=25, drop_remainder=True ).flat_map( lambda x, y: tf.data.Dataset.zip( (x.batch(50), y.batch(50)) ) )
# enumerate dataset and filter every 40th window
ds = ds.apply( tf.data.experimental.enumerate_dataset(start=1) ).filter( lambda i, x: tf.not_equal( i % 40, 0) )
# get rid of enumerations
ds = ds.map( lambda i, x: x )

# batching, shuffling etc...
...

Уточнение: отфильтровано каждое 40-е окно, потому что если у вас есть наборы 1000 исмещение окна 25, будет set_len / win_shift = 40 окна, а последнее (т.е. 40-е) будет переполнено в следующий набор.Также обратите внимание, что перечисление начинается с 1, так что 0-й образец не берется, поскольку 0 % x == 0.

Обратите внимание, что это скорее взлом, чем истинное решение.Он хорошо работает с 50% -ным перекрытием, но при других процентах становится сложнее вычислять выбрасываемые индексы (в случае> 50% -ного перекрытия более одного окна переполняется в следующий набор, поэтому потребуется несколько фильтров).

...