1

I have a tensor x,

x={Tensor} Tensor("Cast:0", shape=(?,3), dtype=int32)

Now, I need to iterate over each triple of this tensor batch (say a triple is (a,b,c)) and fetch the first element (in this example, a) of that.

Then, I need to fetch all other triples in the dataset Y (below) that also have 'a' as their first element.

Ultimately, I wish to return all triples with 'a' as the first element, excluding the triple in question (i.e. in this case, excluding (a,b,c)).

I was previously working with the same, assuming that x is a list.

Therefore, in terms of list operations:

t=list({triple for x in x_to_score for triple in self.d[x[0]]} - set(x_to_score.eval()))

where d is a dictionary containing list of all the triples grouped by first elements. For example:

For

    Y=np.array([['a', 'y', 'b'],
              ['b', 'y', 'a'],
              ['a', 'y', 'c'],
              ['c', 'y', 'a'],
              ['a', 'y', 'd'],
              ['c', 'y', 'd'],
              ['b', 'y', 'c'],
              ['f', 'y', 'e']])

    d={'f': [('f', 'y', 'e')],
       'c': [('c', 'y', 'a'), ('c', 'y', 'd')],
        'a': [('a', 'y', 'b'), ('a', 'y', 'c'), ('a', 'y', 'd')],
        'b': [('b', 'y', 'a'), ('b', 'y', 'c')]}

However, I am new to tensorflow and cannot find a way to convert these operations into tensors. The result should also be of the order [?,3] for each triple evaluated.

Please note that eager execution must be disabled.

Any help is welcome!

EDIT: If the input tensor x=(a,y,d) (note that this can be a batch, so x=[(a,y,d),(b,y,c)] etc.), then the expected output will be:

[('a', 'y', 'b'), ('a', 'y', 'c')]
snelzb
  • 157
  • 3
  • 16
  • Can you give, for example, what would be exactly the desired output for the `X` array that you put in the example? I do not understand whether you want the "triples" in `X` that match the first element of the _first_ triple or of _each_ triple and, if it is the second case, I am not sure if you would want to get several tensors or what. Also, I'm not clear if `X` may contain duplicate triples and, in that case, if you would need to exclude copies of the triple being matched. – jdehesa Aug 14 '19 at 12:46
  • @jdehesa just realised the question is not very clear, made an edit. There will be no duplicate triples in the dataset Y, or in x either. – snelzb Aug 14 '19 at 12:57
  • Okay but you say "note that this can be a batch", so what would you get as output in the case of a batch? All the subresults concatenated? Multiple tensors? A 3D tensor (in which case the number of matches for each given input would have to be the same, otherwise the result would need to be ragged or padded)? – jdehesa Aug 14 '19 at 14:16
  • @jdehesa An [n,3] list basically, which is all subresults concatenated but distinguishable for each subject. So In the example batch of [(a,y,d),(b,y,c)], result should be [[(a,y,b),(a,y,c)],[(b,y,a)]] – snelzb Aug 14 '19 at 15:00
  • Okay, and the number of triples to match within one batch, is it fixed? Because if it is variable you will not be able to do this (if you want a Python list of tensors, the size of that list must be fixed and known in advance). – jdehesa Aug 14 '19 at 15:03
  • @jdehesa unfortunately it is not a fixed size batch. You are right, this approach will not work – snelzb Aug 14 '19 at 15:04
  • @jdehesa if you could suggest some other way to fetch all triples with same first element from a tensor dataset like Y? – snelzb Aug 14 '19 at 15:05

1 Answers1

0

One possible solution for this is to compute to array results, one with the concatenated matches for all inputs and another indicating the index of the input it refers to. It could work like this:

import tensorflow as tf

X = tf.placeholder(tf.string, [None, 3])
Y = tf.constant([
    ['a', 'y', 'b'],
    ['b', 'y', 'a'],
    ['a', 'y', 'c'],
    ['c', 'y', 'a'],
    ['a', 'y', 'd'],
    ['c', 'y', 'd'],
    ['b', 'y', 'c'],
    ['f', 'y', 'e']
])
# Compare every input to every data
cmp = tf.equal(tf.expand_dims(X, 1), Y)
# Triples matching the first element
first_match = cmp[:, :, 0]
# Triples matching all elements
all_match = tf.reduce_all(cmp, axis=2)
# Triple matching the first element but not all elements
matches = first_match & (~all_match)
# Find indices
match_idx = tf.where(matches)
# Index of the input triple each result refers to
match_x = match_idx[:, 0]
# Concatenated resulting triples
match_y = tf.gather(Y, match_idx[:, 1])
# Test
with tf.Graph().as_default(), tf.Session() as sess:
    x_val = [['a', 'y', 'd'], ['b', 'y', 'c']]
    match_x_val, match_y_val = sess.run((match_x, match_y), feed_dict={X: x_val})
    print(*zip(match_x_val, match_y_val), sep='\n')

Output:

(0, array([b'a', b'y', b'b'], dtype=object))
(0, array([b'a', b'y', b'c'], dtype=object))
(1, array([b'b', b'y', b'a'], dtype=object))
jdehesa
  • 58,456
  • 7
  • 77
  • 121