Tencent / ncnn

ncnn is a high-performance neural network inference framework optimized for the mobile platform
Other
20.35k stars 4.16k forks source link

转换keras 模型后模型结果不正确 #5037

Closed Sherlock-hh closed 1 year ago

Sherlock-hh commented 1 year ago

error log | 日志或报错信息 | ログ

已成功使用keras2ncnn项目将MBLLEN模型转为ncnn模型,但是跑出来的结果是花屏 image 使用netron打开keras和ncnn模型后发现除输入层外,其余模型的每一层输入[a,b,c,d]都变成[d,c,b,a]了,这对结果是否会有影响?对比图片 image

model | 模型 | モデル

  1. original model 原始模型 转化代码:

    def export_keras_model():
    #if not os.path.exists(KERAS_MODEL_PATH2):
    
        model = Networkrknn.build_mbllen((input_shape[0],input_shape[1], 3))
        model.load_weights(KERAS_MODEL_PATH)
        opt = keras.optimizers.Adam(lr=2 * 1e-04, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
        model.compile(loss='mse', optimizer=opt)
        model.save(KERAS_MODEL_PATH2)

    运行代码:

    ncnn::Mat in = ncnn::Mat::from_pixels_resize(raw_img.data, ncnn::Mat::PIXEL_BGR, raw_img.cols, raw_img.rows, input_size_w, input_size_h);
    
    printf("in mat %f %f",in[0],in[1]);
    ncnn::Mat out;
    const float mean_vals[3] = {0.0f, 0.0f, 0.0f};
    const float norm_vals[3] = {1.0/255.0f,1.0/255.0f,1.0/255.0f};
    std::string savenamein="./mbllenin"+std::to_string(frame_id)+".raw";
    FILE* fncnnin=fopen(savenamein.c_str(),"wb");
    fwrite(in.data,sizeof(float),in.h*in.c*in.w,fncnnin);
    fclose(fncnnin);
    
    in.substract_mean_normalize(mean_vals, norm_vals);
    
    ncnn::Extractor ex = mobilenet.create_extractor();
    //ex.set_light_mode(true);
    ex.set_num_threads(4);
    //ex.input("data", in);
    //ex.extract("detection_out",out);
    ex.input("input_1_blob", in);
    ex.extract("conv2d_50_blob",out);
    std::string savename="./mbllenout"+std::to_string(frame_id)+".raw";
    FILE* fncnn=fopen(savename.c_str(),"wb");
    fwrite(out.data,sizeof(float),in.h*in.c*in.w,fncnn);
    fclose(fncnn);

how to reproduce | 复现步骤 | 再現方法

只要一运行就会出现这个问题。

Sherlock-hh commented 1 year ago

打印中间层结果发现ncnn模型第一层卷积后的特征图都变成了负数,原始模型则都为正数,想不通脑袋疼的想不通 image image

w8501 commented 1 year ago

输入也提供一下?

Sherlock-hh commented 1 year ago

输入也提供一下?

啊啊啊有人理我了这里这里,keras ncnn模型和输入图片都在这里。 这里是测试第一层卷积“conv2d_blob”的输出,测试代码是在mobilnet的demo上面改出来的:

cv::Rect test_mbllen(cv::Mat& raw_img, float threshold)
{
#if NCNN_VULKAN
    mobilenet.opt.use_vulkan_compute = true;
#endif // NCNN_VULKAN

    cv::Rect ret(0, 0, 0, 0);
    std::vector<cv::Rect> object_rects;

    int img_h = raw_img.size().height;
    int img_w = raw_img.size().width;
    int input_size_w = 256;// = 300;
    int input_size_h = 256;// = 300;
    ncnn::Mat in = ncnn::Mat::from_pixels_resize(raw_img.data, ncnn::Mat::PIXEL_BGR, raw_img.cols, raw_img.rows, input_size_w, input_size_h);

    printf("in mat %f %f",in[0],in[1]);
    ncnn::Mat out;
    const float mean_vals[3] = {0.0f, 0.0f, 0.0f};
    const float norm_vals[3] = {1.0/255.0,1.0/255.0,1.0/255.0};

    in.substract_mean_normalize(mean_vals, norm_vals);
    std::string savenamein="./mbllenin"+std::to_string(frame_id)+".raw";
    FILE* fncnnin=fopen(savenamein.c_str(),"wb");
    fwrite(in.data,sizeof(float),in.h*in.c*in.w,fncnnin);
    fclose(fncnnin);
    ncnn::Extractor ex = mobilenet.create_extractor();
    //ex.set_light_mode(true);
    ex.set_num_threads(4);
    //ex.input("data", in);
    //ex.extract("detection_out",out);
    ex.input("input_1_blob", in);
    ex.extract("conv2d_blob",out);
    std::string savename="./mbllenout"+std::to_string(frame_id)+".raw";
    FILE* fncnn=fopen(savename.c_str(),"wb");
    fwrite(out.data,sizeof(float),in.h*in.c*in.w,fncnn);
    fclose(fncnn);

    printf("out mat %f %f",out[0],out[256*256]);
    printf("\nout size:%d,%d,%d\n", out.w, out.h, out.c);
}
w8501 commented 1 year ago

输入也提供一下?

啊啊啊有人理我了这里这里,keras ncnn模型和输入图片都在这里。 这里是测试第一层卷积“conv2d_blob”的输出,测试代码是在mobilnet的demo上面改出来的:

cv::Rect test_mbllen(cv::Mat& raw_img, float threshold)
{
#if NCNN_VULKAN
    mobilenet.opt.use_vulkan_compute = true;
#endif // NCNN_VULKAN

    cv::Rect ret(0, 0, 0, 0);
    std::vector<cv::Rect> object_rects;

    int img_h = raw_img.size().height;
    int img_w = raw_img.size().width;
    int input_size_w = 256;// = 300;
    int input_size_h = 256;// = 300;
    ncnn::Mat in = ncnn::Mat::from_pixels_resize(raw_img.data, ncnn::Mat::PIXEL_BGR, raw_img.cols, raw_img.rows, input_size_w, input_size_h);

    printf("in mat %f %f",in[0],in[1]);
    ncnn::Mat out;
    const float mean_vals[3] = {0.0f, 0.0f, 0.0f};
    const float norm_vals[3] = {1.0/255.0,1.0/255.0,1.0/255.0};

    in.substract_mean_normalize(mean_vals, norm_vals);
    std::string savenamein="./mbllenin"+std::to_string(frame_id)+".raw";
    FILE* fncnnin=fopen(savenamein.c_str(),"wb");
    fwrite(in.data,sizeof(float),in.h*in.c*in.w,fncnnin);
    fclose(fncnnin);
    ncnn::Extractor ex = mobilenet.create_extractor();
    //ex.set_light_mode(true);
    ex.set_num_threads(4);
    //ex.input("data", in);
    //ex.extract("detection_out",out);
    ex.input("input_1_blob", in);
    ex.extract("conv2d_blob",out);
    std::string savename="./mbllenout"+std::to_string(frame_id)+".raw";
    FILE* fncnn=fopen(savename.c_str(),"wb");
    fwrite(out.data,sizeof(float),in.h*in.c*in.w,fncnn);
    fclose(fncnn);

    printf("out mat %f %f",out[0],out[256*256]);
    printf("\nout size:%d,%d,%d\n", out.w, out.h, out.c);
}

用最新的ncnn版本试试,没发现你说的问题。

Sherlock-hh commented 1 year ago

输入也提供一下?

啊啊啊有人理我了这里这里,keras ncnn模型和输入图片都在这里。 这里是测试第一层卷积“conv2d_blob”的输出,测试代码是在mobilnet的demo上面改出来的:

cv::Rect test_mbllen(cv::Mat& raw_img, float threshold)
{
#if NCNN_VULKAN
    mobilenet.opt.use_vulkan_compute = true;
#endif // NCNN_VULKAN

    cv::Rect ret(0, 0, 0, 0);
    std::vector<cv::Rect> object_rects;

    int img_h = raw_img.size().height;
    int img_w = raw_img.size().width;
    int input_size_w = 256;// = 300;
    int input_size_h = 256;// = 300;
    ncnn::Mat in = ncnn::Mat::from_pixels_resize(raw_img.data, ncnn::Mat::PIXEL_BGR, raw_img.cols, raw_img.rows, input_size_w, input_size_h);

    printf("in mat %f %f",in[0],in[1]);
    ncnn::Mat out;
    const float mean_vals[3] = {0.0f, 0.0f, 0.0f};
    const float norm_vals[3] = {1.0/255.0,1.0/255.0,1.0/255.0};

    in.substract_mean_normalize(mean_vals, norm_vals);
    std::string savenamein="./mbllenin"+std::to_string(frame_id)+".raw";
    FILE* fncnnin=fopen(savenamein.c_str(),"wb");
    fwrite(in.data,sizeof(float),in.h*in.c*in.w,fncnnin);
    fclose(fncnnin);
    ncnn::Extractor ex = mobilenet.create_extractor();
    //ex.set_light_mode(true);
    ex.set_num_threads(4);
    //ex.input("data", in);
    //ex.extract("detection_out",out);
    ex.input("input_1_blob", in);
    ex.extract("conv2d_blob",out);
    std::string savename="./mbllenout"+std::to_string(frame_id)+".raw";
    FILE* fncnn=fopen(savename.c_str(),"wb");
    fwrite(out.data,sizeof(float),in.h*in.c*in.w,fncnn);
    fclose(fncnn);

    printf("out mat %f %f",out[0],out[256*256]);
    printf("\nout size:%d,%d,%d\n", out.w, out.h, out.c);
}

用最新的ncnn版本试试,没发现你说的问题。 感谢回复,我试过了,确实新版本没有问题,唯一的问题就是倒霉的点就是旧工程用的全是2018版本,这些都得重新编和换了OTZ。