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

YOLO-v7转TensorFlow时,如何正确输出标量值?

问题描述

尝试修改YOLO-v7模型输出,添加表示边界框数量的标量输出张量,但转换为TensorFlow时收到警告:

WARNING: The numpy array (ndarray) cannot be specified as an output layer. Therefore, the tool outputs a sequentially numbered .npy binary file. .npy_file_path: tf_output/0.npy

复现步骤

  • 使用onnx_graphsurgeon修改PyTorch模型输出,代码如下:
num_boxes_int = gs.Variable(name='num_boxes_int', dtype=np.int64)
num_boxes_out = gs.Variable(name='num_boxes_out', dtype=np.float32)
num_boxes_node = gs.Node(op="Shape",
                         inputs=[bbox_out],
                         outputs=[num_boxes_int], 
                         attrs={
                             'start':1,'end':2})
graph.nodes.append(num_boxes_node)
num_boxes_cast_node = gs.Node(op="Cast", 
                     inputs=[num_boxes_int], 
                     outputs=[num_boxes_out],
                    attrs={'to':int(onnx.TensorProto.FLOAT)})
graph.nodes.append(num_boxes_cast_node)
...
graph.outputs = [num_boxes_out, ...]
  • 执行命令转换为OpenVINO格式:
!mo --input_model {onnx_model_path} --input_shape [1,3,{input_height},{input_width}] --output_dir {openvino_dir}

经netron.app验证显示正常。

  • 执行命令转换为TensorFlow:
!openvino2tensorflow \
--model_path {openvino_dir}/{openvino_filename} \
--model_output_path {tf_output_dir} \
--weight_replacement_config {weight_replacement_config_path} \
--non_verbose \
--output_saved_model \
--output_no_quant_float32_tflite \
--output_float16_quant_tflite \
--output_full_integer_quant_tflite \
--output_dynamic_range_quant_tflite
  • 收到上述警告信息,且在netron.app中查看生成的.tflite文件时,其余输出正常,但缺失num_detections输出。

请问正确输出标量值的方法是什么?


解决方案

问题根源在于TensorFlow/TFLite不支持纯标量(0维张量)作为模型输出,openvino2tensorflow工具会将这类输出导出为单独的.npy文件而非包含在模型中。要解决这个问题,需要把标量输出转换为形状为[1]的1维张量,具体修改步骤如下:

1. 修改ONNX GraphSurgeon代码,添加Reshape节点

在原有的Cast节点之后,添加一个Reshape节点,把标量张量转换成形状为[1]的1维张量:

# 定义Reshape的目标形状:形状为[1]的常量张量
num_boxes_shape = gs.Constant(name="num_boxes_shape", values=np.array([1], dtype=np.int64))
# 定义Reshape后的输出变量
num_boxes_final = gs.Variable(name='num_boxes_final', dtype=np.float32, shape=(1,))
# 创建Reshape节点
num_boxes_reshape_node = gs.Node(op="Reshape",
                                 inputs=[num_boxes_out, num_boxes_shape],
                                 outputs=[num_boxes_final])
graph.nodes.append(num_boxes_reshape_node)
# 更新模型输出为Reshape后的张量
graph.outputs = [num_boxes_final, ...]  # 替换原来的num_boxes_out

2. 重新导出ONNX并转换格式

  • 重新运行修改后的ONNX GraphSurgeon代码,导出新的ONNX模型
  • 再次执行OpenVINO转换命令,之后用openvino2tensorflow转换为TensorFlow/TFLite格式

3. 验证输出

转换完成后,在netron.app中查看.tflite文件,num_boxes_final(或你自定义的输出名)会作为1维张量存在于输出列表中,同时不会再出现导出.npy文件的警告。

补充说明

如果后续需要在推理时获取标量值,只需从形状为[1]的张量中取出唯一元素即可(比如在TensorFlow中用tf.squeeze()或直接索引[0])。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 20:40:18