2017-03-29 20 views
0

私はhdfファイルのコレクションをnumpyの配列に設定する方法を探していますが、各行はイメージのフラット化されたバージョンです。私が正確に意味するもの:hdfからnumpyのndarray - 速い方法

私のHDFファイルには、他の情報の他に、フレームごとの画像が格納されています。各ファイルには、512x424の画像で51フレームが保持されます。今私は300以上のhdfファイルを持っていて、画像ピクセルを1フレームあたり1つの単一ベクトルとして保存したいと思います。すべての画像のすべてのフレームが1つのnumpy ndarrayに格納されます。私がこれまでに得たもの

Visualized process of transforming many hdf files to one numpy array

が非常に遅い方法であり、私は実際に私はより速くそれを作ることができるか見当がつかない:以下の写真は理解するのに役立つはずです。問題は、私の考えでは、最終的な配列があまりにも頻繁に呼び出されることです。最初のファイルは非常に高速に読み込まれますが、速度は急速に低下することがわかります。

私の現在のコード(現在のHDFファイルの数を印刷することにより観察):詳細については

os.chdir(os.getcwd()+"\\datasets") 

# predefine first row to use vstack later 
numpy_data = np.ndarray((1,217088)) 

# search for all .hdf files 
for idx, file in enumerate(glob.glob("*.hdf5")): 
    f = h5py.File(file, 'r') 
    # load all img data to imgs (=ndarray, but not flattened) 
    imgs = f['img']['data'][:] 

    # iterate over all frames (50) 
    for frame in range(0, imgs.shape[0]): 
    print("processing {}/{} (file/frame)".format(idx+1,frame+1)) 
    data = np.array(imgs[frame].flatten()) 
    numpy_data = np.vstack((numpy_data, data)) 

    # delete first row after another is one is stored 
    if idx == 0 and frame == 0: 
     numpy_data = np.delete(numpy_data, 0,0) 

f.close() 

、私は決定木を学習するためにこれを必要とします。私のhdfファイルは私のRAMよりも大きいので、メモリが節約された配列に変換されるので、より適切です。

すべての入力いただきありがとうございます。

+0

アルゴリズムで一度に複数のフレームが必要ですか?私は速度低下がvstackへのすべての呼び出しから来ていると推測しており、あなたはそのようなことをする必要はないかもしれません。 – Elliot

+0

また、 'if idx == 0とframe == 0:'の条件で何が起こっているのかよく分かりません。私はあなたがそれから0x217088要素配列を取得していると思います。 – Elliot

+0

残念ながら、すべての機能スペースを使用するランダムなforrestsを使用します。たぶんscikitでそれらを養う方法の別のオプションがありますが、私はそのようなことを認識していません。 – muleque

答えて

1

あなたは本当にRAMにすべての画像をロードするためにwan't、代わりに単一HDF5・ファイルを使用しないでください? HDF5ファイルへのアクセスは、間違いがなければ非常に高速になります(不自然な気まぐれな索引付け、不適切なチャンクサイズ)。あなたがnumpyの通行をwan't場合 これは可能性のようになります。シングルHDF5 - ファイルにデータを書き込む

os.chdir(os.getcwd()+"\\datasets") 
img_per_file=51 

# get all HDF5-Files 
files=[] 
for idx, file in enumerate(glob.glob("*.hdf5")): 
    files.append(file) 

# allocate memory for your final Array (change the datatype if your images have some other type) 
numpy_data=np.empty((len(files)*img_per_file,217088),dtype=np.uint8) 

# Now read all the data 
ii=0 
for i in range(0,len(files)): 
    f = h5py.File(files[0], 'r') 
    imgs = f['img']['data'][:] 
    f.close() 
    numpy_data[ii:ii+img_per_file,:]=imgs.reshape((img_per_file,217088)) 
    ii=ii+img_per_file 

は非常に似ています:

f_out=h5py.File(File_Name_HDF5_out,'w') 
# create the dataset (change the datatype if your images have some other type) 
dset_out = f_out.create_dataset(Dataset_Name_out, ((len(files)*img_per_file,217088), chunks=(1,217088),dtype='uint8') 

# Now read all the data 
ii=0 
for i in range(0,len(files)): 
    f = h5py.File(files[0], 'r') 
    imgs = f['img']['data'][:] 
    f.close() 
    dset_out[ii:ii+img_per_file,:]=imgs.reshape((img_per_file,217088)) 
    ii=ii+img_per_file 

f_out.close() 

だけwan't場合後で全体画像にアクセスするには、チャンクサイズは大丈夫です。そうでなければ、それをあなたのニーズに合わせて変更する必要があります。 HDF5-ファイルにアクセスするとき、あなたが何をすべき

  • ニーズに合ったチャンクサイズを、使用してください。

  • 適切なチャンクサイズを設定します。これは、h5pyの低レベルapiまたはh5py_cacheで行うことができます。 https://pypi.python.org/pypi/h5py-cache/1.0

  • 任意の種類のファンシーインデックスを避けてください。データセットにn次元がある場合、返された配列にはn次元も含まれています。

    # Chunk size is [50,50] and we iterate over the first dimension 
    numpyArray=h5_dset[i,:] #slow 
    numpyArray=np.squeeze(h5_dset[i:i+1,:]) #does the same but is much faster 
    

EDIT これはmemmaped numpyの配列にデータを読み取る方法を示しています。私は、あなたのメソッドがフォーマットnp.float32のデータを期待していると思います。 https://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html#numpy.memmap

numpy_data = np.memmap('Your_Data.npy', dtype='np.float32', mode='w+', shape=((len(files)*img_per_file,217088))) 

それ以外は同じに維持することができます。それが動作するなら、私はまた、ハードディスクの代わりにSSDを使用することをお勧めします。

+0

私は、このデータでランダムなforrests/Decisionツリーを使用するつもりです。これらのメソッドは、一度にすべてのデータを必要とすることがわかりました。それで、私はチャンクされたバージョンでは行けないと思うのです。または、hdfファイルをどのようにチャンクするのが嫌なのか理解していますか? – muleque

+0

私の最初の提案(numpy配列のデータのみを読む)はあなたのために働いていますか? – max9111

+0

私が求めた目的のためにうまく機能します。しかし、学習アルゴリズム(デシジョンツリー)にデータをどのように供給するのか分かりません。これは私のデータセットを26GBから3GBに減らしました。これは実際のデータセットのサブセットだったので、私はコアメモリから出ることなくこれをどう扱うか分かりませんでした。 – muleque

1

私はあなたが

imgs = f['img']['data'][:] 

上を反復処理し、各2次元配列を再構築する必要はないと思います。全体を変えるだけです。私はあなたの説明の権利を理解していれば、 imgs 3次元配列である:(51、512、424)

imgs.reshape(51, 512*424) 

は、2D同等であるべきです。

ループする必要がある場合は、vstack(またはより大きな配列を作成するためにいくつかの変形)を使用しないでください。 1つは遅く、2つ目は最初の「ダミー」エントリをクリーンアップすることです。それは一度に多くで動作することができますので、最後

alist = [] 
for frame.... 
    alist.append(data) 
data_array = np.vstack(alist) 

vstack(および家族)で、リスト追加を使用して、一度スタッキングを行うには、入力として配列のリストを取ります。リストの追加は、繰り返し実行するとはるかに高速です。

私は物事を1つの配列に入れることが役立つかどうか質問します。私はhdf5ファイルのサイズがダウンロードされた配列のサイズにどのように関係しているのか正確にはわかりませんが、それらのサイズは同じ桁であると思います。 300個のファイルすべてをメモリにロードしようとすると動作しない可能性があります。それはピクセルの3Gの何ですか?

個々のファイルの場合、h5pyには、メモリに収まらない大きすぎる配列のチャンクをロードする手段があります。これは、問題が頻繁に逆になることを示しています。ファイルには、適合以上のものがあります。

Is it possible to load large data directly into numpy int8 array using h5py?

関連する問題