python tensorflow VarLenFeature与固定透镜Feature

j2datikz  于 2023-03-11  发布在  Python
关注(0)|答案(2)|浏览(97)

我尝试将不同大小的图片保存到tf-records中,我发现即使图片大小不同,我仍然可以用FixedLenFeature加载它们。
通过检查FixedLenFeatureVarLenFeature的文档,我发现区别似乎在于VarLenFeauture返回一个稀疏Tensor。
有人能举例说明一些应该使用FixedLenFeatureVarLenFeature的情况吗?

pw9qyyiw

pw9qyyiw1#

您可以加载图像,可能是因为您使用特征类型tf.train.BytesList()保存了图像,并且整个图像数据是列表中的一个大字节值。
如果我是对的,您将使用tf.decode_raw从TFRecord加载的图像中获取数据。
关于示例用例:我使用VarLenFeature保存对象检测任务的数据集:每个图像的边界框数量可变(等于图像中的对象),因此我需要另一个功能objects_number来跟踪对象数量(和边界框)。每个边界框本身是一个4浮动坐标列表
我使用下面的代码来加载它:

features = tf.parse_single_example(
    serialized_example,
    features={
        # We know the length of both fields. If not the
        # tf.VarLenFeature could be used
        'height': tf.FixedLenFeature([], tf.int64),
        'width': tf.FixedLenFeature([], tf.int64),
        'depth': tf.FixedLenFeature([], tf.int64),
        # Label part
        'objects_number': tf.FixedLenFeature([], tf.int64),
        'bboxes': tf.VarLenFeature(tf.float32),
        'labels': tf.VarLenFeature(tf.int64),
        # Dense data
        'image_raw': tf.FixedLenFeature([],tf.string)

    })

# Get metadata
objects_number = tf.cast(features['objects_number'], tf.int32)
height = tf.cast(features['height'], tf.int32)
width = tf.cast(features['width'], tf.int32)
depth = tf.cast(features['depth'], tf.int32)

# Actual data
image_shape = tf.parallel_stack([height, width, depth])
bboxes_shape = tf.parallel_stack([objects_number, 4])

# BBOX data is actually dense convert it to dense tensor
bboxes = tf.sparse_tensor_to_dense(features['bboxes'], default_value=0)

# Since information about shape is lost reshape it
bboxes = tf.reshape(bboxes, bboxes_shape)
image = tf.decode_raw(features['image_raw'], tf.uint8)
image = tf.reshape(image, image_shape)

注意,“image_raw”是一个固定长度的特征(只有一个元素),并且保存“bytes”类型的值,但是“bytes”类型的值本身可以有可变的大小(它是一个字节字符串,并且可以有很多符号),所以“image_raw”是一个列表,有一个“bytes”类型的元素,它可以非常大。

进一步详细说明它的工作原理:****特性是值列表,这些值具有特定的“类型”。
要素的数据类型是Tensor数据类型的子集,您有:

  • int 64(内存中的64位空间)
  • 字节(占用内存中任意多的字节)
  • 浮点数(在内存中占用32-64位idk多少)

可以检查hereTensor数据类型。
所以你可以不用VarLenFeatures来存储可变长度的数据(实际上你做得很好),但是首先你需要把它转换成字节/字符串特征,然后解码它,这是最常用的方法。

lh80um4z

lh80um4z2#

@Xyz已经对此有所阐述,另外,parse_example_v2的文档字符串也很有帮助(见下面的摘录):
附言:考虑到我们可以很容易地将数组转换为字节(numpy.ndarray.tobytestf.io.serialize_tensor),我想知道在哪些情况下VarLenFeature确实是首选。
例如,如果期望tf.float32VarLenFeatureft,则提供三个串行化的Example

serialized = [
  features
    { feature { key: "ft" value { float_list { value: [1.0, 2.0] } } } },
  features
    { feature []},
  features
    { feature { key: "ft" value { float_list { value: [3.0] } } }
]

则输出将如下所示:

{"ft": SparseTensor(indices=[[0, 0], [0, 1], [2, 0]],
                    values=[1.0, 2.0, 3.0],
                    dense_shape=(3, 2)) }

如果改为使用FixedLenSequenceFeature以及default_value = -1.0shape=[],则输出将如下所示:

{"ft": [[1.0, 2.0], [3.0, -1.0]]}

相关问题