caffe模型量化

1 使用 caffe-int-convert-tools 量化

  • 下载

    git clone https://github.com/BUG1989/caffe-int8-convert-tools.git
    # wget https://github.com/BUG1989/caffe-int8-convert-tools/archive/master.zip
    
  • 准备文件

    test/
    ├── images
    │   ├── 001.jpeg
    │   ├── 002.jpeg
    │   └── 003.jpeg
    └── models
        ├── ResNet_50_train.prototxt
        └── ResNet_50.caffemodel
    
  • 执行

    python caffe-int8-convert-tools/caffe-int8-convert-tool-dev-weight.py \
        --proto=model_resnet/ResNet_50_train.prototxt \
        --model=model_resnet/ResNet_50.caffemodel \
        --mean 127.5 127.5 127.5 \
        --norm=0.00777 \
        --images=caffe-int8-convert-tools/test/images/ \
        --output=caffe-int8-convert-tools/test/ResNet_50.table \
        --gpu=1
    

    其中,output 参数是生成的 .table 文件。

  • 执行遇到问题1

    执行 np.set_printoptions(threshold=np.nan) 报错
    

    解决:将其改为 np.set_printoptions(threshold=np.inf),是版本问题。

  • 执行遇到问题2

    TypeError: _open() got an unexpected keyword argument 'as_grey'
    

    解决:浏览错误信息,找到包含 as_grey 字符的文件,打开该文件,修改 as_greyas_gray 即可,是版本问题。

如果上面步骤执行完会在指定路径产生 .table 文件。

2 转换为 ncnn 模型

参考这里

  • 下载

    git clone https://github.com/Tencent/ncnn.git
    # wget https://github.com/Tencent/ncnn/archive/master.zip
    
  • 编译

    cd ncnn
    mkdir build && cd build
    cmake ..
    make -j8
    make install
    

    编译完成后,会在 ./ncnn/build/tools 目录下生成 caffe/caffe2ncnnncnn2mem 可执行程序。

    caffe2ncnn 是将 caffe 模型转换为 ncnn 模型;
    ncnn2mem 可以对 ncnn 模型加密(本文省略);

  • caffe 转换为 ncnn

    ./ncnn/build/tools/caffe/caffe2ncnn \
        model_resnet/ResNet_50_train.prototxt \
        model_resnet/ResNet_50.caffemodel \
        caffe-int8-convert-tools/test/ResNet_50-int8.param \
        caffe-int8-convert-tools/test/ResNet_50-int8.bin \
        256 \
        caffe-int8-convert-tools/test/ResNet_50.table 
    

    会生成 ResNet_50-int8.paramResNet_50-int8.bin

  • 调用 ncnn 模型

    内容参考 ncnn 源码:./ncnn/examples/squeezenet.cpp。需要的头文件和库文件在 ./ncnn/build/install 中,编译时需要添加。

    CMakeLists.txt

    #SET(CMAKE_CXX_FLAGS "-std=c++11 -O3")
    
    cmake_minimum_required(VERSION 2.8)
    project(use_model)
    
    set(CMAKE_BUILD_TYPE Release)
    
    list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
    
    # OpenMP
    FIND_PACKAGE( OpenMP REQUIRED)
    if(OPENMP_FOUND)
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
    endif()
    
    # OpenCV
    find_package(OpenCV REQUIRED)
    include_directories(${OpenCV_INCLUDE_DIRS})
    
    # Boost
    add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY)
    find_package(Boost REQUIRED COMPONENTS filesystem system) 
    include_directories(${Boost_INCLUDE_DIRS})
    
    # Ncnn
    set(Ncnn_INCLUDE_DIR /home/tamray/trcaffe/ncnn/build/install/include)
    set(Ncnn_LIBRARY_DIR /home/tamray/trcaffe/ncnn/build/install/lib) 
    include_directories(${Ncnn_INCLUDE_DIR})
    LINK_DIRECTORIES(${Ncnn_LIBRARY_DIR})
    
    add_executable(app main.cpp)
    target_link_libraries(app
                            ${OpenCV_LIBS} 
                            ${Boost_LIBS} 
                            libncnn.a
    )
    

    main.cpp

    #include <ncnn/net.h>
    
    #include <algorithm>
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <stdio.h>
    #include <vector>
    
    static int detect_squeezenet(const cv::Mat& bgr, std::vector<float>& cls_scores)
    {
        ncnn::Net squeezenet;
    
        squeezenet.opt.use_vulkan_compute = true;
    
        // the ncnn model https://github.com/nihui/ncnn-assets/tree/master/models
        squeezenet.load_param("squeezenet_v1.1.param");
        squeezenet.load_model("squeezenet_v1.1.bin");
    
        ncnn::Mat in = ncnn::Mat::from_pixels_resize(bgr.data, ncnn::Mat::PIXEL_BGR, bgr.cols, bgr.rows, 227, 227);
    
        const float mean_vals[3] = {104.f, 117.f, 123.f};
        in.substract_mean_normalize(mean_vals, 0);
    
        ncnn::Extractor ex = squeezenet.create_extractor();
    
        ex.input("data", in);
    
        ncnn::Mat out;
        ex.extract("prob", out);
    
        cls_scores.resize(out.w);
        for (int j = 0; j < out.w; j++)
        {
            cls_scores[j] = out[j];
        }
    
        return 0;
    }
    
    static int print_topk(const std::vector<float>& cls_scores, int topk)
    {
        // partial sort topk with index
        int size = cls_scores.size();
        std::vector<std::pair<float, int> > vec;
        vec.resize(size);
        for (int i = 0; i < size; i++)
        {
            vec[i] = std::make_pair(cls_scores[i], i);
        }
    
        std::partial_sort(vec.begin(), vec.begin() + topk, vec.end(),
                          std::greater<std::pair<float, int> >());
    
        // print topk and score
        for (int i = 0; i < topk; i++)
        {
            float score = vec[i].first;
            int index = vec[i].second;
            fprintf(stderr, "%d = %f\n", index, score);
        }
    
        return 0;
    }
    
    int main(int argc, char** argv)
    {
        if (argc != 2)
        {
            fprintf(stderr, "Usage: %s [imagepath]\n", argv[0]);
            return -1;
        }
    
        const char* imagepath = argv[1];
    
        cv::Mat m = cv::imread(imagepath, 1);
        if (m.empty())
        {
            fprintf(stderr, "cv::imread %s failed\n", imagepath);
            return -1;
        }
    
        std::vector<float> cls_scores;
        detect_squeezenet(m, cls_scores);
    
        print_topk(cls_scores, 3);
    
        return 0;
    }
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值