繁体   English   中英

从python列表创建动态形状的张量以馈送tensorflow RNN

[英]Creating tensor of dynamic shape from python lists to feed tensorflow RNN

我正在创建一个端到端的语音识别架构,其中我的数据是一个分段频谱图列表。 我的数据有形状(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)并将其提供给我的模型? 我不想使用零填充!

Keras模型将numpy数组(张量)作为输入。 你不能拥有可变时间步长的张量。 相反,您可以做的是使用例如pad_sequence将所有数据填充到相同的形状然后,您可以向模型添加遮罩层以忽略填充值。

这是Tensorflow和其他在张量上运行的深度学习框架的常见问题。 不幸的是,除了填充序列然后屏蔽之外,目前还没有一种简单的方法可以解决这个问题。

要做到这一点,您只需将输入数据存储在具有固定尺寸的numpy数组中,然后将其输入模型。 您必须添加虚拟值来表示序列中缺少的时间步(公共值为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支持, RaggedTensors是具有一个或多个可变维度的张量。 目前不支持RNN,但最终可能会增加。

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM