1

I am trying to construct a custom estimator for my ML Engine package and I seem to be having trouble properly constructing my decoder input sequence in the correct format. Consider the following where label1, label2 is supposed to be a sequence of labels.

label1, label2 = tf.decode_csv(rows, record_defaults=[[""], [""]])
labels = tf.stack([label1, label2], axis=1)
label_index = tf.contrib.lookup.index_table_from_file(
    vocabulary_file = label_file)
label_idx = label_index.lookup(labels)
features = dict(zip(['decoder_input'], [label_idx]))

these "features" are then passed as the decoder input as below. When I go to use the decoder_input as input into my custom estimator, I run into the an error 'TypeError: 'Tensor' object is not iterable.' here:

outputs, state = tf.contrib.legacy_seq2seq.embedding_rnn_decoder(
    decoder_inputs = features['decoder_input'],
    initial_state = curr_layer,
    cell = tf.contrib.rnn.GRUCell(hidden_units),
    num_symbols = n_labels,
    embedding_size = embedding_dims, # should not be hard-coded
    feed_previous = False)

The full stack trace (below) suggests that the portion of code causing the issue is for 'for i in decoder_inputs' from line 296 so it seems pretty clear to me that the issue is in how I construct my decoder_input in the input_fn(). However, I can't seem to figure out how to make the Tensor object an iterable list of sequences.

Stacktrace:

File "/Users/user/anaconda/envs/tensorflow-

  cloud/lib/python2.7/sitepackages/tensorflow/contrib/legacy_seq2seq/python/ops/seq2seq.py", line 296, in embedding_rnn_decoder
    for i in decoder_inputs)
  File "/Users/user/anaconda/envs/tensorflow-cloud/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 541, in __iter__
    raise TypeError("'Tensor' object is not iterable.")
TypeError: 'Tensor' object is not iterable.

Can anybody help spot how I should correctly format my labels so that they are iterable? The documentation says that decoder_inputs should be "A list of 1D batch-sized int32 Tensors (decoder inputs)." so I thought that by staIs there a more appropriate way to generate the sequence of labels than tf.stack()?

reese0106
  • 2,011
  • 2
  • 16
  • 46
  • It seems like it is expecting features['decoder_input'] to be a list. What is it in your case? – Aaron Aug 15 '17 at 18:21
  • Yes, it is looking for a list of 1D tensors. I believe that what I am submitted is just a 1D tensor with shape [2] that is more or less generated from tf.stack([label1, label2], axis=1) -- I guess my question more specifically would be how to create a list of 1D tensors. Is it as simple as [label1, label2] instead of tf.stack([label1, label2])? – reese0106 Aug 15 '17 at 18:25
  • It wants it as a list. If there is just one or two items in it then there is not much reason to use an RNN. If you want to make the RNN work with a single input just wrap it in square brackets so that it sees it as a list of tensors. – Aaron Aug 15 '17 at 18:26
  • There are significantly more than 2 items, I am just trying to create a simple example for the purposes of this post. – reese0106 Aug 15 '17 at 18:28
  • Ah, well then just split the tensor up into a list of tensors using the tf.unstack function. – Aaron Aug 15 '17 at 18:29

1 Answers1

1

The label_idx values is not a list hence you are facing this problem:

Below example should clarify better:

label_idx = 1

features = dict(zip(['decoder_input'], [label_idx]))

features['decoder_input']

# 1 output

where as if I change label_idx to a list:

label_idx = [1]

features = dict(zip(['decoder_input'], [label_idx]))

features['decoder_input']

# [1] output

Also you can simplify how you create the dictionary:

features = {'decoder_input': [label_idx]} # if label_idx is a value
features = {'decoder_input': label_idx} # if label_idx is a list
Vikash Singh
  • 13,213
  • 8
  • 40
  • 70