EvalSpec input_fn:特征为数组的情况

时间:2018-11-20 20:42:52

标签: tensorflow tensorflow-datasets tensorflow-estimator

我在理解Estimator API和tf.estimator.EvalSpec的某些细节时遇到了一些麻烦。 在EvalSpec中,用户应给出一个input_fn。调用input_fn应该返回A tuple (features, labels)。 据我了解,这些功能可以是由“功能名称”作为键的字典,其值是值的张量。例如,如果我有一批100个示例,并且有一个称为“权重”的特征,我将在特征字典中创建一个条目,该条目的形状为张量(100,1),具有关键权重,并且所有权重均例子,对吧?

但是:

  • 如果我的初始特征已经是张量,例如“ size”,它是3个double值的数组,那该怎么办?如何通过input_fn输入它?

还有我最感兴趣的问题:

  • 如果我的最初特征是可变长度数组怎么办?例如,我的功能可能是“所有购买产品的价格”,并且可能是一个可变长度的双精度数组(这对应于功能规格中的tf.io.VarLenFeature)。如何通过input_fn发送几个示例?

这些类型的功能是否与Estimator API“兼容”?

谢谢!

1 个答案:

答案 0 :(得分:0)

我对Estimator API还是陌生的,但是通过S.O我学到了很多东西。社区,并会尝试回答您的问题。

首先,我想向您介绍此colab。目前,这是我在Estimator中使用的约定。

您是正确的,因为input_fnTRAIN模式的EVAL都是(features, labels)形式的元组。

所以让我们解决您的第一个问题:

  

如果我的初始特征已经是一个张量,例如“ size”,它是3个double值的数组,该怎么办?如何通过input_fn输入它?

好吧,这需要我回溯一下您输入的内容:

  

一批100个示例和一个称为“权重”的特征,我将在特征字典中创建一个形状为(100,1)的张量的条目,

为确保我理解正确,您是在说,如果不是Tensor[100, 1],而是形状为Tensor的{​​{1}},情况3加倍,所以[100, <size>]

如果是这种情况,那完全没有问题。在链接的colab中,输入的单个示例的形状为[100, 3]。因此,[20, 7]中的Tensor很简单。

简而言之,就是将您指定为元组的[3]部分的任何内容都传递给features。因此,您要传递model_fn的{​​{1}},则返回Tensor的元组。但是,正如另一位用户在S.O.上向我指出的那样。我会向您提供相同的建议-使用字典,例如

[batch_size, size]

作为参考,让我们以colab中的([batch_size, size], labels)为例,我在上面做了与上面建议相同的事情:

my_data = # Tensor with shape [batch_size, size]
features = {'my_data': my_data}
...
return (features, labels)

为简单起见,我假设您正在使用input_fn。如果您的数据未存储为TF def input_fn(filenames:list, params): mode = params['mode'] if 'mode' in params else 'train' batch_size = params['batch_size'] shuffle(filenames) # <--- far more efficient than tf dataset shuffle dataset = tf.data.TFRecordDataset(filenames) # using fio's SCHEMA fill the TF Feature placeholders with values dataset = dataset.map(lambda record: fio.from_record(record)) # using fio's SCHEMA restructure and unwrap (if possible) features (because tf records require wrapping everything into a list) dataset = dataset.map(lambda context, features: fio.reconstitute((context, features))) # dataset should be a tuple of (features, labels) dataset = dataset.map(lambda context, features: ( {"input_tensors": features[I_FEATURE]}, # features <--- wrapping it in a dictionary features[O_FEATURE] # labels ) ) ,则需要替换第1行。

tf.data.Dataset

但是,您可以构建数据集,例如Record 1. dataset = tf.data.TFRecordDataset(filenames) 2. dataset = dataset.map(lambda record: fio.from_record(record)) 3. dataset = dataset.map(lambda context, features: fio.reconstitute((context, features))) 等,并删除第2行和第3行,因为您无需从TF {{1}中恢复FeatureColumn } s。

现在让我们解决第二个问题,可变长度数组。

与上面的一样!将其包装在字典中并返回。

除了从TF from_tensor_slices s中恢复(Sequence)Example的显着例外外,这是正确的,在那里您将需要Record