2016-10-05 3 views
2

J'ai un input_fn de base qui peut être utilisé avec les estimateurs de Tensorflow ci-dessous. Il fonctionne parfaitement sans définir le paramètre num_epochs; le tenseur obtenu a une forme discrète. Transmettre num_epochs comme autre chose que None donne une forme inconnue. Mon problème réside dans la construction de tenseurs clairsemés tout en utilisant num_epochs; Je n'arrive pas à comprendre comment créer de façon générique les tenseurs sans connaître la forme du tenseur d'entrée.Comment créer `input_fn` en utilisant` read_batch_examples` avec l'ensemble `num_epochs`?

Quelqu'un peut-il penser à une solution à ce problème? Je voudrais être en mesure de passer num_epochs=1 pour être en mesure d'évaluer seulement 1 fois sur l'ensemble de données, ainsi que de passer à predict pour donner un ensemble de prédictions de la taille de l'ensemble de données, ni plus ni moins.

def input_fn(batch_size): 
    examples_op = tf.contrib.learn.read_batch_examples(
     FILE_NAMES, 
     batch_size=batch_size, 
     reader=tf.TextLineReader, 
     num_epochs=1, 
     parse_fn=lambda x: tf.decode_csv(x, [tf.constant([''], dtype=tf.string)] * len(HEADERS))) 

    examples_dict = {} 
    for i, header in enumerate(HEADERS): 
     examples_dict[header] = examples_op[:, i] 

    continuous_cols = {k: tf.string_to_number(examples_dict[k], out_type=tf.float32) 
         for k in CONTINUOUS_FEATURES} 

    # Problems lay here while creating sparse categorical tensors 
    categorical_cols = { 
     k: tf.SparseTensor(
      indices=[[i, 0] for i in range(examples_dict[k].get_shape()[0])], 
      values=examples_dict[k], 
      shape=[int(examples_dict[k].get_shape()[0]), 1]) 
     for k in CATEGORICAL_FEATURES} 

    feature_cols = dict(continuous_cols) 
    feature_cols.update(categorical_cols) 
    label = tf.string_to_number(examples_dict[LABEL], out_type=tf.int32) 

    return feature_cols, label 

Répondre

3

J'ai résolu le problème ci-dessus en créant une fonction spécifique à ce qui est attendu sur un input_fn; il prend dans une colonne dense et crée un SparseTensor sans connaître la forme. La fonction a été rendue possible en utilisant tf.range et tf.shape. Sans plus tarder, voici le code input_fn générique de travail qui fonctionne indépendamment de num_epochs être mis:

def input_fn(batch_size): 
    examples_op = tf.contrib.learn.read_batch_examples(
     FILE_NAMES, 
     batch_size=batch_size, 
     reader=tf.TextLineReader, 
     num_epochs=1, 
     parse_fn=lambda x: tf.decode_csv(x, [tf.constant([''], dtype=tf.string)] * len(HEADERS))) 

    examples_dict = {} 
    for i, header in enumerate(HEADERS): 
     examples_dict[header] = examples_op[:, i] 

    feature_cols = {k: tf.string_to_number(examples_dict[k], out_type=tf.float32) 
        for k in CONTINUOUS_FEATURES} 

    feature_cols.update({k: dense_to_sparse(examples_dict[k]) 
         for k in CATEGORICAL_FEATURES}) 

    label = tf.string_to_number(examples_dict[LABEL], out_type=tf.int32) 

    return feature_cols, label 


def dense_to_sparse(dense_tensor): 
    indices = tf.to_int64(tf.transpose([tf.range(tf.shape(dense_tensor)[0]), tf.zeros_like(dense_tensor, dtype=tf.int32)])) 
    values = dense_tensor 
    shape = tf.to_int64([tf.shape(dense_tensor)[0], tf.constant(1)]) 

    return tf.SparseTensor(
     indices=indices, 
     values=values, 
     shape=shape 
    ) 

Hope this helps quelqu'un!