解决ValueError: Tensor("Variable:0" dtype=float32_ref) must be from the same graph as Tensor("Reshape:

本文解决在Django框架中调用CNN模型时出现的ValueError错误,通过创建并使用同一计算图确保模型调用成功。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#解决django中调用CNN模型出现ValueError: Tensor(“Variable:0” dtype=float32_ref) must be from the same graph as Tensor(“Reshape:0”, shape=(?, 2 8, 28, 1), dtype=float32)的问题

在同一个.py文件中可以实现,不会报错,在外部的.py文件中调用预测的模型代码报错。

你好! 这是我第一次写博客,原因是最近在学django,里面发文使用了markdown编辑器,正好,在这里练练手,熟悉一下语法,顺便记录一下最近在做物种识别系统遇到的问题,感谢各位大量指教。

##开发工具及版本:pycharm2019.3专业版+django2.0+python3.7

1.首先是在同一个py文件中直接调用,代码和结果如下:

cnn.py:

//预测代码
import numpy as np
import tensorflow as tf
import cv2
class deeper_model:  
    x = tf.placeholder(tf.float32, [None, 784]) 
    # 创建神经网络中间层
    W = tf.Variable(tf.zeros([784, 10]))  #定义权重
    b = tf.Variable(tf.zeros([10])) #定义偏置

    #权重函数,用于初始化
    def weight_variable(self, shape):
        initial = tf.truncated_normal(shape, stddev=0.1) #标准差 stddev用于设置正态分布被截断前的标准差,设置为0.1后,训练精度就达到达到 99.2% 以上
        return tf.Variable(initial)

    #偏置,用于初始化
    def bias_variable(self, shape):
        initial = tf.constant(0.1, shape=shape) #创建常量initial,可设定形状。
        return tf.Variable(initial)

    #卷积操作,步长为1,大小为1*1
    def conv2d(self, x, W):
        return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')#前后必须为1

    #池化操作 tf.nn.max_pool()和tf.nn.avg_pool()
    def max_pool_2x2(self, x):
        return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

    # 槽函数--开始识别
    def startRecognize(self,new_img):
        # 读取图片
        or_img = cv2.imdecode(np.fromfile(new_img, dtype=np.uint8), 0)  # 解决中文路径问题
        img = cv2.resize(or_img, (28, 28))
        # print(img.shape)
        one_map = img.flatten()  # 将矩阵拉伸成一维的数组。
        tva = [(255 - x) * 1.0 / 255.0 for x in one_map]  # 将像素正常化为0和1

        # 1.y=relu(wx+b) 第一次卷积池化
        x_image = tf.reshape(self.x, [-1, 28, 28, 1])  # tf.reshape():解决输入图像的维数不符合的情况,-1表示根据实际情况定
        W_conv1 = self.weight_variable([5, 5, 1, 32])  # 卷积核5*5,通道数为1,对应输出32张图
        b_conv1 = self.bias_variable([32])

        h_conv1 = tf.nn.relu(self.conv2d(x_image, W_conv1) + b_conv1)  # 图片变为:(28-1)/1+1=28*28

        h_pool1 = self.max_pool_2x2(h_conv1)  # 池化后变为28/2=14*14

        # 2.y=relu(wx+b) 第二次卷积池化
        W_conv2 = self.weight_variable([5, 5, 32, 64])  # 卷积核5*5,通道数为32,对应输出64
        b_conv2 = self.bias_variable([64])

        h_conv2 = tf.nn.relu(self.conv2d(h_pool1, W_conv2) + b_conv2)  # 图片变为(14-1)/1+1=14*14
        h_pool2 = self.max_pool_2x2(h_conv2)  # 池化后变为14/2=7*7
        """经过两次卷积和池化操作后,图片大小变为7*7,共64个卷积核"""

        # 3.全连接层
        W_fc1 = self.weight_variable([7 * 7 * 64, 1024])  # 加入1024个神经元
        b_fc1 = self.bias_variable([1024])

        # 把刚才池化后输出的张量reshape成一个一维向量
        h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
        h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

        # 4.dropout防止过拟合的方法
        keep_prob = tf.placeholder(tf.float32)
        h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

        # 4.类别预测与输出
        W_fc2 = self.weight_variable([1024, 10])
        b_fc2 = self.bias_variable([10])

        # 应用softmax实现分类
        y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

        # 在 2017年3月2号以后;用 tf.global_variables_initializer() 替代 tf.initialize_all_variables()
        init_op = tf.global_variables_initializer()  # 变量初始化

        saver = tf.train.Saver()  # 实例化对象,保存所有的checkpoint 文件
        module_file = tf.train.latest_checkpoint('E:\pythonpackage\PyQt_model\model.ckpt')
        with tf.Session() as sess:
            sess.run(init_op)
            if module_file is not None:
                # 重载模型的图及权重参数
                saver.restore(sess, module_file)  # 这里使用了之前保存的模型参数

            prediction = tf.argmax(y_conv, 1)
            predint = prediction.eval(feed_dict={self.x: [tva], keep_prob: 1.0}, session=sess)

            print('recognize result:')
            print(predint[0])

        return predint[0]

if __name__ == '__main__':
    cnn_model = deeper_model()  # 实例化
    new_img='E:\\桌面\\5.jpg'
    reslut = cnn_model.startRecognize(new_img)  # 调用模型,输出识别

结果:
在这里插入图片描述

需要说明的几点:

  1. 代码用途: 我是先尝试了一下手写数字的图片识别,模型已经训练好了,前面的卷积和池化的结构可以自己调整,我已经封装成函数了,我的模型路径是在:E:\pythonpackage\PyQt_model\model.ckpt。
  2. 模型加载过程中只能加载一次,重复加载会报错,因为前端图片上传不止一次,因此这一行判断语句不能少:
module_file = tf.train.latest_checkpoint('E:\pythonpackage\PyQt_model\model.ckpt')
if module_file is not None:  
     saver.restore(sess, module_file)  

2.在外部的.py文件中调用预测的模型代码报错ValueError: Tensor(“Variable:0” dtype=float32_ref) must be from the same graph as Tensor。

在这里插入图片描述在这里插入图片描述

在另一个文件中调用预测的函数

views.py

from django.contrib.auth.models import User
from django.shortcuts import render
from CNNmodel.cnn import deeper_model
from account.models import UserInfo
from deeplearn.models import speciesRecognition
import tensorflow as tf
tf.reset_default_graph()

def pic_upload(request):
    """上传图片"""
    user = User.objects.get(username=request.user.username)
    userinfo = UserInfo.objects.get(user=user)
    if request.method == 'POST':
        new_img = speciesRecognition(data_photo=request.FILES.get('img'))
        new_img.save()

        new_img = new_img.data_photo
        print("图片地址:",new_img)

        cnn_model = deeper_model() #实例化
        cnn_model.startRecognize(new_img)  #调用模型,输出识别结果
       
    return render(request, 'deeplearn/pic_upload.html', {"userinfo_all": userinfo})

说明:

  1. 上面的文件是django的views.py视图函数文件,调用模型时报错。

解决方法

问题出在在cnn.py预测文件中,没有创建计算图,使用的默认的计算图。外部调用发现不在同一个计算图里面。

在代码中创建计算图,统一在同一个计算图中。
我是这样做的:

import numpy as np
import tensorflow as tf
import cv2

graph = tf.Graph()  #定义计算图
# 写深度学习的代码
class deeper_model:
    with graph.as_default(): #在这里加一个
        # 定义占位符
        x = tf.placeholder(tf.float32, [None, 784])  # 保存的数据类型,保存数据的结构,比如要保存一个1×2的矩阵,则struct=[1,2]

        # 创建神经网络中间层
        W = tf.Variable(tf.zeros([784, 10]))  # 定义权重
        b = tf.Variable(tf.zeros([10]))  # 定义偏置

        # y=x*w+b 10分类

    # 权重函数,用于初始化
    def weight_variable(self, shape):
        initial = tf.truncated_normal(shape, stddev=0.1)  # 标准差 stddev用于设置正态分布被截断前的标准差,设置为0.1后,训练精度就达到达到 99.2% 以上
        return tf.Variable(initial)

    # 偏置,用于初始化
    def bias_variable(self, shape):
        initial = tf.constant(0.1, shape=shape)  # 创建常量initial,可设定形状。
        return tf.Variable(initial)

    # 卷积操作,步长为1,大小为1*1
    def conv2d(self, x, W):
        return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')  # 前后必须为1

    # 池化操作 tf.nn.max_pool()和tf.nn.avg_pool()
    def max_pool_2x2(self, x):
        return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

    # 开始识别
    def startRecognize(self, new_img):
        with graph.as_default(): #在这里加第2个
            # 读取图片
            or_img = cv2.imdecode(np.fromfile(new_img, dtype=np.uint8), 0)  # 解决中文路径问题
            img = cv2.resize(or_img, (28, 28))
            # print(img.shape)
            one_map = img.flatten()  # 将矩阵拉伸成一维的数组。
            tva = [(255 - x) * 1.0 / 255.0 for x in one_map]  # 将像素正常化为0和1

            # 1.y=relu(wx+b) 第一次卷积池化
            x_image = tf.reshape(self.x, [-1, 28, 28, 1])  # tf.reshape():解决输入图像的维数不符合的情况,-1表示根据实际情况定
            W_conv1 = self.weight_variable([5, 5, 1, 32])  # 卷积核5*5,通道数为1,对应输出32张图
            b_conv1 = self.bias_variable([32])

            h_conv1 = tf.nn.relu(self.conv2d(x_image, W_conv1) + b_conv1)  # 图片变为:(28-1)/1+1=28*28
            h_pool1 = self.max_pool_2x2(h_conv1)  # 池化后变为28/2=14*14
            # 2.y=relu(wx+b) 第二次卷积池化
            W_conv2 = self.weight_variable([5, 5, 32, 64])  # 卷积核5*5,通道数为32,对应输出64
            b_conv2 = self.bias_variable([64])

            h_conv2 = tf.nn.relu(self.conv2d(h_pool1, W_conv2) + b_conv2)  # 图片变为(14-1)/1+1=14*14
            h_pool2 = self.max_pool_2x2(h_conv2)  # 池化后变为14/2=7*7
            """经过两次卷积和池化操作后,图片大小变为7*7,共64个卷积核"""

            # 3.全连接层
            W_fc1 = self.weight_variable([7 * 7 * 64, 1024])  # 加入1024个神经元
            b_fc1 = self.bias_variable([1024])

            # 把刚才池化后输出的张量reshape成一个一维向量
            h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
            h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

            # 4.dropout防止过拟合的方法
            keep_prob = tf.placeholder(tf.float32)
            h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

            # 4.类别预测与输出
            W_fc2 = self.weight_variable([1024, 10])
            b_fc2 = self.bias_variable([10])
            
            # 应用softmax实现分类
            y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

            # 在 2017年3月2号以后;用 tf.global_variables_initializer() 替代 tf.initialize_all_variables()
            init_op = tf.global_variables_initializer()  # 变量初始化

            saver = tf.train.Saver()  # 实例化对象,保存所有的checkpoint 文件
            module_file = tf.train.latest_checkpoint('E:\pythonpackage\PyQt_model\model.ckpt')
            with tf.Session() as sess:
                sess.run(init_op)
                if module_file is not None:
                    # 重载模型的图及权重参数
                    saver.restore(sess, module_file)  # 这里使用了之前保存的模型参数

                prediction = tf.argmax(y_conv, 1)
                predint = prediction.eval(feed_dict={self.x: [tva], keep_prob: 1.0}, session=sess)

                print('recognize result:')
                print(predint[0])

            return predint[0]

if __name__ == '__main__':
     cnn_model = deeper_model()  # 实例化
     new_img='E:\\桌面\\3.jpg'
     reslut = cnn_model.startRecognize(new_img)  # 调用模型,输出识别结果
#     print("结果:", reslut)

###加入后测试cnn,py1文件,发现没有问题,直接出结果:
在这里插入图片描述

外部文件中调用,问题也解决了。不再报错ValueError: Tensor(“Variable:0” dtype=float32_ref) must be from the same graph as Tensor(“Reshape:0”, shape=(?, 2 8, 28, 1), dtype=float32)

在这里插入图片描述

搞定。

关于计算图的理解,参考这篇博文:
[https://www.cnblogs.com/studylyn/p/9105818.html]

### 解决方案 `ValueError: Invalid dtype: float32_ref` 的错误通常发生在 TensorFlow 或其他深度学习框架中,当操作的数据类型不匹配或者某些张量被意外地指定为 `float32_ref` 类型。这种问题可能是由于旧版本的 TensorFlow 中的一些 API 使用了 `_ref` 后缀来表示可变变量的结果。 以下是可能导致此问题的原因以及解决方案: #### 原因分析 1. **API 更新冲突** 如果使用的 TensorFlow 版本较新,而代码是基于旧版编写的,则可能会遇到此类问题。例如,在 TensorFlow 2.x 中,默认启用了 Eager Execution,这改变了许多函数的行为[^4]。 2. **张量不可变性** 在 TensorFlow 中,`_ref` 表示该对象是可以修改的变量。如果尝试对一个不可变的对象执行需要 `_ref` 的操作,就会引发上述错误[^1]。 3. **数据类型的显式声明缺失** 某些情况下,未正确设置输入或中间计算结果的数据类型也可能导致类似的错误消息。 --- #### 解决方法 ##### 方法一:升级到最新版本的 TensorFlow 并启用兼容模式 确保安装的是最新稳定版本的 TensorFlow,并考虑切换回图模式(Graph Mode)。可以通过以下命令禁用默认的急切执行(Eager Execution): ```python import tensorflow as tf tf.compat.v1.disable_eager_execution() ``` ##### 方法二:替换过的操作符或函数 检查是否有任何已弃用的功能正在使用。例如,早期版本中的 `K.variable()` 应逐步迁移到更现代的方式定义变量,比如通过 `tf.Variable()` 替代: ```python from tensorflow.keras import backend as K # 过写法 old_var = K.variable(value) # 推荐替代 new_var = tf.Variable(initial_value=value, trainable=True) ``` ##### 方法三:验证并修正所有涉及数值运算的部分 确认所有的数学表达式都指定了适当的数据格式。对于大多数情况来说,应该统一转换成标准浮点数形式——即 `dtype=tf.float32` 而不是带有特殊标记的形式如 `float32_ref`。举个例子,假设存在如下片段: ```python box_xy = (K.sigmoid(feats[..., :2]) + grid) / K.cast(grid_shape[..., ::-1], K.dtype(feats)) ``` 这里需特别注意 `grid`, `feats` 和 `input_shape` 是否一致且均为合法数值数组。必要强制转型处理: ```python grid_casted = tf.cast(grid, dtype=tf.float32) feats_casted = tf.cast(feats, dtype=tf.float32) result = (tf.nn.sigmoid(feats_casted[..., :2]) + grid_casted) \ / tf.cast(grid_shape[..., ::-1], dtype=tf.float32)[^1] ``` ##### 方法四:调试工具辅助定位具体位置 利用断言语句排查潜在隐患区域。例如加入临打印日志查看实际传递过来的内容是否符合预期: ```python assert isinstance(box_xy, tf.Tensor), f"Expected Tensor got {type(box_xy)}" print(f"DType check passed! Current DType={box_xy.dtype}") ``` --- ### 总结 综上所述,“Invalid dtype: float32_ref”的根本原因多源于环境配置不当或是遗留代码风格所致。建议按照前述步骤逐一排查直至彻底消除异常现象为止。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值