在哪里执行 tf.string_split() 操作

Where to perform tf.string_split() operation

我正在为如何调整 ML 引擎示例以使用长文本字符串作为输入功能而苦苦挣扎。我正在构建一个自定义估算器(像这样 example)并希望理解 "best practices" 并着眼于部署模型——我希望 [=43] 中包含尽可能多的转换=] 本身,以便在服务时更容易。考虑一个包含 "text" 列的 .csv,其中包含诸如 "This is a sentence" 之类的句子——最终我需要使用 tf.string_split() 将此文本拆分为标记,然后将单个标记转换为索引(使用词汇文件或类似文件),然后将它们传递给嵌入。假设 "This is a sentence" 是我们正在处理的句子,下面概述了一种方法。我的问题是这是否是 "optimal" 实现此目的的方法,或者是否有更好的方法来做到这一点。

特征列

def get_feature_columns():
    sparse = tf.contrib.layers.sparse_column_with_integerized_feature(
        column_name = 'text',
        bucket_size = 100000,
        combiner = "sum")
    embedding = tf.contrib.layers.embedding_column(
        sparse, dimension = word_embedding_size)

    return set([embedding])

输入函数

def generate_input_fn():
    # read rows
    filename_queue = tf.train.string_input_producer(filenames, 
        num_epochs=num_epochs, shuffle=shuffle, capacity=32)

    reader = tf.TextLineReader(skip_header_lines=skip_header_lines)

    _, rows = reader.read_up_to(filename_queue, num_records=batch_size)

    text, label = tf.decode_csv(rows, record_defaults=[[""], [""]])

    # transform text from sentence --> tokens --> integerized tokens
    text_index = tf.contrib.lookup.index_table_from_file(vocabulary_file = vocab_file)
    tokens = tf.string_split(text)
    tokens_idx = text_index.lookup(tokens)

    features = dict(zip(['text', 'label'], [tokens_idx, label]))

    features = tf.train.shuffle_batch(features,batch_size)

    return features, features.pop('label')

Model FN: 还有其他上下文,但一般来说这是通过..

input_layer = tf.feature_column.input_layer(features, 
        feature_columns = get_feature_columns())

我知道一种方法是提前进行拆分和索引,但由于我访问 .csv 的方式,目前无法做到这一点。我对这种方法的问题是,我觉得转换应该全部在 get_feature_columns() 内处理——是 "best practices" 在发送到模型之前处理输入函数内的转换,还是我应该尝试找到一种在模型本身内执行拆分或查找的方法?

我担心的是,我现在需要一个单独的 serving_input_fn(),它需要执行与当前 input_fn() 中相同的转换,但如果更改,这些转换很容易不同步是为一个人而不是另一个人做的。是否可以建议任何其他选项来避免此问题?

input_fn 中发生的事情与 model_fn 中发生的事情之间的区别完全取决于您在推理时想要的行为。作为一般经验法则:

  • 如果你需要对训练输入和预测输入都进行转换,把它放在model_fn
  • 如果您只需要对训练输入或预测输入进行转换,请将其放入相应的input_fn(服务或training/eval)

这只是为了方便起见的规则,无论哪种方式都行得通。但通常您希望在 training/eval 的图外尽可能多地进行预处理,这样当您训练多个时期或尝试新的模型架构时,就不会重复预处理的计算时间。但是,您随后希望将尽可能多的预处理 放在 图形中以进行推理,因为从延迟的角度来看,它(通常)比代理更有效。

希望这能解决问题。