静かなる名辞

pythonとプログラミングのこと

2019/03/22:TechAcademyがteratailの質問・回答を盗用していた件
2019/03/26:TechAcademy盗用事件 公式発表と深まる疑念


numpy配列の直列化方法によるファイル容量の違いを比較

はじめに

 numpy配列を直列化する方法はいろいろあります。numpyから使える方法に限っても4つあります*1

numpy.savetxt — NumPy v1.15 Manual
numpy.save — NumPy v1.15 Manual
numpy.savez — NumPy v1.15 Manual
numpy.savez_compressed — NumPy v1.15 Manual

 出力されるファイルの容量はどれが少ないのでしょうか? なんとなく予想できる気もしますが、検討してみました。

それぞれの簡単な説明

  • numpy.savetxt

 テキスト形式で保存する。1次元ないし2次元配列しか出力できない

  • numpy.save

 いわゆる普通の直列化。.npyという拡張子を使うらしい

  • numpy.savez

 複数の配列を同時に直列化できる。.npzという拡張子を使う。読み込むときは辞書

  • numpy.savez_compressed

 savezを圧縮して出力するだけ

 numpy.savetxtで出力したものはnumpy.loadtxtで読み込む必要があります。それ以外はnumpy.loadで行けるようです。

容量比較

 次のようなコードを書きました。

import numpy as np

A = np.arange(10**6).astype(np.float64).reshape(10**3, 10**3)

np.savetxt("savetxt.txt", A)
np.save("save.npy", A)
np.savez("savez.npz", A)
np.savez_compressed("savez_compressed.npz", A)

 出力されたファイルの容量は、

関数 容量[MB]
savetxt.txt 25.0
save.npy 8.0
savez.npz 8.0
savez_compressed.npz 1.3

 のように、numpy.savez_compressedを使うのが最良でした。

 まあ、やる前からわかっていましたが。

考察とまとめ

 特にこだわりがなければnumpy.savez_compressedが良さげです。圧縮に時間はかかるはずですが、20倍弱違うとストレージI/Oの時間が短縮できるので相殺できる気がします(未検証)。

 難点は.npz形式への親しみのなさでしょうか。save_compressedがあれば良かった気もしますが(特に単一の配列をシリアライズしたい場合など)、同じようなものを複数作る必要はないという思想なのでしょう。しょせんloadするとただの辞書が返るだけなので、そんなに難しく考える必要もなく、numpy.savez_compressed使えば良いですね。

*1:というか、もう少しいろいろある気もする。詳細は Input and output — NumPy v1.15 Manual を参照