Создание тензора динамической формы из списков python для подачи тензора потока RNN - PullRequest
1 голос
/ 14 июня 2019

Я создаю сквозную архитектуру распознавания речи, в которой мои данные представляют собой список сегментированных спектрограмм. Мои данные имеют форму (batch_size, timesteps, 8, 65, 1), в которой batch_size является фиксированной, но timesteps меняется. Я не могу понять, как поместить эти данные в тензор с соответствующей формой для подачи моей модели. Вот фрагмент кода, который показывает мою проблему:

import numpy as np
import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras.layers import Conv2D, MaxPool2D, Dense, Dropout, Flatten, TimeDistributed
from tensorflow.keras.layers import SimpleRNN, LSTM
from tensorflow.keras import Input, layers
from tensorflow.keras import backend as K

segment_width = 8
segment_height = 65
segment_channels = 1

batch_size = 4

segment_lengths = [28, 33, 67, 43]
label_lengths = [16, 18, 42, 32]

TARGET_LABELS = np.arange(35)

# Generating data
X = [np.random.uniform(0,1, size=(segment_lengths[k], segment_width, segment_height, segment_channels))
     for k in range(batch_size)]

y = [np.random.choice(TARGET_LABELS, size=label_lengths[k]) for k in range(batch_size)]

# Model definition
input_segments_data = tf.keras.Input(name='input_segments_data', shape=(None, segment_width, segment_height, segment_channels),
                               dtype='float32')
input_segment_lengths = tf.keras.Input(name='input_segment_lengths', shape=[1], dtype='int64')
input_label_lengths = tf.keras.Input(name='input_label_lengths', shape=[1], dtype='int64')
# More complex architecture comes here
outputs = Flatten()(input_segments_data)

model = tf.keras.Model(inputs=[input_segments_data, input_segment_lengths, input_label_lengths], outputs = outputs)

def dummy_loss(y_true, y_pred):
  return y_pred

model.compile(optimizer="Adam", loss=dummy_loss)
model.summary()

Выход:

Model: "model"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_segments_data (InputLayer [(None, None, 8, 65, 0                                            
__________________________________________________________________________________________________
input_segment_lengths (InputLay [(None, 1)]          0                                            
__________________________________________________________________________________________________
input_label_lengths (InputLayer [(None, 1)]          0                                            
__________________________________________________________________________________________________
flatten (Flatten)               (None, None)         0           input_segments_data[0][0]        
==================================================================================================
Total params: 0
Trainable params: 0
Non-trainable params: 0
__________________________________________________________________________________________________

Теперь, когда я пытаюсь предсказать из моих случайных данных:

model.predict([X, segment_lengths, segment_lengths])

Я получаю эту ошибку:

ValueError: Error when checking input: expected input_segments_data to have 5 dimensions, but got array with shape (4, 1)

Как я могу преобразовать X (который представляет собой список массивов) в тензор формы (None, None, 8, 65, 1) и передать его в мою модель? Я не хочу использовать заполнение нулями!

Ответы [ 2 ]

2 голосов
/ 17 июня 2019

Модель Keras принимает в качестве входных данных массив numey (тензор). Вы не можете иметь тензор с переменными временными шагами. Вместо этого вы можете добавить все данные в одну форму, используя, например, pad_sequence И затем вы можете добавить Маскирующий слой к вашей модели, чтобы игнорировать дополненные значения.

1 голос
/ 22 июня 2019

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

Чтобы сделать это, вам просто нужно сохранить свои входные данные в массиве с фиксированными размерами и передать их в модель. Вы должны добавить фиктивные значения, чтобы представить пропущенные временные шаги в ваших последовательностях (общее значение - 0).

Затем вам нужно добавить слой Masking к вашей модели, который скажет Keras игнорировать временные шаги, имеющие фиктивные особенности. С документация :

keras.layers.Masking(mask_value=0.0)

Если все объекты для данного временного шага выборки равны mask_value, тогда временной шаг выборки будет маскироваться (пропускаться) во всех последующих слоях (если они поддерживают маскирование).

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

# Generating data (using a dummy zero-array to store padded sequences)
X = np.zeros((batch_size, max(segment_lengths), segment_width, segment_height, segment_channels))
X_true = [np.ones((segment_lengths[k], segment_width, segment_height, segment_channels)) 
          for k in range(batch_size)]

# Populate dummy array
for i, x in enumerate(X_true): 
    X[i, -segment_lengths[i]:, ...] = x

# Model definition
input_segments_data = tf.keras.Input(name='input_segments_data', shape=(max(segment_lengths), segment_width, segment_height, segment_channels))
masked_segments_data = tf.keras.layers.Masking()(input_segments_data)

# More complex architecture comes here
outputs = tf.keras.layers.Flatten()(input_segments_data)

model = tf.keras.Model(inputs=input_segments_data, outputs = outputs)

def dummy_loss(y_true, y_pred):
  return y_pred

model.compile(optimizer="Adam", loss=dummy_loss)
model.summary()

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

Альтернативным подходом было бы сделать что-то похожее на то, что вы делали, но используя партии размером 1. Это, однако, может вызвать нестабильность в вашей учебной процедуре, и я бы по возможности ее избегал.

В качестве последнего примечания в Tensorflow 2 добавлена ​​поддержка RaggedTensors, тензоров с одним или несколькими переменными измерениями. В настоящее время нет поддержки RNN, но, вероятно, она будет добавлена ​​в конце концов.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...