web-dev-qa-db-ja.com

速度、メモリ、ルックアップに関して、Pythonで `.npy`ではなく` .npz`ファイルを保存する利点は何ですか?

numpy.savezファイルを保存する.npzのpythonドキュメントは次のとおりです。

.npzファイル形式は、ファイルに含まれる変数にちなんで名付けられたファイルの圧縮アーカイブです。アーカイブは圧縮されておらず、アーカイブ内の各ファイルには.npy形式の変数が1つ含まれています。 [...]

保存された.npzファイルをロードで開くと、NpzFileオブジェクトが返されます。これは辞書のようなオブジェクトであり、配列のリスト(.files属性を使用)および配列自体を照会できます。

私の質問は、numpy.savezのポイントは何ですか?

複数の配列を保存するのは、よりエレガントなバージョン(短いコマンド)ですか、それとも保存/読み取りプロセスが高速化されていますか?メモリ使用量は少なくなりますか?

9
SuperCiocia

あなたの質問に答えるための説明の2つの部分があります。

I. NPYとNPZ

既にドキュメントから読んだように、.npyの形式は次のとおりです。

singleディスク上の任意のNumPyアレイを永続化するためのNumPyの標準バイナリファイル形式。 ...このフォーマットは、その限られた目標を達成しながら、できるだけシンプルになるように設計されています。 ( ソース

そして.npz

multiple配列を1つのファイルに結合する簡単な方法。ZipFileを使用して複数の「.npy」ファイル。これらのアーカイブには、ファイル拡張子「.npz」を使用することをお勧めします。 ( ソース

したがって、.npzは、複数の「.npy」ファイルを含むZipFileにすぎません。そして、このZipFileは圧縮(np.savez_compressedを使用して)または非圧縮(np.savez)を使用してできます。

Unixライクなシステムの tarballアーカイブファイル に似ています。tarballファイルは、他のファイルを含む非圧縮アーカイブファイル、またはさまざまな圧縮プログラム(gzipbzip2など)

II。バイナリシリアル化用のさまざまなAPI

また、Numpyは 別のAPI も提供して、これらのバイナリファイル出力を生成します。

  • np.save --->配列をバイナリファイルにNumPy .npy形式で保存します
  • np.savez->複数の配列をuncompressed.npz形式で1つのファイルに保存します
  • np.savez_compressed->複数の配列をcompressed.npz形式で1つのファイルに保存します
  • np.load-> .npy.npzまたはピクル化ファイルから配列またはピクル化オブジェクトをロードします

Numpyのソースコード 内部 を流用すると、次のようになります。

def _savez(file, args, kwds, compress, allow_pickle=True, pickle_kwargs=None):
    ...
    if compress:
        compression = zipfile.Zip_DEFLATED
    else:
        compression = zipfile.Zip_STORED
    ...


def savez(file, *args, **kwds):
    _savez(file, args, kwds, False)


def savez_compressed(file, *args, **kwds):
    _savez(file, args, kwds, True)

次に、質問に戻ります。

np.saveのみを使用する場合、.npyフォーマットに加えて圧縮は行われず、関連する複数のファイルを管理するために1つのアーカイブファイルのみが使用されます。

np.savez_compressedを使用する場合、圧縮ジョブを実行するためのCPU時間が増えるため(つまり、少し遅いため)、当然、ディスク上のメモリは少なくなります。

8
YaOzI

主な利点は、配列が遅延ロードされることです。つまり、100個の配列を持つnpzファイルがある場合、実際にデータをロードせずにファイルをロードできます。単一の配列を要求すると、その配列のデータのみがロードされます。

npzファイルの欠点は、(load(<file>, mmap_mode='r')を使用して)メモリをマップできないため、大きな配列の場合は最適な選択ではない可能性があります。配列に共通の形状があるデータについては、 構造化配列 を確認することをお勧めします。これらはメモリマップすることができ、dictのような構文でデータにアクセスできます(つまり、arr['field'])、そして非常に効率的なメモリの賢いです。

2
user2699