Context
据了解,目前 TF 的 Record 文档还有一些不足之处。
我的问题是关于什么是最佳存储:
- 一个序列,
- 它的每个元素类别概率,以及
- 一些(上下文?)信息(例如序列的名称)
作为 TF 记录。
也就是说,这个问题考虑将序列和类概率存储为通道与字节字符串,以及元信息是否应该作为tf.train.Example
或作为上下文tf.train.SequenceExample
。 (请参阅底部的问题)。
M.W.E.
例如,假设我的外观顺序如下
seq = [
# el1, el2
[ 0, 1 ], # channel 1
[ 0, 1 ] # channel 2
]
即它是一个 2 通道序列fixedlength(本例中为 2),其中值只能是整数值。
我们尝试将序列分为三个类
cls_probs = [
#cls1, cls2, cls3
[0 , 0.9 , 0.1 ], # class probabilities element 1
[0 , 0.1 , 0.9 ] # class probabilities element 2
]
实际上两者都有效seq
and cls_probs
are numpy.array
s.
仅网络requires此信息。但是,我也有一些元数据,我想将其与序列保留在一起。
e.g.
meta = {
'name': 'my_seq', # safer to keep this with the data rather than as file name
'meta_val_1': 100, # not used by network, but may be useful when evaluating network's predictions for this particular sequence
'meta_val_2': 10
}
制作TF记录
tf.train.示例
然后我有几种方法可以构建我的tf.train.Example
:
作为渠道
example = tf.train.Example(
features = tf.train.Features(
feature = {
'channel_1': tf.train.Feature(int64_list=tf.train.Int64List(value=seq[:,0])),
'channel_2': tf.train.Feature(int64_list=tf.train.Int64List(value=seq[:,1])),
'class_1' : tf.train.Feature(float_list=tf.train.FloatList(value=cls_probs[:,0])),
'class_2' : tf.train.Feature(float_list=tf.train.FloatList(value=cls_probs[:,1])),
'class_3' : tf.train.Feature(float_list=tf.train.FloatList(value=cls_probs[:,2])),
'name' : tf.train.Feature(bytes_list=tf.train.BytesList(value=[f'{meta["name"]}'.encode('utf-8')])),
# should these be FloatList even though it is just a single value?
# should these be included here if they are not used by the network?
'val_1' : tf.train.Feature(float_list=tf.train.FloatList(value=[f'{meta["meta_val_1"]}'])),
'val_2' : tf.train.Feature(float_list=tf.train.FloatList(value=[f'{meta["meta_val_2"]}'])),
})
)
where f'{variable}'.encode('utf-8')
目前不建议fb'<string>' (note: f-strings
仅适用于 python3.6+)。
这种格式有点好,因为每个序列通道都是明确的。然而,它也很冗长,并且在加载到网络中时需要进行预处理。
作为字符串
或者,我可以将数组转储到字符串中
example = tf.train.Example(
features = tf.train.Features(
feature = {
'sequence' : tf.train.Feature(bytes_list=tf.train.BytesList(value=seq.tostring())),
'cls_probs': tf.train.Feature(bytes_list=tf.train.BytesList(value=cls_probs.tostring())),
# ... see encoding of meta values from above
})
)
tf.train.Sequence示例
TF Records 还接受另一种形式:tf.train.SequenceExample
. SequenceExample
需要上下文特征和未命名特征的有序列表。
作为渠道
所以上面的重组为channels例子:
example = tf.train.SequenceExample(
context = tf.train.Features(
feature = {
'Name' : tf.train.Feature(bytes_list=tf.train.BytesList(value=[f'{meta["name"]}'.encode('utf-8')])),
'Val_1': tf.train.Feature(float_list=tf.train.FloatList(value=[f'{meta["meta_val_1"]}'])),
'Val_2': tf.train.Feature(float_list=tf.train.FloatList(value=[f'{meta["meta_val_2"]}'])),
}
),
feature_lists = tf.train.FeatureLists(
feature_list = {
'sequence': tf.train.FeatureList(
feature = [
tf.train.Feature(int64_list=tf.train.Int64List(value=seq[:,0])),
tf.train.Feature(int64_list=tf.train.Int64List(value=seq[:,1])),
]
),
'class_probabilities': tf.train.FeatureList(
feature = [
tf.train.Feature(float_list=tf.train.FloatList(value=cls_probs[:,0])),
tf.train.Feature(float_list=tf.train.FloatList(value=cls_probs[:,1])),
tf.train.Feature(float_list=tf.train.FloatList(value=cls_probs[:,2]))
]
)
}
)
)
作为字符串
同样我们可以创建 asstring例子:
example = tf.train.SequenceExample(
context = tf.train.Features(
# see above
),
feature_lists = tf.train.FeatureLists(
feature_list = {
'sequence': tf.train.FeatureList(
feature = [
tf.train.Feature(bytes_list=tf.train.BytesList(value=seq.tostring()))
]
),
'class_probabilities': tf.train.FeatureList(
feature = [
tf.train.Feature(bytes_list=tf.train.BytesList(value=cls_probs.tostring()))
]
)
}
)
)
问题
在这里我给出了 M.W.E.了解如何构建一个示例(准备导出到 TF 记录)tf.train.Example
and tf.train.SequenceExample
。此外,我还演示了如何按通道执行此操作或通过转储为字节字符串来执行此操作。这两种方法(作为通道/作为字符串)都包含示例中的元信息。
因此我的问题是:
-
哪种存储方式(作为通道/作为字符串)更优化(对于读取、写入、重用等)?
-
考虑到应与示例一起保留的元信息,最好使用tf.train.Example
并将元信息作为特征存储在那里?或使用tf.train.SequenceExample
并将元信息存储在上下文参数中?
有谁知道这四种策略中的任何一种是否有任何显着的优点/缺点?
对于那些想要在更大的、更少虚拟的数据上进行测试的人,可以找到一些用于生成此代码的函数below
最后我想指出这一点中等职位其中详细阐述了 TF 的文档。