TFLite目标检测模型输出形状异常问题求助
问题概述
在WSL Ubuntu 20.04/22.04环境下,通过Conda创建Python3.9环境,使用tflite_model_maker训练efficientdet_lite0目标检测模型(Pascal VOC格式数据集)时,出现以下问题:
- 训练阶段弹出警告:
Node 'resample_p7/PartitionedCall'输出数与_output_shapes属性指定不符 - 导出的TFLite模型输出形状不符合TensorFlow官方规定的4种标准输出(
detection_boxes: [1, num_boxes,4]等) - 测试时输出张量为空,多次尝试无法解决
环境配置代码
# Install Miniconda !apt install wget !wget https://repo.anaconda.com/miniconda/Miniconda3-py37_4.9.2-Linux-x86_64.sh !chmod +x Miniconda3-py37_4.9.2-Linux-x86_64.sh !bash ./Miniconda3-py37_4.9.2-Linux-x86_64.sh -b -f -p /usr/local # Update Conda !conda update -n base -c defaults conda -y # Create a Python 3.9 environment !conda create --name py39_environment python=3.9 -y # Initialize shell for Conda !conda init bash # Activate the environment and check Python version !source activate py39_environment && python --version !source /usr/local/etc/profile.d/conda.sh && conda activate py39_environment && pip install tflite_model_maker !source /usr/local/etc/profile.d/conda.sh && conda activate py39_environment && pip install -q pycocotools !source /usr/local/etc/profile.d/conda.sh && conda activate py39_environment && pip install opencv-python-headless !source /usr/local/etc/profile.d/conda.sh && conda activate py39_environment && pip uninstall -y tensorflow && pip install -q tensorflow==2.8.0 !source /usr/local/etc/profile.d/conda.sh && conda activate py39_environment && pip install ipykernel !source /usr/local/etc/profile.d/conda.sh && conda activate py39_environment && pip install --upgrade numba llvmlite
训练代码(train.py)
import numpy as np import os np.object = object np.bool = bool np.complex = complex from tflite_model_maker.config import ExportFormat from tflite_model_maker import model_spec from tflite_model_maker import object_detector import tensorflow as tf assert tf.__version__.startswith('2') tf.get_logger().setLevel('ERROR') from absl import logging logging.set_verbosity(logging.ERROR) label_map = {1: 'Plastic', 2: 'Trash'} train_images_dir = '/trashnet-training/pascal_voc/train/images' train_annotations_dir = '/trashnet-training/pascal_voc/train/Annotations' val_images_dir = '/trashnet-training/pascal_voc/valid/images/' val_annotations_dir = '/trashnet-training/pascal_voc/valid/Annotations' train_data = object_detector.DataLoader.from_pascal_voc( train_images_dir, train_annotations_dir, label_map=label_map) validation_data = object_detector.DataLoader.from_pascal_voc( val_images_dir, val_annotations_dir, label_map=label_map) spec = model_spec.get('efficientdet_lite0') model = object_detector.create(train_data=train_data, model_spec=spec, validation_data=validation_data, epochs=50, batch_size=10, train_whole_model=True) model.evaluate(validation_data) TFLITE_FILENAME = 'trained_model.tflite' LABELS_FILENAME = 'model-labels.txt' model.export(export_dir='.', tflite_filename=TFLITE_FILENAME, label_filename=LABELS_FILENAME, export_format=[ExportFormat.TFLITE, ExportFormat.LABEL])
测试代码(test_model.py)
import tensorflow as tf import numpy as np interpreter = tf.lite.Interpreter(model_path="trained_model.tflite") interpreter.allocate_tensors() input_details = interpreter.get_input_details() output_details = interpreter.get_output_details() interpreter.invoke() output_data = interpreter.get_tensor(output_details[0]['index']) input_data = interpreter.get_tensor(input_details[0]['index']) print(f"Input tensor: {input_data}") print(f"Output tensor: {output_data}") tf.lite.experimental.Analyzer.analyze(model_path="trained_model.tflite")
原因分析与修复方案
1. 版本兼容性不匹配
TensorFlow与TFLite Model Maker版本必须严格对应,直接pip install tflite_model_maker会安装最新版本,与指定的TensorFlow 2.8.0不兼容,导致模型结构转换异常。
修复:
安装与TensorFlow 2.8.0匹配的TFLite Model Maker版本,替换环境配置中的tflite_model_maker安装命令:
pip install tflite-model-maker==0.4.1
2. NumPy手动修改的潜在风险
代码中手动修改NumPy属性(np.object = object等)是为了兼容高版本NumPy,但这种修改会干扰TensorFlow内部的张量形状处理逻辑,尤其在模型导出阶段引发异常。
修复:
降级NumPy到兼容版本,避免手动修改:
pip install numpy==1.23.5
3. 训练与导出配置问题
启用train_whole_model=True会修改模型的原始结构,TFLite转换时可能无法正确识别输出节点;同时测试代码未输入有效图像数据,导致输出为空。
修复:
- 先尝试关闭
train_whole_model=True(改为False),仅训练模型头部,验证导出是否正常; - 修改测试代码,添加图像预处理并输入有效数据:
import tensorflow as tf import numpy as np def preprocess_image(image_path, input_shape): # 加载图像 img = tf.io.read_file(image_path) img = tf.image.decode_jpeg(img, channels=3) # 调整尺寸匹配模型输入 img = tf.image.resize(img, input_shape[:2]) # 添加batch维度 img = tf.expand_dims(img, axis=0) # 归一化(EfficientDet Lite通常用0-1范围) img = img / 255.0 return img interpreter = tf.lite.Interpreter(model_path="trained_model.tflite") interpreter.allocate_tensors() input_details = interpreter.get_input_details() output_details = interpreter.get_output_details() # 替换为你的测试图像路径 img_data = preprocess_image("test_plastic.jpg", input_details[0]['shape']) # 设置输入张量 interpreter.set_tensor(input_details[0]['index'], img_data) # 执行推理 interpreter.invoke() # 获取所有输出张量 detection_boxes = interpreter.get_tensor(output_details[0]['index']) detection_classes = interpreter.get_tensor(output_details[1]['index']) detection_scores = interpreter.get_tensor(output_details[2]['index']) num_detections = interpreter.get_tensor(output_details[3]['index']) print(f"检测框:{detection_boxes[0][:int(num_detections[0])]}") print(f"类别:{detection_classes[0][:int(num_detections[0])]}") print(f"置信度:{detection_scores[0][:int(num_detections[0])]}")
4. 数据集标签映射一致性问题
需确认Pascal VOC标注文件中的类别ID与代码中的label_map完全匹配,若XML文件中<object>的ID不是1和2,会导致数据加载无效,模型训练无有效特征。
修复:
检查Annotations文件夹中的XML文件,查看<object>对应的类别ID,调整label_map为实际标注的ID,例如如果标注中Plastic的ID是0,则修改为:
label_map = {0: 'Plastic', 1: 'Trash'}
内容的提问来源于stack exchange,提问作者jansdhillon

