Tensorflow a-t-il quelque chose de similaire à scikit learn n encodeur à chaud pour le traitement de données catégoriques? L'utilisation d'un espace réservé de tf.string se comporterait-elle comme des données catégoriques?
Je me rends compte que je peux pré-traiter manuellement les données avant de les envoyer à tensorflow, mais les intégrer est très pratique.
Depuis TensorFlow 0.8, il existe maintenant un natif one-hot op, tf.one_hot
qui permet de convertir un ensemble d'étiquettes clairsemées en une représentation dense one-hot. Cela s'ajoute à tf.nn.sparse_softmax_cross_entropy_with_logits
, qui peut dans certains cas vous permettre de calculer l'entropie croisée directement sur les étiquettes clairsemées au lieu de les convertir en one-hot.
Réponse précédente, au cas où vous voudriez le faire à l'ancienne: @ La réponse de Salvador est correcte - il n'y avait pas d'opérateur natif pour le faire . Au lieu de le faire numpy, vous pouvez le faire de manière native dans tensorflow en utilisant les opérateurs peu dense à dense:
num_labels = 10
# label_batch is a tensor of numeric labels to process
# 0 <= label < num_labels
sparse_labels = tf.reshape(label_batch, [-1, 1])
derived_size = tf.shape(label_batch)[0]
indices = tf.reshape(tf.range(0, derived_size, 1), [-1, 1])
concated = tf.concat(1, [indices, sparse_labels])
outshape = tf.pack([derived_size, num_labels])
labels = tf.sparse_to_dense(concated, outshape, 1.0, 0.0)
La sortie, labels, est une matrice one-hot de batch_size x num_labels.
Notez également qu'à compter du 2016-02-12 (qui, je suppose, fera éventuellement partie d'une version 0.7), TensorFlow possède également le tf.nn.sparse_softmax_cross_entropy_with_logits
op, qui peut dans certains cas vous permettre de suivre une formation sans avoir à convertir en un seul encodage. .
Modifié pour ajouter: À la fin, vous devrez peut-être explicitement définir la forme des étiquettes. L'inférence de forme ne reconnaît pas la taille du composant num_labels. Si vous n'avez pas besoin d'une taille de lot dynamique avec la taille dérivée, cela peut être simplifié.
Édité le 12/02/2016 pour modifier l'attribution de outshape par commentaire ci-dessous.
tf.one_hot()
est disponible dans TF et facile à utiliser.
Supposons que vous avez 4 catégories possibles (chat, chien, oiseau, humain) et 2 instances (chat, humain). Donc, votre depth=4
et votre indices=[0, 3]
import tensorflow as tf
res = tf.one_hot(indices=[0, 3], depth=4)
with tf.Session() as sess:
print sess.run(res)
Gardez à l'esprit que si vous fournissez index = -1, vous obtiendrez tous les zéros dans votre vecteur one-hot.
Ancienne réponse, lorsque cette fonction n'était pas disponible.
Après avoir jeté un œil sur le documentation python , je n'ai rien trouvé de semblable. Une chose qui renforce ma conviction que cela n'existe pas, c'est que leur propre exemple ils écrivent one_hot
manuellement.
def dense_to_one_hot(labels_dense, num_classes=10):
"""Convert class labels from scalars to one-hot vectors."""
num_labels = labels_dense.shape[0]
index_offset = numpy.arange(num_labels) * num_classes
labels_one_hot = numpy.zeros((num_labels, num_classes))
labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
return labels_one_hot
Vous pouvez également le faire dans scikitlearn .
numpy
le fait!
import numpy as np
np.eye(n_labels)[target_vector]
Un moyen simple et rapide d’encoder à chaud un entier ou une liste d’entiers:
a = 5
b = [1, 2, 3]
# one hot an integer
one_hot_a = tf.nn.embedding_lookup(np.identity(10), a)
# one hot a list of integers
one_hot_b = tf.nn.embedding_lookup(np.identity(max(b)+1), b)
Les versions récentes de TensorFlow (nightlies et peut-être même 0.7.1) ont un op appelé tf.one_hot qui fait ce que vous voulez. Vérifiez-le!
D'autre part, si vous avez une matrice dense et que vous souhaitez y rechercher et y agréger des valeurs, vous souhaiterez utiliser la fonction embedding_lookup.
Cela est peut-être dû aux modifications apportées à Tensorflow depuis novembre 2015, mais la réponse de @ dga a généré des erreurs. Je l'ai fait fonctionner avec les modifications suivantes:
sparse_labels = tf.reshape(label_batch, [-1, 1])
derived_size = tf.shape(sparse_labels)[0]
indices = tf.reshape(tf.range(0, derived_size, 1), [-1, 1])
concated = tf.concat(1, [indices, sparse_labels])
outshape = tf.concat(0, [tf.reshape(derived_size, [1]), tf.reshape(num_labels, [1])])
labels = tf.sparse_to_dense(concated, outshape, 1.0, 0.0)
Jetez un coup d'oeil à tf.nn.embedding_lookup . Il mappe des identifiants catégoriels à leurs intégrations.
Pour un exemple d'utilisation des données d'entrée, voir here .
Vous pouvez utiliser tf.sparse_to_dense :
L'argument sparse_indices indique où aller ceux-ci, output_shape doit être défini sur le nombre de sorties possibles (par exemple le nombre d'étiquettes) et sparse_values doit être 1 avec le type souhaité (il déterminera le type de sortie à partir du type de sparse_values).
Il y a embedding_ops dans Scikit Flow et des exemples traitant des variables catégorielles, etc.
Si vous commencez juste à apprendre TensorFlow, je vous suggérerais d'essayer exemples dans TensorFlow/skflow d'abord, puis une fois que vous maîtriserez mieux TensorFlow, ce sera assez facile pour vous. insérer du code TensorFlow pour créer le modèle personnalisé souhaité (il existe également des exemples).
J'espère que ces exemples de compréhension d'images et de texte pourront vous aider à démarrer et à nous signaler si vous rencontrez des problèmes! (publier des numéros ou tag skflow dans SO).
Les versions actuelles de tensorflow implémentent la fonction suivante pour créer des tenseurs one-hot:
https://www.tensorflow.org/versions/master/api_docs/python/array_ops.html#one_hot
Comme mentionné ci-dessus par @dga, Tensorflow a tf.one_hot maintenant:
labels = tf.constant([5,3,2,4,1])
highest_label = tf.reduce_max(labels)
labels_one_hot = tf.one_hot(labels, highest_label + 1)
array([[ 0., 0., 0., 0., 0., 1.],
[ 0., 0., 0., 1., 0., 0.],
[ 0., 0., 1., 0., 0., 0.],
[ 0., 0., 0., 0., 1., 0.],
[ 0., 1., 0., 0., 0., 0.]], dtype=float32)
Vous devez spécifier la profondeur, sinon vous obtiendrez un tenseur one-hot élagué.
Si vous aimez le faire manuellement:
labels = tf.constant([5,3,2,4,1])
size = tf.shape(labels)[0]
highest_label = tf.reduce_max(labels)
labels_t = tf.reshape(labels, [-1, 1])
indices = tf.reshape(tf.range(size), [-1, 1])
idx_with_labels = tf.concat([indices, labels_t], 1)
labels_one_hot = tf.sparse_to_dense(idx_with_labels, [size, highest_label + 1], 1.0)
array([[ 0., 0., 0., 0., 0., 1.],
[ 0., 0., 0., 1., 0., 0.],
[ 0., 0., 1., 0., 0., 0.],
[ 0., 0., 0., 0., 1., 0.],
[ 0., 1., 0., 0., 0., 0.]], dtype=float32)
Remarquez les arguments dans tf.concat ()
In [7]: one_hot = tf.nn.embedding_lookup(np.eye(5), [1,2])
In [8]: one_hot.eval()
Out[8]:
array([[ 0., 1., 0., 0., 0.],
[ 0., 0., 1., 0., 0.]])
fonctionne sur TF version 1.3.0. À partir de septembre 2017.
Il y a plusieurs façons de le faire.
ans = tf.constant([[5, 6, 0, 0], [5, 6, 7, 0]]) #batch_size*max_seq_len
labels = tf.reduce_sum(tf.nn.embedding_lookup(np.identity(10), ans), 1)
>>> [[ 0. 0. 0. 0. 0. 1. 1. 0. 0. 0.]
>>> [ 0. 0. 0. 0. 0. 1. 1. 1. 0. 0.]]
L'autre façon de le faire est.
labels2 = tf.reduce_sum(tf.one_hot(ans, depth=10, on_value=1, off_value=0, axis=1), 2)
>>> [[0 0 0 0 0 1 1 0 0 0]
>>> [0 0 0 0 0 1 1 1 0 0]]
Ma version de @CFB et de @dga, par exemple, a été légèrement raccourcie pour faciliter la compréhension.
num_labels = 10
labels_batch = [2, 3, 5, 9]
sparse_labels = tf.reshape(labels_batch, [-1, 1])
derived_size = len(labels_batch)
indices = tf.reshape(tf.range(0, derived_size, 1), [-1, 1])
concated = tf.concat(1, [indices, sparse_labels])
labels = tf.sparse_to_dense(concated, [derived_size, num_labels], 1.0, 0.0)