You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ROS线程中tf.keras模型预测报Tensor不在当前图错误求助

解决ROS回调线程中调用tf.keras模型预测的图绑定错误

我之前在ROS里部署Keras模型时也踩过一模一样的坑!主线程预测好好的,回调线程一调用就炸,各种图相关的ValueError,试过锁、clear_session都没用,后来才搞明白是TensorFlow的图线程绑定问题。给你一步步解决:

核心问题原因

TensorFlow的计算图是和创建它的线程绑定的——你在主线程加载模型时,所有模型操作都被加到了主线程的默认图里。而ROS的回调是在新线程执行的,默认不会复用这个图,所以调用predict时就会找不到对应的张量,直接报错。

修复步骤(直接改你的代码就行)

  1. 主线程加载模型后,必须初始化预测函数
    加载完权重后立刻调用my_model._make_predict_function(),这个方法会在主线程的默认图里创建预测需要的所有操作,不然线程里调用时会找不到这些操作(你之前注释掉了这个关键步骤!)。
  2. 保存主线程的默认图
    加载模型后,把当前的默认图存为全局变量,后续回调线程要显式切换到这个图。
  3. 回调中必须用with graph.as_default():包裹预测代码
    哪怕加了锁,也要确保预测操作在正确的图上下文里执行。

修改后的完整代码

#!/usr/bin/python2
from tensorflow import keras
from tensorflow.keras.models import model_from_json
from tfm_msgs.msg import IsLooking
import numpy as np
import tensorflow as tf
from threading import Lock
import os  # 补上你漏写的os导入

# 全局变量提前声明
my_model = None
graph = None
mutex = Lock()
pub = None  # 假设pub在其他地方初始化完成

def callback(face_array_stamped):
    global mutex, graph, my_model, pub
    mutex.acquire()
    try:
        true_faces = []
        for face in face_array_stamped.faces:
            if len(face.eyes) == 2:
                true_faces.append(face)
        if len(true_faces) == 1:
            true_face = true_faces[0]
            # 关键:切换到主线程的图上下文执行预测
            with graph.as_default():
                prediction = my_model.predict(np.array([[ # 这里填你的输入数据 ]]))[0]
            # 后续处理逻辑...
    finally:
        mutex.release()

if __name__ == '__main__':
    # 加载模型文件
    model_dir = str(os.path.dirname(os.path.abspath(__file__))) + "/../nnet_models/"
    json_file = open(model_dir+'model.json', 'r')
    my_model = model_from_json(json_file.read())
    json_file.close()
    my_model.load_weights(model_dir+'model.h5')
    
    # 核心步骤1:在主线程初始化预测函数
    my_model._make_predict_function()
    
    # 核心步骤2:保存主线程的默认计算图
    graph = tf.get_default_graph()
    
    # Compile只需要在主线程执行一次
    my_model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    
    # 这里放ROS节点初始化、发布者/订阅者初始化的代码...

额外注意事项

  • 所有模型初始化操作(加载、compile、_make_predict_function)必须在主线程完成,绝对不能放到回调线程里。
  • 锁mutex要保留,避免多个回调线程同时调用predict导致资源冲突。
  • 如果还是有问题,可以试试直接保存整个模型(用my_model.save()),再用keras.models.load_model()加载——这种方式会自动处理图的绑定,有时候比json+weights的方式更可靠。

内容的提问来源于stack exchange,提问作者fcolecumberri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:14:06