为什么我的TFRecord文件比csv大得多?

时间:2017-06-28 06:58:24

标签: tensorflow

我一直认为作为二进制格式,TFRecord将比人类可读的csv消耗更少的空间。但是当我试图比较它们时,我发现事实并非如此。

例如,我在这里创建一个带有num_rows X 10标签的num_rows矩阵,并将其另存为csv。我通过将其保存到TFRecors来做同样的事情:

import pandas as pd
import tensorflow as tf
from random import randint

num_rows = 1000000
df = pd.DataFrame([[randint(0,300) for r in xrange(10)] + [randint(0, 1)] for i in xrange(num_rows)])

df.to_csv("data/test.csv", index=False, header=False)

writer = tf.python_io.TFRecordWriter('data/test.bin')
for _, row in df.iterrows():
    arr = list(row)
    features, label = arr[:-1], arr[-1]
    example = tf.train.Example(features=tf.train.Features(feature={
        'features' : tf.train.Feature(int64_list=tf.train.Int64List(value=features)),
        'label':     tf.train.Feature(int64_list=tf.train.Int64List(value=[label])),
    }))
    writer.write(example.SerializeToString())
writer.close()

创建二进制文件不仅比csv(2秒VS 1分50秒)花费更多时间,而且它还使用了近2倍的空间(38Mb VS 67.7Mb)。

我能正确地做到吗?如何使输出文件更小(看到TFRecordCompressionType),但还有什么我可以做的吗?更大尺寸的原因是什么?

Vijay关于int64 的评论是有道理的,但仍然没有回答所有问题。 Int64消耗8个字节,因为我在csv中存储数据,整数的字符串表示应该是8的长度。所以如果我这样做df = pd.DataFrame([[randint(1000000,99999999) for r in xrange(10)] for i in xrange(num_rows)])我仍然会得到一个稍大的大小。现在它是90.9Mb VS 89.1Mb。除此之外,csv为每个整数之间的每个逗号存储1个字节。

2 个答案:

答案 0 :(得分:1)

您的文件较大的事实是由于TFRecords对每一行的开销,特别是每次都存储标签名称的事实。

在您的示例中,如果您增加功能的数量(从10到1000),您会发现您的tfrecord文件实际上大约是csv的一半大小。

此外,整数存储在64位上的事实最终无关紧要,因为序列化使用" varint"编码取决于整数的值,而不是其初始编码。以上面的示例为例,而不是0到300之间的随机值,使用常量值300:您将看到文件大小增加。

请注意,用于编码的字节数不完全是整数本身的字节数。因此值255仍然需要两个字节,但值127将占用一个字节。有趣的是,负值会带来巨大的损失:无论如何都要存储10个字节。

值和存储要求之间的对应关系可以在protobuf的函数_SignedVarintSize中找到。

答案 1 :(得分:0)

这可能是因为你生成的数字在0~300范围内,所以它们只需要3个字节来存储一个数字,但是当它们作为int64存储在tfrecords中时,它至少需要8个字节(不太确定)存储一个号码。如果你生成的数字在0~2 ^ 64-1范围内,我认为tfrecords文件会比csv文件小得多。