sariii
sariii

Reputation: 2140

how to loop over a tensor object until a condition met

I have a tensor like this:

masked_bad_col = [[False  True  True False  True  True  True  True  True  True  True False]]

I want to loop through this tensor untill all elements get True. So I have another function, which will update this tensor, lets call it uniqueness.

def uniqueness():

   'blah blah blha'
   return tensor1, updated_masked_bad_col

I looked at the documentation and got to know that I can do that using tf.while_loop. Although, I could not find any example working on boolean stuff. This is what I have done so far:

tensor1, _ = tf.while_loop(masked_bad_col != True, uniqueness)

It is obviously incorrect, but don't know how to use each element of masked_bad_col as a condition to continue looping through uniqueness function.

Update 1 This is the method I am trying to call in the loop:

corpus = load_corpus('path_to_corpus/train.corpus')
topics = []
vocab, docs = corpus['vocab'], corpus['docs']
number_of_topics = 0
encoder_model = load_keras_model(
    'path_to_model/encoder_model',
    custom_objects={"KCompetitive": KCompetitive})
weights = encoder_model.get_weights()[0]
for idx in range(encoder_model.output_shape[1]):
    token_idx = np.argsort(weights[:, idx])[::-1][:20]
    topics.append([(revdict(vocab)[x]) for x in token_idx])
    number_of_topics += 1

nparr = np.asarray(topics)
# print nparr.shape

unique, indices, count = np.unique(nparr, return_inverse=True, return_counts=True)

tensor1 = (np.sum(count[indices].reshape(nparr.shape), axis=1).reshape(1, nparr.shape[0]) / (
        number_of_topics * 20))

def uniqueness_score():
    corpus = load_corpus('path_to_corpus/train.corpus')
    topics = []
    vocab, docs = corpus['vocab'], corpus['docs']
    number_of_topics = 0
    encoder_model = load_keras_model(
        'path_to_model/encoder_model',
        custom_objects={"KCompetitive": KCompetitive})
    weights = encoder_model.get_weights()[0]
    for idx in range(encoder_model.output_shape[1]):
        token_idx = np.argsort(weights[:, idx])[::-1][:20]
        topics.append([(revdict(vocab)[x]) for x in token_idx])
        number_of_topics += 1

    nparr = np.asarray(topics)

    unique, indices, count = np.unique(nparr, return_inverse=True, return_counts=True)

    tensor1 = (np.sum(count[indices].reshape(nparr.shape), axis=1).reshape(1, nparr.shape[0]) / (
            number_of_topics * 20))
    return tensor1

And this is the way I called this method in the while_loop

with tf.Session() as sess:

        tensor2, _ = tf.while_loop(
            # Loop condition (negated goal condition)
            lambda tensor1: ~tf.math.reduce_all(tensor1 > tf.reduce_mean(tensor1)),
            # Loop body
            lambda tensor1: uniqueness_score(),
            # Loop variables
            [tensor1])
        # Returned loop value
        print(tensor2.eval())

Upvotes: 1

Views: 344

Answers (1)

javidcf
javidcf

Reputation: 59701

I think I get an idea of what you want, more or less, but I'm not sure I see the need for the boolean array. If you want to do some iterative process where you compute or retrieve some values until they meet some condition, you can do that without additional arrays. See for example this loop to sample some random values until all of them meet a condition:

import tensorflow as tf

# Draw five random numbers until all are > 0.5
with tf.Graph().as_default(), tf.Session() as sess:
    tf.random.set_random_seed(0)
    # Initial values, here simply initialized to zero
    tensor1 = tf.zeros([5], dtype=tf.float32)
    # Loop
    tensor1 = tf.while_loop(
        # Loop condition (negated goal condition)
        lambda tensor1: ~tf.math.reduce_all(tensor1 > 0.5),
        # Loop body
        lambda tensor1: tf.random.uniform(tf.shape(tensor1), dtype=tensor1.dtype),
        # Loop variables
        [tensor1])
    # Returned loop value
    print(tensor1.eval())
    # [0.7778928  0.9396961  0.572209   0.6187117  0.89615726]

See if this helps and leave a comment if you are still not sure how to apply this to your particular case.


EDIT: Seeing again your question, your uniqueness function computed both tensor1 and the mask, so maybe a more similar analogous code would be this:

import tensorflow as tf

def sample_numbers(shape, dtype):
    tensor1 = tf.random.uniform(shape, dtype=dtype)
    mask = tensor1 > 0.5
    return tensor1, mask

# Draw five random numbers until all are > 0.5
with tf.Graph().as_default(), tf.Session() as sess:
    tf.random.set_random_seed(0)
    # Initial values, here simply initialized to zero
    tensor1 = tf.zeros([5], dtype=tf.float32)
    mask = tf.zeros(tf.shape(tensor1), dtype=tf.bool)
    # Loop
    tensor1, _ = tf.while_loop(
        # Loop condition (negated goal condition)
        lambda tensor1, mask: ~tf.math.reduce_all(mask),
        # Loop body
        lambda tensor1, mask: sample_numbers(tf.shape(tensor1), tensor1.dtype),
        # Loop variables
        [tensor1, mask])
    # Returned loop value
    print(tensor1.eval())
    # [0.95553064 0.5170193  0.69573617 0.9501506  0.99776053]

Upvotes: 1

Related Questions