2017-10-01 16 views
3

私はU-net 2D医療セグメンテーションプロジェクトにKeras 2.0.8を使用しています。 現在、私はカスタムスレッドセーフイメージジェネレータ(XとYを同時に)を作成するのに苦労しています。 XとYは4D行列であり、形状n_img x n_col x n_row x T、ここで、Tは4、yは1である(4つの数値ラベルは4次元で1つのホットエンコーディングに変換される)Python 3.6.xでmodel.fit_generator用ケラススレッドセーフジェネレータ

ここは私ですコード:

def gen_tr(X,y,batch_size): 
    n=np.floor((len(X)-1)/batch_size).astype(int) 
    s=list(X.shape) 
    s[0]=batch_size 
    while 1: 
     for i in range(n): 
      j=0 
      X_b=np.zeros(s,dtype=np.float32) 
      y_b=np.zeros(s,dtype=int) 
      while j<batch_size: 
       data=distort_imgs(X[i*batch_size+j,:,:,0, np.newaxis], 
           X[i*batch_size+j,:,:,1, np.newaxis], 
           X[i*batch_size+j,:,:,2, np.newaxis], 
           X[i*batch_size+j,:,:,3, np.newaxis], 
           y[i*batch_size+j,:,:,0, np.newaxis]) 
       X_i=np.concatenate(data[:4],axis=2) 
       y_i=data[-1] 
       y_i=np.concatenate((y_i==0,y_i==1,y_i==2,y_i==4), 
           axis=2).astype(int) 
       X_b[j]=X_i 
       y_b[j]=y_i 
       j+=1 
      yield (X_b,y_b) 
batch_size=20 
gen = gen_tr(X_train,Y_train,batch_size) 
steps=np.floor((len(X_train)-1)/batch_size).astype(int) 
model.fit_generator(gen,steps_per_epoch=steps, epochs=5, verbose=1, shuffle=True, 
max_queue_size=10,workers=2, use_multiprocessing=False) 

とエラー: keunwoochoi.wordpress.comstanford(同):

Exception in thread Thread-13: 
Traceback (most recent call last): 
    File "D:\Users\SZ_KOCOT\Anaconda3\envs\cnn1\lib\threading.py", line 916, in _bootstrap_inner 
    self.run() 
    File "D:\Users\SZ_KOCOT\Anaconda3\envs\cnn1\lib\threading.py", line 864, in run 
    self._target(*self._args, **self._kwargs) 
    File "D:\Users\SZ_KOCOT\Anaconda3\envs\cnn1\lib\site-packages\keras\utils\data_utils.py", line 568, in data_generator_task 
    generator_output = next(self._generator) 
ValueError: generator already executing 

Traceback (most recent call last): 

    File "<ipython-input-17-1a91cea3a91e>", line 7, in <module> 
    max_queue_size=10,workers=2, use_multiprocessing=False) 

    File "D:\Users\SZ_KOCOT\Anaconda3\envs\cnn1\lib\site-packages\keras\legacy\interfaces.py", line 87, in wrapper 
    return func(*args, **kwargs) 

    File "D:\Users\SZ_KOCOT\Anaconda3\envs\cnn1\lib\site-packages\keras\engine\training.py", line 2011, in fit_generator 
    generator_output = next(output_generator) 

StopIteration 

私はからの解決策を試してみました。

いずれも機能しませんでした。私は追加する場合:次の(GEN)と世代を含め、fit_generator内部の労働者と

Epoch 1/5 
Exception in thread Thread-10: 
Traceback (most recent call last): 
    File "D:\Users\SZ_KOCOT\Anaconda3\envs\cnn1\lib\threading.py", line 916, in _bootstrap_inner 
    self.run() 
    File "D:\Users\SZ_KOCOT\Anaconda3\envs\cnn1\lib\threading.py", line 864, in run 
    self._target(*self._args, **self._kwargs) 
    File "D:\Users\SZ_KOCOT\Anaconda3\envs\cnn1\lib\site-packages\keras\utils\data_utils.py", line 568, in data_generator_task 
    generator_output = next(self._generator) 
    File "<ipython-input-12-24605a93d655>", line 17, in __next__ 
    return self.it.next() 
AttributeError: 'generator' object has no attribute 'next' 

Traceback (most recent call last): 

    File "<ipython-input-13-b07830ef87c0>", line 5, in <module> 
    max_queue_size=10,workers=2, use_multiprocessing=False) 

    File "D:\Users\SZ_KOCOT\Anaconda3\envs\cnn1\lib\site-packages\keras\legacy\interfaces.py", line 87, in wrapper 
    return func(*args, **kwargs) 

    File "D:\Users\SZ_KOCOT\Anaconda3\envs\cnn1\lib\site-packages\keras\engine\training.py", line 2011, in fit_generator 
    generator_output = next(output_generator) 

StopIteration 

= 1、すべてが(解決策からのコードなしで発電機を提供する)正常に動作します.__:

import threading 
class threadsafe_iter: 
def __init__(self, it): 
    self.it = it 
    self.lock = threading.Lock() 
def __iter__(self): 
    return self 
def __next__(self): 
    with self.lock: 
     return self.it.next() 

def threadsafe_generator(f): 
    def g(*a, **kw): 
     return threadsafe_iter(f(*a, **kw)) 
    return g 

@threadsafe_generator 
#now goes my generator from above 

私はエラーを得ましたnext__

1人のスレッドデータ生成のパフォーマンスは、私は複数のコアavaliableを持っている、特にこと、不足していると...

誰かがこれで私を助けることができ問題?私はPythonのスレッディングの初心者です。

編集: 私は解決策/回避策を見つけました。たぶんケラのために少しハッキーですが、それは動作します。 zsdonghaoに触発されました。 2750サンプルの10パーツでデータセット拡張を分割することで、データを非常に迅速に作成でき、ほぼ100%でgtx1080を利用できます。また、RAMの使用量は〜22GBを超えません。 1エポックのトレーニングには約14-15分、データプレップ/オーグには合計10-12分かかる。 私はそれが誰かを助けるかもしれない場合は3倍以上が

を減らす単一のワーカーとfit_generatorして比較すると、ここで正確なコードがある:Pythonの3では

import tensorlayer as tl 
import pandas as pd 

batch_size=20 
epochs=10 
batch_size=20 
step_size=2750 
steps=np.floor((len(X_train)-1)/step_size).astype(int) 
s=list(X_train.shape) 
train_all=pd.DataFrame() 
eval_all=pd.DataFrame() 

#training and evaluation 
for i in range(epochs): 
    start_time = time.clock() 
    print('Epoch: {0:02d}'.format(i+1)) 
    for j in range(steps): 
     ind=range(step_size*j,step_size*(j+1)) 
     data = tl.prepro.threading_data([_ for _ in zip(X_train[ind,:,:,0, np.newaxis], 
                 X_train[ind,:,:,1, np.newaxis], 
                 X_train[ind,:,:,2, np.newaxis], 
                 X_train[ind,:,:,3, np.newaxis], 
                 y_train[ind])],fn=distort_imgs,thread_count=None) 
     X_s = data[:,0:4,:,:,:]             
     y_s = data[:,4,:,:,:] 
     X_s = X_s.transpose((0,2,3,1,4)) 
     X_s.shape = (step_size, s[1], s[2], s[3]) 
     y_s=np.concatenate((y_s==0,y_s==1,y_s==2,y_s==4), 
              axis=3).astype(int) 
     train=model.fit(X_s, y_s,class_weight=weights, verbose=0, 
         batch_size=batch_size, epochs=i+2,initial_epoch=i+1) 
     train.history['epoch']=i+1 
     train.history['step']=j+1 
     train=pd.DataFrame(train.history) 
     train_all=pd.concat([train_all,train],ignore_index=True) 
     print(train.to_string(index=False)) 
    eval=model.evaluate(X_test, y_test, batch_size=batch_size, verbose=0) 
    eval=pd.DataFrame({'val_dice_coe':eval[0],'val_dice_hard_coe':eval[1], 'val_iou_coe':eval[2], 'val_loss':eval[3]},index=[0]) 
    eval['epoch']=i+1 
    eval_all=pd.concat([eval_all,eval],ignore_index=True) 
    print(eval.to_string(index=False)) 
    model.save('{0}_ep_{1}.h5'.format(model_name,i+1)) 
    print('Epoch {0:02d} took: {1:.3f} min'.format(i+1,(time.clock()-start_time)/60)) 

答えて

1

、あなたはnext(self.it)の代わりself.it.next()を使用する必要があります。

また、Keras Sequencesを試してみてください。マルチプロセッシング時にデータの正しい順序を保持するために索引付けされているので、安全です。

最後に、workersは、モデルではなく、ジェネレータ自体にのみ影響を与えるようです。私のテストでは(私はどちらのスレッドもうまくいきませんでした...)、より多くのワーカーが見ることのできる唯一の違いは、モデルへの移行を待っているプリロードされたデータの大きなキューでした。

+0

私がよく覚えていれば、私は次のテストもしましたが、うまくいかなかったのです。私は他の解決策を持ってきました。無作為に10000〜27k列車のサンプルを訓練しました。 テストするときに、後でコードを投稿します。 –