2017-10-13 2 views
2

나는 tensorflow 1.3.0 백엔드가있는 keras 2.0.8을 사용하고 있습니다.Keras Tensorflow - 여러 스레드에서 예측하는 동안 예외가 발생했습니다

모델을 init 클래스에로드하고이를 사용하여 다중 스레드를 예측합니다.

import tensorflow as tf 
from keras import backend as K 
from keras.models import load_model 


class CNN: 
    def __init__(self, model_path): 
     self.cnn_model = load_model(model_path) 
     self.session = K.get_session() 
     self.graph = tf.get_default_graph() 

    def query_cnn(self, data): 
     X = self.preproccesing(data) 
     with self.session.as_default(): 
      with self.graph.as_default(): 
       return self.cnn_model.predict(X) 

나는 한 번 CNN을 초기화하고 query_cnn 방법은 여러 스레드에서 발생합니다.

난 내 로그에 수는 예외입니다 :

File "/home/*/Similarity/CNN.py", line 43, in query_cnn 
    return self.cnn_model.predict(X) 
    File "/usr/local/lib/python3.5/dist-packages/keras/models.py", line 913, in predict 
    return self.model.predict(x, batch_size=batch_size, verbose=verbose) 
    File "/usr/local/lib/python3.5/dist-packages/keras/engine/training.py", line 1713, in predict 
    verbose=verbose, steps=steps) 
    File "/usr/local/lib/python3.5/dist-packages/keras/engine/training.py", line 1269, in _predict_loop 
    batch_outs = f(ins_batch) 
    File "/usr/local/lib/python3.5/dist-packages/keras/backend/tensorflow_backend.py", line 2273, in __call__ 
    **self.session_kwargs) 
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py", line 895, in run 
    run_metadata_ptr) 
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py", line 1124, in _run 
    feed_dict_tensor, options, run_metadata) 
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py", line 1321, in _do_run 
    options, run_metadata) 
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py", line 1340, in _do_call 
    raise type(e)(node_def, op, message) 
tensorflow.python.framework.errors_impl.NotFoundError: PruneForTargets: Some target nodes not found: group_deps 

코드는 대부분의 시간을 잘 작동, 멀티 스레딩과의 아마 문제는.

어떻게 해결할 수 있습니까?

답변

5

다른 스레드를 만들기 전에 그래프 작성을 완료했는지 확인하십시오.

그래프에 finalize()을 부르는 것이 도움이 될 수 있습니다.

def __init__(self, model_path): 
     self.cnn_model = load_model(model_path) 
     self.session = K.get_session() 
     self.graph = tf.get_default_graph() 
     self.graph.finalize() 

업데이트 1 :finalize()이 그래프는 읽기 전용 안전하게 여러 스레드에서 사용할 수 있도록 할 것입니다. 부작용으로 의도하지 않은 동작과 때때로 메모리 누수를 찾는 데 도움이됩니다. 그래프를 수정하려고 할 때 예외가 발생하기 때문입니다.

예를 들어, 입력 중 하나를 핫 인코딩하는 스레드가 있다고 상상해보십시오. (나쁜 예 :

def preprocessing(self, data): 
    one_hot_data = tf.one_hot(data, depth=self.num_classes) 
    return self.session.run(one_hot_data) 

당신이 그래프에서 개체의 크기를 인쇄 할 경우 시간이 지남

# amount of nodes in tf graph 
print(len(list(tf.get_default_graph().as_graph_def().node))) 

증가 할 것으로 알 수 그러나 먼저 그래프를 정의하면 그되지 않습니다 경우 (약간 더 나은 코드) :

def preprocessing(self, data): 
    # run pre-created operation with self.input as placeholder 
    return self.session.run(self.one_hot_data, feed_dict={self.input: data}) 

업데이트 2 : 당신이 model._make_predict_function()를 호출 할 필요가이 thread에 따르면, 멀티 스레딩을하기 전에 keras 모델에서.

Keras builds the GPU function the first time you call predict(). That way, if you never call predict, you save some time and resources. However, the first time you call predict is slightly slower than every other time.

업데이트 된 코드 :

def __init__(self, model_path): 
    self.cnn_model = load_model(model_path) 
    self.cnn_model._make_predict_function() # have to initialize before threading 
    self.session = K.get_session() 
    self.graph = tf.get_default_graph() 
    self.graph.finalize() # make graph read-only 

업데이트 3 : 나는 _make_predict_function()는 않기 때문에하지 예상대로 작동하는 것 같다, 온난화 최대의 개념 증명했다.다른 스크립트에서 내가 그 모델을로드가 warmingup의 라인을 언급하면서 여러 스레드

import tensorflow as tf 
from keras import backend as K 
from keras.models import load_model 
import threading as t 
import numpy as np 

K.clear_session() 

class CNN: 
    def __init__(self, model_path): 

     self.cnn_model = load_model(model_path) 
     self.cnn_model.predict(np.array([[0,0]])) # warmup 
     self.session = K.get_session() 
     self.graph = tf.get_default_graph() 
     self.graph.finalize() # finalize 

    def preproccesing(self, data): 
     # dummy 
     return data 

    def query_cnn(self, data): 
     X = self.preproccesing(data) 
     with self.session.as_default(): 
      with self.graph.as_default(): 
       prediction = self.cnn_model.predict(X) 
     print(prediction) 
     return prediction 


cnn = CNN("dummymodel") 

th = t.Thread(target=cnn.query_cnn, kwargs={"data": np.random.random((500, 2))}) 
th2 = t.Thread(target=cnn.query_cnn, kwargs={"data": np.random.random((500, 2))}) 
th3 = t.Thread(target=cnn.query_cnn, kwargs={"data": np.random.random((500, 2))}) 
th4 = t.Thread(target=cnn.query_cnn, kwargs={"data": np.random.random((500, 2))}) 
th5 = t.Thread(target=cnn.query_cnn, kwargs={"data": np.random.random((500, 2))}) 
th.start() 
th2.start() 
th3.start() 
th4.start() 
th5.start() 

th2.join() 
th.join() 
th3.join() 
th5.join() 
th4.join() 

에서 실행하고 나는 재현 할 수 있었다 마무리했다 그런 다음

import tensorflow as tf 
from keras.layers import * 
from keras.models import * 

model = Sequential() 
model.add(Dense(256, input_shape=(2,))) 
model.add(Dense(1, activation='softmax')) 

model.compile(loss='mean_squared_error', optimizer='adam') 

model.save("dummymodel") 

: 먼저 나는 더미 모델을 생성 첫 번째 문제

+0

그래프 변수를 저장 한 후 마무리해야합니까? –

+0

문제는 그래프 생성이 스레드로부터 안전하지 않다는 것입니다 (https://www.tensorflow.org/versions/r0.12/api_docs/python/framework/core_graph_data_structures). 그래서 그래프 생성을 다음과 같이 완료해야합니다. 하나의 스레드로 시작한 다음 다른 스레드를 시작하십시오. 'finalize()'는 그래프를 읽기 전용으로 만듭니다. –

+0

당신에게 효과가 있습니까? –

관련 문제