J'ai un tenseur de dimensions irrégulier [BATCH_SIZE, TIME_STEPS, EMBEDDING_DIM]. Je veux augmenter le dernier axe avec des données d'un autre tenseur de forme [BATCH_SIZE, AUG_DIM]. Chaque pas de temps d'un exemple donné est augmenté de la même valeur.

Si le tenseur n'était pas irrégulier avec la variation de TIME_STEPS pour chaque exemple, je pourrais simplement remodeler le deuxième tenseur avec tf.repeat puis utiliser tf.concat:

import tensorflow as tf


# create data
# shape: [BATCH_SIZE, TIME_STEPS, EMBEDDING_DIM]
emb = tf.constant([[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [0, 0, 0]]])
# shape: [BATCH_SIZE, 1, AUG_DIM]
aug = tf.constant([[[8]], [[9]]])

# concat
aug = tf.repeat(aug, emb.shape[1], axis=1)
emb_aug = tf.concat([emb, aug], axis=-1)

Cette approche ne fonctionne pas lorsque emb est irrégulier car emb.shape[1] est inconnu et varie selon les exemples:

# rag and remove padding
emb = tf.RaggedTensor.from_tensor(emb, padding=(0, 0, 0))

# reshape for augmentation - this doesn't work
aug = tf.repeat(aug, emb.shape[1], axis=1)

ValueError: tentative de conversion d'une valeur (None) avec un type non pris en charge () en un Tensor.

Le but est de créer un tenseur irrégulier emb_aug qui ressemble à ceci:

<tf.RaggedTensor [[[1, 2, 3, 8], [4, 5, 6, 8]], [[1, 2, 3 ,9]]]>

Des idées?

3
JuliettVictor 12 mars 2021 à 21:55

1 réponse

Meilleure réponse

Le moyen le plus simple de le faire est de simplement faire de votre tenseur irrégulier un tenseur régulier en utilisant tf.RaggedTensor.to_tensor(), puis effectuez le reste de votre solution. Je suppose que vous avez besoin que le tenseur reste irrégulier. La clé est de trouver le row_lengths de chaque lot dans votre tenseur en lambeaux, puis utilisez ces informations pour rendre votre tenseur d'augmentation irrégulier.

Exemple :

import tensorflow as tf


# data
emb = tf.constant([[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [0, 0, 0]]])
aug = tf.constant([[[8]], [[9]]])

# make embeddings ragged for testing
emb_r = tf.RaggedTensor.from_tensor(emb, padding=(0, 0, 0))

print(emb_r.shape)
# (2, None, 3)

Ici, nous allons utiliser une combinaison de row_lengths et sequence_mask < / a> pour créer un nouveau tenseur irrégulier.

# find the row lengths of the embeddings
rl = emb_r.row_lengths()

print(rl)
# tf.Tensor([2 1], shape=(2,), dtype=int64)

# find the biggest row length
max_rl = tf.math.reduce_max(rl)

print(max_rl)
# tf.Tensor(2, shape=(), dtype=int64)

# repeat the augmented data `max_rl` number of times
aug_t = tf.repeat(aug, repeats=max_rl, axis=1)

print(aug_t)
# tf.Tensor(
# [[[8]
#   [8]]
# 
#  [[9]
#   [9]]], shape=(2, 2, 1), dtype=int32)

# create a mask
msk = tf.sequence_mask(rl)

print(msk)
# tf.Tensor(
# [[ True  True]
#  [ True False]], shape=(2, 2), dtype=bool)

De là, nous pouvons utiliser tf.ragged.boolean_mask pour augmenter données irrégulières

# make the augmented data a ragged tensor
aug_r = tf.ragged.boolean_mask(aug_t, msk)
print(aug_r)
# <tf.RaggedTensor [[[8], [8]], [[9]]]>

# concatenate!
output = tf.concat([emb_r, aug_r], 2)
print(output)
# <tf.RaggedTensor [[[1, 2, 3, 8], [4, 5, 6, 8]], [[1, 2, 3, 9]]]>

Vous pouvez trouver la liste des méthodes tensorflow prenant en charge les tenseurs irréguliers ici

1
gobrewers14 13 mars 2021 à 15:22