2

J'ai une fonctionnalité comme une balise de poste. Ainsi, pour chaque observation, la fonction post_tag pourrait être une sélection d'étiquettes comme "oscars, brad-pitt, awards". Je voudrais être en mesure de transmettre cela en tant que caractéristique à une construction de modèle tensorflow en utilisant l'API d'estimation fonctionnant sur google cloud machine learning (selon this example mais adapté pour mon propre problème). Je ne suis pas sûr de savoir comment transformer cela en une fonctionnalité codée multi-hot dans tensorflow. J'essaie d'obtenir quelque chose de similaire à MultiLabelBinarizer dans sklearn idéalement.Codage multihot dans tensoflow (google cloud machine learning, tf estimateur api)

Je pense que this est un peu lié mais pas tout à fait ce dont j'ai besoin.

dire donc j'ai données comme:

id,post_tag 
1,[oscars,brad-pitt,awards] 
2,[oscars,film,reviews] 
3,[matt-damon,bourne] 

Je veux featurize, comme une partie de pré-traitement au sein tensorflow, comme:

id,post_tag_oscars,post_tag_brad_pitt,post_tag_awards,post_tag_film,post_tag_reviews,post_tag_matt_damon,post_tag_bourne 
1,1,1,1,0,0,0,0 
2,1,0,0,1,1,0,0 
3,0,0,0,0,0,1,1 

Mise à jour

Si j'ai post_tag_list est une chaîne comme "oscars, brad-pitt, awards" dans l'entrée csv. Et si j'essaie alors faire:

INPUT_COLUMNS = [ 
... 
tf.contrib.lookup.HashTable(tf.contrib.lookup.KeyValueTensorInitializer('post_tag_list', 
              tf.range(0, 10, dtype=tf.int64), 
              tf.string, tf.int64), 
          default_value=10, name='post_tag_list'), 
...] 

Je reçois cette erreur:

Traceback (most recent call last): 
    File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main 
    "__main__", fname, loader, pkg_name) 
    File "/usr/lib/python2.7/runpy.py", line 72, in _run_code 
    exec code in run_globals 
    File "/home/andrew_maguire/localDev/codeBase/pmc-analytical-data-mart/clickmodel/trainer/task.py", line 4, in <module> 
    import model 
    File "trainer/model.py", line 49, in <module> 
    default_value=10, name='post_tag_list'), 
    File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/lookup_ops.py", line 276, in __init__ 
    super(HashTable, self).__init__(table_ref, default_value, initializer) 
    File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/lookup_ops.py", line 162, in __init__ 
    self._init = initializer.initialize(self) 
    File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/lookup_ops.py", line 348, in initialize 
    table.table_ref, self._keys, self._values, name=scope) 
    File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/gen_lookup_ops.py", line 205, in _initialize_table_v2 
    values=values, name=name) 
    File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/op_def_library.py", line 767, in apply_op 
    op_def=op_def) 
    File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py", line 2632, in create_op 
    set_shapes_for_outputs(ret) 
    File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py", line 1911, in set_shapes_for_outputs 
    shapes = shape_func(op) 
    File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py", line 1861, in call_with_requiring 
    return call_cpp_shape_fn(op, require_shape_fn=True) 
    File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/common_shapes.py", line 595, in call_cpp_shape_fn 
    require_shape_fn) 
    File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/common_shapes.py", line 659, in _call_cpp_shape_fn_impl 
    raise ValueError(err.message) 
ValueError: Shape must be rank 1 but is rank 0 for 'key_value_init' (op: 'InitializeTableV2') with input shapes: [], [], [10]. 

Si je devais pad chaque post_tag_list être comme « oscars, brad-pitt, prix, AUTRES, AUTRES, LES AUTRES , AUTRE, AUTRE, AUTRE, AUTRE "donc c'est toujours 10 longtemps. Serait-ce une solution potentielle ici?

Ou dois-je d'une certaine manière connaître la taille de toutes les balises de poste que je pourrais passer ici (un peu mal défini comme les nouveaux créés tout le temps).

+0

Quelle est la cardinalité de l'ensemble de toutes les étiquettes? – rhaertel80

+1

C'est en fait ouvert. Lorsque quelqu'un crée un message, il peut également créer une nouvelle étiquette s'il ne trouve pas d'article existant. Jusqu'à présent, il est environ 7k et nous essayons de les encourager à ne pas faire de nouvelles balises, mais ils sont ouverts en ce sens que si une nouvelle histoire se brise sur quelque chose de nouveau, il pourrait obtenir une nouvelle étiquette. Il se peut donc que le fait de traiter les tags comme des mots similaires à un titre de publication et de les placer dans un espace d'intégration soit plus approprié. J'entraîne un doc2vec sur les tags et les posts et je vais passer ces vecteurs dans des fonctionnalités aussi denses. Espérait avoir des mannequins à utiliser pour les cols larges. – andrewm4894

+1

Les balises précédemment invisibles vont être mappées à un ou plusieurs vecteurs de poids "invisibles". Donc 7K est ce que je cherchais - ordre de grandeur, surtout. – rhaertel80

Répondre

1

Avez-vous essayé tf.contrib.lookup.Hashtable?

Voici un exemple d'utilisation de mon propre usage: https://github.com/TensorLab/tensorfx/blob/master/src/data/_transforms.py#L160 et un extrait exemple composé sur cette base:

import tensorflow as tf 
session = tf.InteractiveSession() 

entries = ['red', 'blue', 'green'] 
table = tf.contrib.lookup.HashTable(
    tf.contrib.lookup.KeyValueTensorInitializer(entries, 
               tf.range(0, len(entries), dtype=tf.int64), 
               tf.string, tf.int64), 
    default_value=len(entries), name='entries') 
tf.tables_initializer().run() 

value = tf.constant([['blue', 'red'], ['green', 'red']]) 
print(table.lookup(value).eval()) 

Je crois que recherche fonctionne aussi bien pour les tenseurs et SparseTensors réguliers (vous pourriez finir par ce dernier compte tenu de votre liste de valeurs de longueur variable).

+0

super - ressemble exactement à ce dont j'ai besoin, merci un million. J'ai juste besoin de jouer un peu pour comprendre comment je peux obtenir ma chaîne dans le CSV qui ressemble en fait à "red | blue | green" dans une liste comme dans votre exemple. Donc je pense quelque chose comme 'post_tags = post_tag_list.split (" | ")' et puis quelque chose comme 'INPUT_COLUMNS = [ ... tf.contrib.lookup.KeyValueTensorInitializer ('post_tags', tf.range (0, len (post_tags), DTYPE = tf.int64), tf.string, tf.int64), ... ] '' – andrewm4894

+0

ugh .. retraçage (appel le plus récent en dernier): fichier «/usr/lib/python2 .7/runpy.py ", ligne 174, dans _run_module_as_main " __main__ ", fname, loader, pkg_name) Fichier" /usr/lib/python2.7/runpy.py ", ligne 72, dans _run_code exec code dans run_globals Fichier "/home/andrew_maguire/localDev/codeBase/pmc-analytical-data-mart/clickmodel/trainer/task.py", ligne 4, dans modèle import fichier "formateur/model.py", ligne 32, dans post_tags = post_tag_list.split ("|") NameError: nom 'post_tag_list' est pas defined' – andrewm4894

+0

ne sais pas si je peux faire la .split ("|") dans la définition de INPUT_COLUMNS. Mais je ne sais pas exactement quel type lire le champ [post_tag_list] (ressemble à "red | green | blue") pour qu'il finisse comme une liste par entités dans votre exemple que je peux ensuite passer à la hashtable() – andrewm4894

1

Il y a quelques problèmes à résoudre ici. Tout d'abord, est la question d'un ensemble d'étiquettes qui ne cesse de croître. Vous aimeriez également savoir comment analyser les données de longueur variable à partir de CSV.

Pour gérer un jeu d'étiquettes en croissance, vous devez utiliser un OOV ou un hachage de caractéristiques. Nikhil a montré ce dernier, alors je vais montrer le premier.

Comment analyser les données de longueur variable de CSV

Supposons que la colonne avec des données de longueur variable utilise | en tant que séparateur, par ex.

csv = [ 
    "1,oscars|brad-pitt|awards", 
    "2,oscars|film|reviews", 
    "3,matt-damon|bourne", 
] 

Vous pouvez utiliser le code comme ceci pour convertir ceux à un SparseTensor.

import tensorflow as tf 

# Purposefully omitting "bourne" to demonstrate OOV mappings. 
TAG_SET = ["oscars", "brad-pitt", "awards", "film", "reviews", "matt-damon"] 
NUM_OOV = 1 

def sparse_from_csv(csv): 
    ids, post_tags_str = tf.decode_csv(csv, [[-1], [""]]) 
    table = tf.contrib.lookup.index_table_from_tensor(
     mapping=TAG_SET, num_oov_buckets=NUM_OOV, default_value=-1) 
    split_tags = tf.string_split(post_tags_str, "|") 
    return ids, tf.SparseTensor(
     indices=split_tags.indices, 
     values=table.lookup(split_tags.values), 
     dense_shape=split_tags.dense_shape) 

# Optionally create an embedding for this. 
TAG_EMBEDDING_DIM = 3 

ids, tags = sparse_from_csv(csv) 

embedding_params = tf.Variable(tf.truncated_normal([len(TAG_SET) + NUM_OOV, TAG_EMBEDDING_DIM])) 
embedded_tags = tf.nn.embedding_lookup_sparse(embedding_params, sp_ids=tags, sp_weights=None) 

# Test it out 
with tf.Session() as s: 
    s.run([tf.global_variables_initializer(), tf.tables_initializer()]) 
    print(s.run([ids, embedded_tags])) 

Vous verrez la sortie comme si (puisque l'intégration est aléatoire, le nombre exact changeront):

[array([1, 2, 3], dtype=int32), array([[ 0.16852427, 0.26074541, -0.4237918 ], 
     [-0.38550434, 0.32314634, 0.858069 ], 
     [ 0.19339906, -0.24429649, -0.08393878]], dtype=float32)] 

Vous pouvez voir que chaque colonne dans le CSV est représenté comme un ndarray, où les étiquettes sont maintenant des plongements en trois dimensions.

+0

Merci un million - c'est très utile. Je vais essayer de m'incorporer et de vous faire savoir comment je m'entends. – andrewm4894