如何重塑LSTM输入的图层?

时间:2019-04-17 05:49:39

标签: python tensorflow keras

我想在this flowchart中建立神经网络,但不确定如何重塑输入或自定义嵌入层的形状。它是由Google TensorFlow Hub模块创建的,用于为LSTM层提供3维输入。

通常,当我们需要为LSTM网络重塑形状时,我们将重塑输入-而不是另一层。具体来说-根据How to Reshape Input Data for Long Short-Term Memory Networks in Keras,我们希望形状表示:

  • 样品:一个序列就是一个样品。一批由一个或多个样品组成。

  • 时间步长:一个时间步长是样本中观察的一个点。

  • 功能:一项功能是一次观察一次。

我的代码:

import tensorflow_hub as hub
from tensorflow.dtypes import as_string
import tensorflow as tf
import numpy as np

embedding_shape = (32,32,32)
def embedding(x):
    module = hub.Module("https://tfhub.dev/google/nnlm-en-dim128/1")
    return_tensor = module(tf.squeeze(tf.cast(x, tf.string)),signature="default", as_dict=True)["default"]
    try:
      return_tensor = tf.cast(return_tensor,tf.float32)
    except ValueError:
      print("Embedding function could not cast return_tensor to float")
    print ("Returning tensor with shape",return_tensor.get_shape())
    return return_tensor
def split(x,col):
    return tf.reshape(x[:,col:col+1],(-1,))
def flatten_tensor(x):
    flat_tensor = tf.keras.backend.flatten(x)
    assert (len(flat_tensor.get_shape())==1)
    return flat_tensor
def flatten_layer():
    return Lambda(flatten_tensor)

input_questions = Input(shape=(1,),dtype=tf.string)
questions_embedded = Lambda(embedding)(input_questions)
questions_rnn = LSTM(32,return_sequences=True)(questions_embedded)
left_branch_outputs = questions_rnn
input_context = Input(shape=(1,),dtype=tf.string)
context_embedded = Lambda(embedding)(input_context)
context_rnn = LSTM(32,return_sequences=True)(context_embedded)
right_branch_outputs = context_rnn
main_branch_inputs = Add()([left_branch_outputs,right_branch_outputs])
main_outputs = Dense(24,activation="softmax")(Flatten()(main_branch_inputs))
answers_network_rnn = tf.keras.Model(inputs=[input_questions,input_context],outputs=main_outputs)
answers_network_rnn.compile("adam","categorical_crossentropy",metrics=['accuracy'])
answers_network_rnn_checkpoint = ModelCheckpoint('answers_network-rnn-best.h5', verbose=1, monitor='val_acc',save_best_only=True, mode='auto')

with tf.Session() as session:
    session.run([tf.global_variables_initializer(), tf.tables_initializer()])
    X_2_train_text = np.array(
      [["how much wood would a woodchuck chuck if a woodchuck could chuck wood",
        "a woodchuck would chuck as much wood as a woodchuck could chuck if a woodchuck could chuck wood"]
      ,["who sells seashells by the seashore",
       "she sells seashells by the seashore"]])
    y=session.run(tf.one_hot(np.array([23,0]),24))
    print(X_2_train_text.shape)
    print(y.shape)
    x = np.hsplit(X_2_train_text,2)
    print(x)
    answers_network_rnn.fit(x=x,y=y)

神经网络应该能够为每个样本输出一维向量。

错误:

---------------------------------------------------------------------------
InvalidArgumentError                      Traceback (most recent call last)
<ipython-input-40-cb0103df9a44> in <module>()
     13   x = np.hsplit(X_2_train_text,2)
     14   print(x)
---> 15   answers_network_rnn.fit(x=x,y=y)

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, max_queue_size, workers, use_multiprocessing, **kwargs)
    878           initial_epoch=initial_epoch,
    879           steps_per_epoch=steps_per_epoch,
--> 880           validation_steps=validation_steps)
    881 
    882   def evaluate(self,

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training_arrays.py in model_iteration(model, inputs, targets, sample_weights, batch_size, epochs, verbose, callbacks, val_inputs, val_targets, val_sample_weights, shuffle, initial_epoch, steps_per_epoch, validation_steps, mode, validation_in_fit, **kwargs)
    327 
    328         # Get outputs.
--> 329         batch_outs = f(ins_batch)
    330         if not isinstance(batch_outs, list):
    331           batch_outs = [batch_outs]

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/backend.py in __call__(self, inputs)
   3074 
   3075     fetched = self._callable_fn(*array_vals,
-> 3076                                 run_metadata=self.run_metadata)
   3077     self._call_fetch_callbacks(fetched[-len(self._fetches):])
   3078     return nest.pack_sequence_as(self._outputs_structure,

/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py in __call__(self, *args, **kwargs)
   1437           ret = tf_session.TF_SessionRunCallable(
   1438               self._session._session, self._handle, args, status,
-> 1439               run_metadata_ptr)
   1440         if run_metadata:
   1441           proto_data = tf_session.TF_GetBuffer(run_metadata_ptr)

/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/errors_impl.py in __exit__(self, type_arg, value_arg, traceback_arg)
    526             None, None,
    527             compat.as_text(c_api.TF_Message(self.status.status)),
--> 528             c_api.TF_GetCode(self.status.status))
    529     # Delete the underlying status object from memory otherwise it stays alive
    530     # as there is a reference to status from this from the traceback due to

InvalidArgumentError: Incompatible shapes: [2,24] vs. [32,24]
     [[{{node training_8/Adam/gradients/loss_21/dense_loss/mul_grad/BroadcastGradientArgs}}]]

1 个答案:

答案 0 :(得分:0)

由@Lescurel提供:

使用句子嵌入时,您会将整个句子编码为向量。所以我在这里真的看不到使用LSTM的意义。您必须问自己,TimeSteps和功能是什么。在您的情况下,天真的,因为您的特征是1D 128向量,所以您的时间步长为1。而时间步长为1的LSTM只是具有tanh的FC层。您的问题彼此相关,可以批处理它们,或者您应该对单词进行一对一编码(例如,使用Word2Vec),然后使用滑动窗口进行处理。