バックエンドとしてTensorflowでKerasを使用しています。
メインプロセスでモデルを保存してから、別のプロセス内でロード/実行(つまり、_model.predict
_を呼び出し)しようとしています。
私は現在、ドキュメントからの素朴なアプローチを試みてモデルを保存/ロードしています: https://keras.io/getting-started/faq/#how-can-i-save-a-keras-モデル 。
だから基本的に:
model.save()
メインプロセス内model = load_model()
子プロセス内model.predict()
子プロセス内ただし、それは単に_load_model
_呼び出しでハングします。
周りを検索すると、この潜在的に関連する答えを発見しました.Kerasは1つのプロセスでしか使用できないことを示唆しています: theanoでマルチプロセッシングを使用する しかし、これが本当かどうかはわかりません。
私の目標を達成する方法はありますか?高レベルの説明または短い例は大歓迎です。
注:プロセスにグラフを渡すという線に沿ってアプローチを試みましたが、テンソルフローグラフは選択できないようであるため、失敗しました(関連するSO post for here: Tensorflow :セッションをpython multiprocess )に渡す確かに、テンソルフローグラフ/モデルを子プロセスに渡す方法があれば、私もそれを受け入れます。
ありがとう!
私の経験から、問題はKeras
を1つのプロセスにロードし、keras
がメイン環境にロードされたときに新しいプロセスを生成することにあります。ただし、一部のアプリケーション(たとえば、Keras
modelの混合物のトレーニングなど)の場合、このすべてを1つのプロセスに入れる方が簡単です。だから私がお勧めするのは、次のアプローチです(少し面倒ですが、私のために働いています):
メイン環境にケラスをロードしないでください。 Keras/Theano/TensorFlowをロードする場合は、関数環境でのみ実行してください。例えば。 しないこれを行う:
import keras
def training_function(...):
...
ただし、次のことを行います。
def training_function(...):
import keras
...
各モデルに関連付けられた作業を個別のプロセスで実行する私は通常、ジョブを作成するワーカー(たとえば、トレーニング、チューニング、スコアリングなど)を作成し、個別のプロセスで実行しています。このプロセスで使用されるメモリ全体が完全にfreedであることが、プロセスの完了時に素晴らしいことです。これは、マルチプロセッシングを使用している場合や、1つのプロセスで複数のモデルを実行している場合に通常遭遇するメモリの負荷の問題に役立ちます。これは、たとえばこのような:
def _training_worker(train_params):
import keras
model = obtain_model(train_params)
model.fit(train_params)
send_message_to_main_process(...)
def train_new_model(train_params):
training_process = multiprocessing.Process(target=_training_worker, args = train_params)
training_process.start()
get_message_from_training_process(...)
training_process.join()
異なるアプローチは、異なるモデルアクションに対して異なるスクリプトを準備するだけです。ただし、特にモデルがメモリを消費する場合、これによりメモリエラーが発生する可能性があります。 [〜#〜] note [〜#〜]この理由により、厳密にシーケンシャルに実行することをお勧めします。
複数のGPUを持つ複数のプロセスでKerasモデルを実行する方法を示す簡単な例を作成しました。このサンプルがお役に立てば幸いです。 https://github.com/yuanyuanli85/Keras-Multiple-Process-Prediction
コードを修正するデコレータを作成しました。
from multiprocessing import Pipe, Process
def child_process(func):
"""Makes the function run as a separate process."""
def wrapper(*args, **kwargs):
def worker(conn, func, args, kwargs):
conn.send(func(*args, **kwargs))
conn.close()
parent_conn, child_conn = Pipe()
p = Process(target=worker, args=(child_conn, func, args, kwargs))
p.start()
ret = parent_conn.recv()
p.join()
return ret
return wrapper
@child_process
def keras_stuff():
""" Keras stuff here"""