使用python多处理并行化keras中的模型预测

使用python多处理并行化keras中的模型预测,python,numpy,tensorflow,multiprocessing,eager-execution,Python,Numpy,Tensorflow,Multiprocessing,Eager Execution,我正在尝试使用python2中keras提供的model.predict命令并行执行模型预测。我将tensorflow 1.14.0用于python2。我有5个模型(.h5)文件,希望predict命令并行运行。这是在Python2.7中运行的。我使用多处理池在多个进程上映射模型文件名和预测函数,如下所示 import matplotlib as plt import numpy as np import cv2 from multiprocessing import Pool pool=Poo

我正在尝试使用python2中keras提供的model.predict命令并行执行模型预测。我将tensorflow 1.14.0用于python2。我有5个模型(.h5)文件,希望predict命令并行运行。这是在Python2.7中运行的。我使用多处理池在多个进程上映射模型文件名和预测函数,如下所示

import matplotlib as plt
import numpy as np
import cv2
from multiprocessing import Pool
pool=Pool()
def prediction(model_name):
    global input
    from tensorflow.keras.models import load_model
    model=load_model(model_name)
    ret_val=model.predict(input).tolist()[0]
    return ret_val

models=['model1.h5','model2.h5','model3.h5','model4.h5','model5.h5']
start_time=time.time()
res=pool.map(prediction,models)
print('Total time taken: {}'.format(time.time() - start_time))
print(res)
Traceback (most recent call last):
  File "stackoverflow.py", line 47, in <module>
    with multiprocessing.Pool() as p:
AttributeError: __exit__
import matplotlib as plt
import numpy as np
import cv2
import multiprocessing
import tensorflow as tf
from contextlib import closing
import time

models=['model1.h5','model2.h5','model3.h5','model4.h5','model5.h5']
loaded_models=[]
for model in models:
    loaded_models.append(tf.keras.models.load_model(model))

def prediction(input_tuple):
    inputs,loaded_models=input_tuple
    predops=[]
    for model in loaded_models:
        predops.append(model.predict(inputs).tolist()[0])
    actops=[]
    for predop in predops:
        actops.append(predop.index(max(predop)))
    max_freqq = max(set(actops), key = actops.count) 
    return max_freqq

#....some pre-processing....#

    '''new_all_t is a list which contains tuples and each tuple has inputs from all_t 
    and the list containing loaded models which will be extracted
 in the prediction function.'''

new_all_t=[]
for elem in all_t:
    new_all_t.append((elem,loaded_models))
start_time=time.time()
with closing(multiprocessing.Pool()) as p:
    predops=p.map(prediction,new_all_t)
print('Total time taken: {}'.format(time.time() - start_time))
输入是从代码的另一部分获得的图像numpy数组。但在执行这项任务时,我得到以下信息:

Traceback (most recent call last):
Traceback (most recent call last):
  File "/usr/lib/python2.7/multiprocessing/process.py", line 267, in _bootstrap
  File "/usr/lib/python2.7/multiprocessing/process.py", line 267, in _bootstrap
    self.run()
    self.run()
  File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 102, in worker
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 102, in worker
    task = get()
  File "/usr/lib/python2.7/multiprocessing/queues.py", line 376, in get
    task = get()
  File "/usr/lib/python2.7/multiprocessing/queues.py", line 376, in get
    return recv()
    return recv()
AttributeError: 'module' object has no attribute 'prediction'
AttributeError: 'module' object has no attribute 'prediction'
我无法解释此错误消息,如何解决此问题?任何建议都将不胜感激

更新2: 感谢所有的提示和一个完整的例子@sokato。我执行了@sokato发布的确切代码,但是我得到了以下错误(我也对代码进行了更改,得到了如下所示的相同错误)

new_all_t是一个包含元组的列表,每个元组都有来自all_t的输入和包含加载模型的列表,这些模型将在预测函数中提取。但是,我现在得到以下错误:

Traceback (most recent call last):
  File "trial_mult-ips.py", line 240, in <module>
    predops=p.map(prediction,new_all_t)
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 253, in map
    return self.map_async(func, iterable, chunksize).get()
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 572, in get
    raise self._value
NotImplementedError: numpy() is only available when eager execution is enabled.

我无法解释此错误消息,如何解决此问题?任何建议都将不胜感激

因此,我不确定您的一些设计选择,但我根据给定的信息进行了最佳尝试。具体来说,我认为并行函数中的全局变量和import语句可能存在一些问题

  • 您应该使用共享变量而不是全局变量在进程之间共享输入。如果需要,可以在多处理文档中阅读有关共享内存的更多信息

  • 我从教程中生成了模型,因为不包括您的模型

  • 您没有加入或关闭您的池,但使用以下代码,我能够使代码并行成功执行。您可以通过调用
    pool.close()
    或使用下面所示的“with”语法来关闭池。注意,with语法不适用于Python2.7


  • 我希望这会有所帮助。

    请包括模型文件的回购(或以其他方式),以便我可以重新创建您的问题。您也不会在任何地方指定输入值。所以完整的代码会很好。请提供一个。您使用Python 2有什么特别的原因吗?您找到这个问题的解决方案了吗?感谢您的观点,我执行了您的代码,但出现了以下错误,回溯(最近一次调用):文件“stackoverflow.py”,第47行,多处理.Pool()作为p:AttributeError:exitSorry,这是因为python 2.7不包括池的上下文管理器。请参阅我用2.7运行的更新响应,以确保它工作正常。请查看原始问题中的Update2和UPDATE3,以获得python2的修复。非常感谢@sokato。然而,顺序版本的速度是并行版本的3倍。这不是个好主意吗?我知道这取决于型号。model.predict是否已使用多处理(针对单个实例)?但我希望在并行运行多个模型预测时,与顺序预测相比,速度会有所加快。进程间的通信开销是否太大,以致于超出了处理的重量?抱歉@sokato我没有刷新页面以查看您的评论。你已经评论过了!谢谢。但是你能看看我的评论吗?我还有一个疑问。@NickRogers分配池和流程管理有相关费用。并非所有应用程序都适合并行处理。我相信张量流可以选择在引擎盖下进行多处理,这可能会与多处理池本身发生冲突。根据我的经验,大量的计算显然可以用于并行编程。在这种情况下,模型评估趋于简单,因此流程管理开销占主导地位。另一方面,如果要测试大量的模型,或者每个模型计算本身都很昂贵,那么它可能会更有用。
    WARNING:tensorflow:From /home/nick/.local/lib/python2.7/site-packages/tensorflow/python/ops/math_grad.py:1250: where (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.
    Instructions for updating:
    Use tf.where in 2.0, which has the same broadcast rule as np.where
    
    Traceback (most recent call last):
      File "the_other_end-mp.py", line 216, in <module>
        predops=p.map(prediction,modelon)
      File "/usr/lib/python2.7/multiprocessing/pool.py", line 253, in map
        return self.map_async(func, iterable, chunksize).get()
      File "/usr/lib/python2.7/multiprocessing/pool.py", line 572, in get
        raise self._value
    ValueError: Resource handles are not convertible to numpy.
    
    import numpy as np
    import multiprocessing, time, ctypes, os
    import tensorflow as tf
    
    mis = (28, 28) #model input shape
    mnist = tf.keras.datasets.mnist
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    x_train, x_test = x_train / 255.0, x_test / 255.0
    
    def createModels(models):
        model = tf.keras.models.Sequential([
            tf.keras.layers.Flatten(input_shape=mis),
            tf.keras.layers.Dense(128, activation='relu'),
            tf.keras.layers.Dropout(0.2),
            tf.keras.layers.Dense(10)
        ])
    
        model.compile(optimizer='adam',
                   loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
                   metrics=['accuracy'])
    
        model.fit(x_train, y_train, epochs=5)
    
        for mod in models:
            model.save(mod)
    
    def prediction(model_name):
    
        model=tf.keras.models.load_model(model_name)
        ret_val=model.predict(input).tolist()[0]
        return ret_val
    
    if __name__ == "__main__":
        models=['model1.h5','model2.h5','model3.h5','model4.h5','model5.h5']
        dir = os.listdir(".")
        if models[0] not in dir:
            createModels(models)
        # Shared array input
        ub = 100
        testShape = x_train[:ub].shape
        input_base = multiprocessing.Array(ctypes.c_double, 
        int(np.prod(testShape)),lock=False)
        input = np.ctypeslib.as_array(input_base)
        input = input.reshape(testShape)
        input[:ub] = x_train[:ub]
    
        # with multiprocessing.Pool() as p:  #Use me for python 3
        p = multiprocessing.Pool() #Use me for python 2.7
        start_time=time.time()
        res=p.map(prediction,models)
        p.close() #Use me for python 2.7
        print('Total time taken: {}'.format(time.time() - start_time))
        print(res)