运行Keras模型以在多线程中进行预测

时间:2017-03-31 08:44:16

标签: tensorflow thread-safety keras reinforcement-learning

类似于this question我正在运行异步强化学习算法,需要在多个线程中运行模型预测以更快地获得训练数据。我的代码基于GitHub上的DDPG-keras,其神经网络构建于Keras& Tensorflow。我的代码片段如下所示:

  • 异步线程创建和加入:

    for roundNo in xrange(self.param['max_round']):
        AgentPool = [AgentThread(self.getEnv(), self.actor, self.critic, eps, self.param['n_step'], self.param['gamma'])]
        for agent in AgentPool:
            agent.start()
        for agent in AgentPool:
            agent.join()
    
  • 代理线程代码

    """Agent Thread for collecting data"""
    def __init__(self, env_, actor_, critic_, eps_, n_step_, gamma_):
        super(AgentThread, self).__init__()
        self.env = env_         # type: Environment
        self.actor = actor_     # type: ActorNetwork
        # TODO: use Q(s,a)
        self.critic = critic_   # type: CriticNetwork
        self.eps = eps_         # type: float
        self.n_step = n_step_   # type: int
        self.gamma = gamma_
        self.data = {}
    
    def run(self):
        """run behavior policy self.actor to collect experience data in self.data"""
        state = self.env.get_state()
        action = self.actor.model.predict(state[np.newaxis, :])[0]
        action = np.maximum(np.random.normal(action, self.eps, action.shape), np.ones_like(action) * 1e-3)
    

运行这些代码时,我遇到了Tensorflow异常:

Using TensorFlow backend.
create_actor_network
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/Users/niyan/code/routerRL/A3C.py", line 26, in run
    action = self.actor.model.predict(state[np.newaxis, :])[0]
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/keras/engine/training.py", line 1269, in predict
    self._make_predict_function()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/keras/engine/training.py", line 798, in _make_predict_function
    **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/keras/backend/tensorflow_backend.py", line 1961, in function
    return Function(inputs, outputs, updates=updates)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/keras/backend/tensorflow_backend.py", line 1919, in __init__
    with tf.control_dependencies(self.outputs):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 3583, in control_dependencies
    return get_default_graph().control_dependencies(control_inputs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 3314, in control_dependencies
    c = self.as_graph_element(c)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 2405, in as_graph_element
    return self._as_graph_element_locked(obj, allow_tensor, allow_operation)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 2484, in _as_graph_element_locked
    raise ValueError("Tensor %s is not an element of this graph." % obj)
ValueError: Tensor Tensor("concat:0", shape=(?, 4), dtype=float32) is not an element of this graph.

那么如何使用经过训练的Keras模型(使用Tensorflow作为后端)在多个线程中同时进行预测?

4月2日更新: 我尝试过应对模型而不是重量,但是没有用:

for roundNo in xrange(self.param['max_round']):
    for agent in self.AgentPool:
        agent.syncModel(self.getEnv(), self.actor, self.critic, eps)
        agent.start()
    for agent in self.AgentPool:
        agent.join()

def syncModel(self, env_, actor_, critic_, eps_):
    """synchronize A-C models before collecting data"""
    # TODO copy env, actor, critic
    self.env = env_     # shallow copy
    self.actor.model.set_weights(actor_.model.get_weights())        # deep copy, by weights
    self.critic.model.set_weights(critic_.model.get_weights())      # deep copy, by weights
    self.eps = eps_     # shallow copy
    self.data = {}

编辑: 在Github上看到这个jaara/AI-blog,似乎

model._make_predict_function()  # have to initialize before threading

的工作原理。

作者对this issue进行了一些解释。有关进一步的讨论,请参阅this issue on Keras

4 个答案:

答案 0 :(得分:1)

python 中的多线程不一定能更好地利用您的资源,因为 python 使用 global interpreter lock 并且一次只能运行一个本机线程。

在 python 中,通常你应该使用多处理来利用你的资源,但由于我们谈论的是 keras 模型,我不确定这样做是否正确。 在多个进程中加载​​多个模型有其自身的开销,您可以简单地增加批量大小,正如其他人已经指出的那样。

或者,如果您有一个繁重的预处理阶段,您可以在一个过程中预处理您的数据并在另一个过程中预测它们(尽管我怀疑这是否必要)。

答案 1 :(得分:0)

预测多个线程中的数据是一个坏主意。离线预测数据时,可以在batch_size中使用更大的model.predict,而在线预测数据时,可以使用tensorflow serving

答案 2 :(得分:0)

Keras不是线程安全的,要预测大批量,可以使用batch_size设置最大限制。 如果要部署到生产环境,理想的方法是转换模型权重tensorflow原型并使用tensorflow服务。

您可以关注此博客 http://machinelearningmechanic.com/keras/2019/06/26/keras-serving-keras-model-quickly-with-tensorflow-serving-and-docker-md.html

答案 3 :(得分:0)

由于 Python 的全局解释器锁,你应该考虑使用多处理而不是线程。 Ray 是使用 Python 构建分布式应用程序的绝佳 API,并且他们已经拥有一个名为 RLlib 的强化学习框架。我强烈建议您查看 Ray,尤其是对于强化学习应用。