5

現在、かなり大きな2D numpy配列を作成し、numpy.savetxtを使用してタブ区切りのテキストファイルとして保存するPythonプログラムがあります。numpy配列にはfloatのみが含まれています。次に、別のC++プログラムで一度に1行ずつファイルを読み取ります。

私がやりたいのは、2つのプログラム間で渡すファイルのサイズを小さくできるように、コードをできるだけ変更せずに、これと同じタスクを実行する方法を見つけることです。

numpy.savetxtを使用して、テキストファイルの代わりに圧縮された.gzファイルに保存できることがわかりました。これにより、ファイルサイズが約2MBから約100kBに減少します。

これを行うためのより良い方法はありますか?おそらく、スペースを節約するために、numpy配列をバイナリでファイルに書き込むことができますか?もしそうなら、C ++プログラムに読み込めるようにするにはどうすればよいですか?

お手伝いありがとう。私が得ることができるどんな指導にも感謝します。

編集:

ゼロがたくさんあります(おそらくnumpy配列の値の70%は0.0000です)しかし、どういうわけかこれを悪用して、C++プログラムが読み取ることができる小さなファイルを生成する方法がわかりません

4

5 に答える 5

3

エンディアンなどについて心配する必要がないことが確実でない限りnumpy.savez、@ unutbuの回答と@jorgecaのコメントで説明されているように、最適に使用してください:numpyのtostring /fromstring---配列を復元するために何を指定する必要がありますか

結果のサイズが十分に小さくない場合は、常に存在しますzlib(Python側では:import zlib、C ++側では、実装が存在すると確信しています)。

別の方法として、フォーマットを使用することもできhdf5ます。これにより、ディスク上のファイルサイズが必ずしも縮小されるわけではありませんが、保存/読み込みが高速になります(これは、フォーマットが設計された大規模なデータ配列です)。には、PythonとC++の両方のリーダー/ライターがありhdf5ます。

于 2013-03-12T19:44:19.957 に答える
3

ゼロがたくさんあるので、ゼロ以外の要素をフォーム(インデックス、数値)に書き出すことしかできませんでした。

ゼロ以外の数値が少量ある配列があるとします。

In [5]: a = np.zeros((10, 10))

In [6]: a
Out[6]: 
array([[ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]])

In [7]: a[3,1] = 2.0

In [8]: a[7,4] = 17.0

In [9]: a[9,0] = 1.5

まず、興味深い数とそのインデックスを分離します。

In [11]: x, y = a.nonzero()

In [12]: zip(x,y)
Out[12]: [(3, 1), (7, 4), (9, 0)]

In [13]: nonzero = zip(x,y)

これで、残っているデータ要素の数は少なくなります。最も簡単なのは、それらをテキストファイルに書き込むことです。

In [17]: with open('numbers.txt', 'w+') as outf:
   ....:     for r, k in nonzero:
   ....:         outf.write('{:d} {:d} {:g}\n'.format(r, k, a[r,k]))
   ....:         

In [18]: cat numbers.txt
3 1 2
7 4 17
9 0 1.5

これにより、データを目で確認する機会も得られます。C ++プログラムでは、このデータをで読み取ることができますfscanf

ただし、 struct:を使用してバイナリデータを書き込むことにより、サイズをさらに減らすことができます。

In [17]: import struct

In [19]: c = struct.Struct('=IId')

In [20]: with open('numbers.bin', 'w+') as outf:
   ....:     for r, k in nonzero:
   ....:         outf.write(c.pack(r, k, a[r,k]))

Structコンストラクターへの引数は、次のことを意味します。ネイティブの日付形式'='を使用します。1番目と2番目のデータ要素は符号なし整数'I'、3番目の要素はdouble'd'です。

C ++プログラムでは、このデータはおそらくバイナリデータとしてパックに読み込まれるのが最適structです。

編集:2D配列の回答が更新されました。

于 2013-03-12T20:46:13.297 に答える
1

numpy.ndarray.tofilenumpy.fromfilePythonからの直接バイナリ出力/入力に役立ちます 。std::ostream::write std::istream::readC++でのバイナリ出力/入力に役立ちます。

データが1つのマシンから別のマシンに転送される場合は、エンディアンに注意する必要があります。

于 2013-03-12T19:18:34.590 に答える
1

hdf5ファイルを使用します。これらはh5pyを介して非常に簡単に使用でき、setcompressionフラグを使用できます。hdf5にはc++インターフェースもあることに注意してください。

于 2013-10-07T14:02:46.987 に答える
0

python追加のパッケージ(との両方)をインストールしてもかまわない場合は、 (Binary JSON)c++を使用できます。[BSON][1]

于 2013-03-12T19:16:27.060 に答える