2012-04-09 25 views
11

ここに最初の質問。私は簡潔にしようとします。辞書と配列を同じアーカイブ(numpy.savez)に保存する方法

機械学習アプリケーションの機能情報を含む複数の配列を生成しています。配列は等しい次元を持たないので、配列ではなく辞書に格納します。 2つの異なる種類の機能があるので、2つの異なる辞書を使用しています。

また、機能を使用するラベルも生成します。これらのラベルは配列に格納されます。さらに、スクリプトの実行に使用される正確なパラメータとタイムスタンプを含む文字列があります。

import numpy as np  

feature1 = {} 
feature2 = {} 
label1 = np.array([]) 
label2 = np.array([]) 
docString = 'Commands passed to the script were...' 

# features look like this: 
feature1 = {'case 1': np.array([1, 2, 3, ...]), 
      'case 2': np.array([2, 1, 3, ...]), 
      'case 3': np.array([2, 3, 1, ...]), 
      and so on... } 

今私の目標は、これを行うには、次のようになります:それはこのようになりますすべてで

すべて

np.savez(outputFile, 
     saveFeature1 = feature1, 
     saveFeature2 = feature2, 
     saveLabel1 = label1, 
     saveLabel2 = label2, 
     saveString = docString) 

これは一見働く(すなわち、このようなファイルはエラーなしスローで保存され、再度読み込むことができます)。しかし、私は再び、たとえばファイルから機能をロードしようとすると:

loadedArchive = np.load(outFile) 
loadedFeature1 = loadedArchive['saveFeature1'] 
loadedString = loadedArchive['saveString'] 

そして、代わりに戻って辞書を得るための、私は形状のnumpyの配列を取得(0)私がアクセスする方法がわからないところ内容:

In []: loadedFeature1 
Out[]: 
     array({'case 1': array([1, 2, 3, ...]), 
       'case 2': array([2, 3, 1, ...]), 
       ..., }, dtype=object) 

はまた、文字列を配列になり、奇妙なデータ型を取得します:

In []: loadedString.dtype 
Out[]: dtype('|S20') 

だから、要するに、私はそれが正しく行われているか、これがないと仮定しています。しかし、私は別のプロセスでそれらを取得し、単に文字列の比較を心配することなくdictionary.keys()をループしたいので、私はすべての変数を1つの大きな辞書に入れることを好まないでしょう。

アイデアをいただければ幸いです。 ありがとう

答えて

15

@fraxelが既に示唆しているように、この場合はpickleを使用するほうがはるかに優れています。アイテムにdictを保存するだけです。

ただし、必ず、pickleをバイナリプロトコルで使用してください。デフォルトでは、フォーマットが効率が悪く、メモリ使用量が大きくなり、配列が大きい場合はファイルが膨大になります。

saved_data = dict(outputFile, 
        saveFeature1 = feature1, 
        saveFeature2 = feature2, 
        saveLabel1 = label1, 
        saveLabel2 = label2, 
        saveString = docString) 

with open('test.dat', 'wb') as outfile: 
    pickle.dump(saved_data, outfile, protocol=pickle.HIGHEST_PROTOCOL) 

これまで説明したことは、説明のために、より詳細に何が起こっているかを見てみましょう。

numpy.savezは、各項目が配列であると想定しています。実際には、渡したものすべてについてnp.asarrayが呼び出されます。

dictを配列に変換すると、オブジェクト配列が得られます。例えば。

import numpy as np 

test = {'a':np.arange(10), 'b':np.arange(20)} 
testarr = np.asarray(test) 

あなたは文字列から配列を作る場合は同様に、あなたは文字列配列を取得します:あなたしまうと、オブジェクト配列の処理方法では気まぐれで、しかし

In [1]: np.asarray('abc') 
Out[1]: 
array('abc', 
     dtype='|S3') 

をタプル、リスト、または配列ではない1つのオブジェクト(あなたの場合はdict)を渡すと、0次元のオブジェクト配列が得られます。

これは、直接インデックスに登録できないことを意味します。実際にtestarr[0]を実行すると、IndexErrorが発生します。データはまだそこにありますが、最初にディメンションを追加する必要がありますので、yourdictionary = testarr.reshape(-1)[0]を実行する必要があります。

このすべてが厄介なように見える場合は、それが原因です。オブジェクト配列は、基本的に常に間違った答えです。 (asarrayは間違いなく、この特定の問題を解決するであろう、arrayndmin=1に渡すが、潜在的に他のものを壊すべきである。)

savezはなく、任意のオブジェクトよりも、配列を格納することが意図されています。それが動作する方法のため、完全に任意のオブジェクトを格納できますが、そのように使用しないでください。しかし、これは明らかにずっとある

np.savez(outputFile, 
     saveFeature1 = [feature1], 
     saveFeature2 = [feature2], 
     saveLabel1 = [label1], 
     saveLabel2 = [label2], 
     saveString = docString) 

そして、あなたはそれから

loadedArchive = np.load(outFile) 
loadedFeature1 = loadedArchive['saveFeature1'][0] 
loadedString = str(loadedArchive['saveString']) 

で物事にアクセスしたい:

あなたがそれを使用したいなかった場合は、しかし、迅速な回避策を行うことであろう単にピクルスを使用するよりももっとclunky。配列を保存するだけの場合は、numpy.savezを使用してください。この場合、配列ではなく、ネストされたデータ構造を保存しています。

+0

素晴らしい!ありがとうございました! – surchs

+2

私は、 'testarr.flat [0]'によって '()'形の配列の要素にアクセスするほうが好きです。好奇心を抱く読者のために、 'testarr [()]'のように空のタプルを使うこともできますが、これは読みやすさを傷つけます。 –

0

すべての変数をオブジェクトに入れてからPickleを使用します。これは、状態情報を格納するためのより良い方法です。

+0

ありがとうございました。 これは、毎回同じ数の変数を使用する必要がありますか?何らかの理由で1つの辞書しか保存しない場合、このファイルをpickleでロードするすべてのスクリプトが、格納された変数の順序を崩してしまいます。 – surchs

+0

Pickleは2.xではこれで動作しません。 64ビットのサポートはありません。 – Will

10

構造化された方法でデータを保存する必要がある場合は、HDF5ファイル形式(http://www.hdfgroup.org/HDF5/)の使用を検討する必要があります。これは非常に柔軟で、使いやすく、効率的で、他のソフトウェアがすでにサポートしている可能性があります(HDFView、Mathematica、Matlab、Origin ..)。 h5pyという単純なPythonバインディングがあります。

構造体のようなファイルシステムにデータセットを格納し、辞書などの各データセットの属性を定義できます。たとえば、次のようにデータを読み込み

import numpy as np 
import h5py 

# some data 
table1 = np.array([(1,1), (2,2), (3,3)], dtype=[('x', float), ('y', float)]) 
table2 = np.ones(shape=(3,3)) 

# save to data to file 
h5file = h5py.File("test.h5", "w") 
h5file.create_dataset("Table1", data=table1) 
h5file.create_dataset("Table2", data=table2, compression=True) 
# add attributes 
h5file["Table2"].attrs["attribute1"] = "some info" 
h5file["Table2"].attrs["attribute2"] = 42 
h5file.close() 

も簡単です、あなたが望むなら、あなたも、大容量のファイルのうち、わずか数の要素を読み込むことができます。

h5file = h5py.File("test.h5", "r") 
# read from file (numpy-like behavior) 
print h5file["Table1"]["x"][:2] 
# read everything into memory (real numpy array) 
print np.array(h5file["Table2"]) 
# read attributes 
print h5file["Table2"].attrs["attribute1"] 

より多くの機能と可能性をドキュメントに記載されていていますそしてウェブサイト(Quick Start Guideが興味のあるかもしれない)で。

関連する問題