csv文件对于不同形状张量的存储与解析
关于同一个csv文件存储和解析不同形状张量的问题,看似简单,暗坑很多。
csv文件对于不同形状张量的存储与解析
起因
最近写项目测试的时候,发小有一个小的需求,需要将不同形状的张量存入同一个文件中,同时需要记录其形状信息,从而方便算子的测试。但由于numpy
中的savetxt
等方法都要求张量形状一致,所以没办法直接使用。
一开始想的比较简单,使用csv
文件来存储,分四列数据,前三列记录三个维度的形状信息,最后一列将整个张量存储下来。但实际开始写之后才发现,其中有一些问题处理起来比较麻烦,特此记录一下。
初步尝试
生成数据的代码比较简单,使用numpy
随机生成一个张量,不仅张量中的数据是随机的,张量本身的形状也是在一定范围内随机生成的。
1 |
|
这个函数返回一个元组,前三个元素记录形状,最后一个元素是张量本身。然后写一个简单的批量数据生成代码。
1 |
|
问题出现
看起来没有任何问题,调用它来生成文件。
1 |
|
这里的意思是生成10个张量,每个张量的形状最大为(8, 8, 320)
,每一个维度都是0到该数之间的一个随机整数,数据类型是float32
。我们来看看生成的csv
文件的内容,这里只取有问题的一部分展示。
1 |
|
会发现生成的csv
文件中出现了省略号,这是numpy
在输出张量的时候为了美观做的处理,但当他被解析为字符串后,数据信息就丢失了。这一点比较好处理,只需要令numpy
完整输出整个张量即可,我们修改generateDataset
函数。
1 |
|
上述问题就得到了解决。
文件解析
到此我以为这个需求已经实现了,只需要再写一个解析csv
文件的函数就好了,于是我写了如下函数。
1 |
|
我们调用它来读取刚才生产的文件。
1 |
|
这里只输出第一条记录,下面展示一部分。
1 |
|
这里发现输出的张量中有一些换行符,这是由于numpy
格式化输出张量带来的后果,一开始我并没有觉得这是个问题,以numpy
的强大能力,应该可以就这样将这个张量解析出来。
问题又出现
这里使用type
函数查看从文件中读出来的张量的真实类型,即type(data[0][3])
,发现是<class 'str'>
,然后我做了如下尝试。
1 |
|
但是报如下错误。
1 |
|
经过一通查询,原来np.fromstring
是根据dtype
来解析字符串的,它要求字符串的大小必须是元素个数的整数倍。但在我们存文件的时候会发现,有些数字是科学计数法存入的,有些数是普通的浮点数形式。对于字符串来说,每个数字映射后的字符串长度显然不一定是float32
类型的4字节,所以解析的时候肯定会出问题。(PS.
又一个因为numpy
格式化输出带来的问题。)
到此遇到的两个问题都是因为numpy
的格式化输出引起的,所以我就尝试令numpy
不要格式化输出,但在搜索了很多资料后我放弃了这个想法。(可能是我粗心没找到解决方案。)
后来换了一种思路来解决这个问题,我尝试先将这个读取出来的字符串解析成python
的list
,然后再用这个list
来初始化一个numpy
张量,从而供其他地方使用,于是进行了如下尝试。
1 |
|
但执行会报如下错误。
1 |
|
查询了很多资料,都没有说明这个问题是什么引起的。但在查询资料的过程中发现,别人在调用这个函数的时候,字符串都是以逗号隔开的一系列数字。这里由于numpy
的格式化输出,是用空格隔开的,中间还有很多换行符。(again!)
于是我尝试令numpy
输出的数据以逗号隔开,找了很多numpy
中的写文件函数,均由于各种限制无法实现我的需求。所以在存文件的时候尝试将numpy
数组先转换为字符串后,在写入文件。因为numpy
的array2string
函数是支持指定元素分隔符的,故我们改进generateData3D
函数。
1 |
|
重新生成文件后,再次尝试将该字符串解析为list
,这次成功解析了!
1 |
|
我们再进一步尝试将该list
转为numpy
张量。
1 |
|
打印该数组。
1 |
|
发现已经变成了numpy
张量的格式化输出,再查看其类型和形状进一步确认有没有问题。
1 |
|
类型与生成的数据中记录下来的一致,问题应该是解决了。
进一步优化
写到这里,回头看看可以发现,记录下来的形状信息其实并没有用到。因为在将字符串解析为list
的时候,形状的信息自然的保留了下来。所以我们将存储形状信息的代码去掉,让这个csv
文件只存储张量本身。
1 |
|
1 |
|
在读取数据的时候做一些相应处理即可。
1 |
|
这样读取出来的数据就是一个list
,其中的每个元素都是一个numpy.ndarray
。最后再写一个生成算子真值的函数。
1 |
|
其中加了一些tqdm
的内容,输出信息丰富一些。
完整代码
1 |
|
csv文件对于不同形状张量的存储与解析