PaddleSlim icon indicating copy to clipboard operation
PaddleSlim copied to clipboard

AssertionError: feed_list should be set when return_list=False

Open liyuyuan6969 opened this issue 3 years ago • 7 comments

场景描述

我正在量化paddle里面的关键点检测模型,我参考的量化文档,但是我还是不是很懂sample_generator这个参数要怎么传?然后我看代码里面的加载数据集的方式是先调用self.dataset = cfg['{}Dataset'.format(self.mode.capitalize())]来构造一个对象,然后使用self.loader = create('{}Reader'.format(self.mode.capitalize()))( self.dataset, cfg.worker_num)来构造一个loader, 最后推理的方式为

for step_id, data in enumerate(self.loader):
        self.status['data_time'].update(time.time() - iter_tic)
        self.status['step_id'] = step_id
        profiler.add_profiler_step(profiler_options)
        self._compose_callback.on_step_begin(self.status)
        data['epoch_id'] = epoch_id
        
        if self.cfg.get('amp', False):
            with amp.auto_cast(enable=self.cfg.use_gpu):
                # model forward
                outputs = model(data)
                loss = outputs['loss']

我以为是把这个loader传到sample_generator参数就好了,于是我的量化代码就写成了下面的样子:

if __name__ == "__main__":
    image_path = r"./images/100"
    save_path = r"./images/all_anns_100.json"
    if os.path.exists(save_path):
        convert(image_path, save_path, image_path)
    # gt_db = load_coco_keypoint_annotations(save_path, image_path)
    cfg = load_config('/data/liyy/QuantPoseDemo/other/PaddleDetection/configs/keypoint/tiny_pose/tinypose_128x96.yml')
    # 开启静态图模式
    paddle.enable_static()
    image = paddle.static.data(
        name='image', shape=[None, 1, 128, 96], dtype='float32')
    label = paddle.static.data(name='label', shape=[None, 1], dtype='int64')
    dataset = cfg['{}Dataset'.format("eval".capitalize())]
    eval_reader = create('{}Reader'.format("eval".capitalize()))
    loader = eval_reader(dataset, cfg.worker_num)
    slim.quant.quant_post_static(
        executor=paddle.static.Executor(),
        feed_list=[image, label],
        model_dir='./inference_model',
        quantize_model_path='./quant_post_static_model',
        sample_generator=loader,
        model_filename='fp32.pdmodel',
        params_filename='fp32.pdiparams',
        batch_nums=10)

于是就有下面的报错: image

问题

  1. 请问我这里的sample_generator是直接传loader就行了吗?还是要把loader里面的data取出来,然后组成一个列表再传给sample_generator呢?
  2. 请问静态图中这个feed_list我这里应该怎么传呢? 感谢帮忙解答一下哈!谢谢了!

liyuyuan6969 avatar May 24 '22 01:05 liyuyuan6969

https://github.com/PaddlePaddle/PaddleSlim/blob/develop/demo/quant/quant_post/quant_post.py#L75 如果有已经写好的dataloader的话,可以直接传入dataloader,不用写 sample_generator 了

ceci3 avatar May 25 '22 02:05 ceci3

https://github.com/PaddlePaddle/PaddleSlim/blob/develop/demo/quant/quant_post/quant_post.py#L75 如果有已经写好的dataloader的话,可以直接传入dataloader,不用写 sample_generator 了

好的,谢谢哈!我试试

liyuyuan6969 avatar May 25 '22 06:05 liyuyuan6969

  1. 我调用这个API接口出现了这个错误,是版本不对吗?我得paddleSlim是2.1.1的 image

  2. 请问这个支持动态图量化吗?静态图量化需要给data_loader传一个feed_list进去,我直接传了image进去,不知道要不要传label,这个feed_list该怎么传是需要看哪里呢? image

liyuyuan6969 avatar May 25 '22 07:05 liyuyuan6969

我将paddleslim的版本更新为了2.2.2后,可以使用dataloader的选项,但是现在报错feed_list的数量不匹配 错误信息:ValueError: (InvalidArgument) The sample number of reader's input data and the input number of feed list are not equal. image

liyuyuan6969 avatar May 26 '22 01:05 liyuyuan6969

我将paddleslim的版本更新为了2.2.2后,可以使用dataloader的选项,但是现在报错feed_list的数量不匹配 错误信息:ValueError: (InvalidArgument) The sample number of reader's input data and the input number of feed list are not equal. image

应该是dataloader返回的输入的数量和模型里面的输入的数量不匹配,可以用netron可视化模型看下输入叫什么,然后在dataloader里相应的改一下就可以了~

ceci3 avatar May 27 '22 05:05 ceci3

我将paddleslim的版本更新为了2.2.2后,可以使用dataloader的选项,但是现在报错feed_list的数量不匹配 错误信息:ValueError: (InvalidArgument) The sample number of reader's input data and the input number of feed list are not equal. image

应该是dataloader返回的输入的数量和模型里面的输入的数量不匹配,可以用netron可视化模型看下输入叫什么,然后在dataloader里相应的改一下就可以了~

好的,我检查一下,前几天请假了!回的有点慢,谢谢哈

liyuyuan6969 avatar May 31 '22 00:05 liyuyuan6969

终于量化成功了 参考文档见:https://aistudio.baidu.com/aistudio/projectdetail/3924444 关键点检测模型量化代码如下:

# quant.py
import os
import paddle
import paddleslim as slim
import numpy as np
import warnings
from pycocotools.coco import COCO
import json
import tqdm
from PIL import Image
import traceback
from ppdet.core.workspace import load_config
from ppdet.core.workspace import create
from ppdet.data import transform
warnings.simplefilter('ignore', ResourceWarning)
USE_GPU = True
place = paddle.CUDAPlace(0) if USE_GPU else paddle.CPUPlace()
executor = paddle.static.Executor(place)
import yaml

def load_config(file_path):
    """
    Load config from file.

    Args:
        file_path (str): Path of the config file to be loaded.

    Returns: global config
    """
    _, ext = os.path.splitext(file_path)
    assert ext in ['.yml', '.yaml'], "only support yaml files for now"
    # load config
    with open(file_path) as f:
        file_cfg = yaml.load(f, Loader=yaml.Loader)
    return file_cfg


class Compose(object):
    def __init__(self, transforms, num_classes=80):
        self.transforms = transforms
        self.transforms_cls = []
        for t in self.transforms:
            for k, v in t.items():
                op_cls = getattr(transform, k)
                f = op_cls(**v)
                if hasattr(f, 'num_classes'):
                    f.num_classes = num_classes

                self.transforms_cls.append(f)

    def __call__(self, data):
        for f in self.transforms_cls:
            try:
                data = f(data)
            except Exception as e:
                stack_info = traceback.format_exc()
                print("err ", stack_info)
                # logger.warning("fail to map sample transform [{}] "
                #                "with error: {} and stack:\n{}".format(
                #                    f, e, str(stack_info)))
                raise e
        return data


if __name__ == "__main__":
    # 开启静态图模式
    paddle.enable_static()
    # 配置参数
    image_path = r"/data/liyy/QuantPoseDemo-20220531/other/PaddleDetection/tools/images/100"
    model_dir = '/data/liyy/QuantPoseDemo-20220531/other/PaddleDetection/tools/tinypose_128x96'
    quantize_model_path = '/data/liyy/QuantPoseDemo-20220531/other/PaddleDetection/tools/quant_post_static_model'
    model_filename = 'model.pdmodel'
    params_filename = 'model.pdiparams'
    model_dir_quant_static = "./"
    save_path = r"./images"
    # 加载config文件
    cfg = load_config(
        '/data/liyy/QuantPoseDemo-20220531/other/PaddleDetection/configs/keypoint/tiny_pose/tinypose_128x96.yml')
    # 构建sample_transforms
    sample_transforms = cfg["TestReader"]["sample_transforms"]
    sample_transforms = Compose(
        sample_transforms, num_classes=1)
    # 构建dataset,主要用于获取roidbs的规范化数据字典用于输入sample_transforms
    dataset = cfg['{}Dataset'.format("test".capitalize())]
    dataset.check_or_download_dataset()
    dataset.parse_dataset()
    dataset.set_transform(sample_transforms)
    # 注意datas返回的图片需要经过reshape到输入尺寸
    datas = iter([
        sample_transforms(
            info
        )["image"].reshape(-1, 3, 128, 96) for info in dataset.roidbs
    ])
    # 静态量化
    slim.quant.quant_post_static(
        executor=paddle.static.Executor(),  # Paddle 静态图执行器
        model_dir=model_dir,  # 输入模型路径
        model_filename=model_filename,  # 输入模型计算图文件名称
        params_filename=params_filename,  # 输入模型参数文件名称
        quantize_model_path=model_dir_quant_static,  # 输出模型路径
        save_model_filename=model_filename,  # 输出模型计算图文件名称
        save_params_filename=params_filename,  # 输出模型参数文件名称
        batch_generator=None,  # 数据批次生成器,需传入一个可调用对象,返回一个 Generator
        sample_generator=lambda: datas,  # 数据采样生成器,需传入一个可调用对象,返回一个 Generator
        data_loader=None,  # Paddle DataLoader
        batch_size=1,  # 数据批次大小
        batch_nums=100,  # 数据批次数量,默认为使用全部数据
        weight_bits=8,  # 参数量化比特数 8/16 对应 INT8/16 类型
        activation_bits=8,  # 激活值量化比特数 8/16 对应 INT8/16 类型
        weight_quantize_type='channel_wise_abs_max',
        # 参数量化方法,目前支持 'range_abs_max', 'moving_average_abs_max' 和 'abs_max'
        activation_quantize_type='range_abs_max',  # 激活值量化方法,目前支持 'range_abs_max', 'moving_average_abs_max' 和 'abs_max'
        algo='mse',  # 校准方法,目前支持 'KL', 'hist', 'mse', 'avg', 'abs_max'
    )
    print("ok!")

liyuyuan6969 avatar Jun 24 '22 10:06 liyuyuan6969

@liyuyuan6969 哈喽,大佬,使用您最后提供的这部分代码,出现如下的错误 File "/root/PaddleDetection/quant.py", line 86, in dataset.parse_dataset() File "/root/PaddleDetection/ppdet/data/source/dataset.py", line 168, in parse_dataset self.roidbs = self._load_images() File "/root/PaddleDetection/ppdet/data/source/dataset.py", line 196, in _load_images assert len(records) > 0, "No image file found" AssertionError: No image file found 能帮忙看看吗,感谢。

APeiZou avatar Mar 27 '23 07:03 APeiZou