为啥 numpy.savez() 输出不可重现的文件?

Posted

技术标签:

【中文标题】为啥 numpy.savez() 输出不可重现的文件?【英文标题】:Why does numpy.savez() output non reproducible files?为什么 numpy.savez() 输出不可重现的文件? 【发布时间】:2018-03-13 14:18:04 【问题描述】:

numpy.savez() 函数允许将 numpy 对象存储在文件中。将相同的对象存储在两个文件中会导致两个不同的文件:

import numpy as np
some_array = np.arange(42)
np.savez('/tmp/file1', some_array=some_array)
np.savez('/tmp/file2', some_array=some_array)

这两个文件不同:

$ diff /tmp/file1.npz /tmp/file2.npz 
Binary files /tmp/file1.npz and /tmp/file2.npz differ

为什么文件不一样?是否包含一些随机行为、文件名或时间戳?这可以解决或修复吗? (这是一个错误吗?)

请注意,np.save() 并非如此。 np.save() 生成的文件对于相同的输入是相同的。所以我猜这与压缩数据有关。

AFAICS 只有两点不同:

$ xxd /tmp/file1.npz > /tmp/file1.hex
$ xxd /tmp/file2.npz > /tmp/file2.hex
$ diff -u0 /tmp/file1.hex /tmp/file2.hex    
--- /tmp/file1.hex      2018-03-13 13:39:12.235897095 +0100
+++ /tmp/file2.hex      2018-03-13 13:39:08.743927081 +0100
@@ -1 +1 @@
-0000000: 504b 0304 1400 0000 0000 ce6c 6d4c 9c9d  PK.........lmL..
+0000000: 504b 0304 1400 0000 0000 cf6c 6d4c 9c9d  PK.........lmL..
@@ -30 +30 @@
-00001d0: 1403 1400 0000 0000 ce6c 6d4c 9c9d 6ad9  .........lmL..j.
+00001d0: 1403 1400 0000 0000 cf6c 6d4c 9c9d 6ad9  .........lmL..j.

我在implementation of the function 中找不到任何好的提示,但我还没有检查邮政编码(Python 3.6 也可能有所作为)。

注意:使用 Python 2.7 和 numpy 1.9.2 测试。

【问题讨论】:

【参考方案1】:

有一个关于这个here的github问题:

savez() 不是确定性的 #9439

这似乎归结为 Zip 文件将时间戳附加到文件(如您所料)与临时文件的使用相结合。

也讨论了解决方法,但似乎这个问题仍然开放(尽管 Python>=3.6.0 现在可能是unaffected(您似乎再次观察到))。

【讨论】:

deterministic 是我正在寻找的正确关键字,而不是 reproducible...谢谢! :) 我仍然不明白时间戳如何只能改变两位,但可能不太重要。 (关于位更改)这肯定不是我的专业领域。但它似乎很大程度上基于秒为单位(而且精度似乎有限:2 秒),对于您可能已经完成的某些实验,两位变化似乎是合理的。这可能很容易通过阅读 zip 的设计来分析。可能以wiki开头,表示一个2字节的时间戳。 你是绝对正确的。 “2 秒”的单位似乎令人惊讶,但一个简单的实验证实了您的理论:当在两者之间放置一个 sleep(20) 时,我得到 0xf9 - 0xef = 10 的差异。

以上是关于为啥 numpy.savez() 输出不可重现的文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 numpy.savez 将带有子数组的数组保存到单独的 .npy 文件中

如何将字典和数组保存在同一个存档中(使用 numpy.savez)

(原+译)使用numpy.savez保存字典后读取的问题

Numpy之数据保存与读取

在磁盘上保留 numpy 数组的最佳方法

TinyMCE 在动态生成的文本区域上不可点击和编辑