版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_14845119/article/details/74931602

caffe模型在训练完成后,会生成一个*.caffemodel的文件,在运行的时候,直接调用caffe就可以读取其中的相应权值参数。但是如果用一个第三方软件打开这个,却是不可以可视化的二值乱码。

将模型中的参数导出,可编辑化后能有哪些好处呢,

(1)方便进行fpga平台的移植

(2)可以基于别人训练好的模型,0数据训练自己的模型,使用自己的模型拟合别人模型的权值分布,达到用模型训模型的目的。

(3)可以对网络进行剪支,加速等操作。

将模型中的特征图和权值可视化有哪些好处呢,

(1)方便对卷积网络的特征有所了解,训练好的特征总是有规则的特征图,可以侧面辅助训练过程。

这里分析lenet5这样的网络结构,所有其他网络都通用。

核心程序:

(1)只导出weights,不进行显示

  1. void parse_caffemodel(string caffemodel, string outtxt)

  2. {

  3. printf("%s\n", caffemodel.c_str());

  4. NetParameter net;

  5. bool success = loadCaffemodel(caffemodel.c_str(), &net);

  6. if (!success){

  7. printf("读取错误啦:%s\n", caffemodel.c_str());

  8. return;

  9. }

  10. FILE* fmodel = fopen(outtxt.c_str(), "wb");

  11. for (int i = 0; i < net.layer_size(); ++i){

  12. LayerParameter& param = *net.mutable_layer(i);

  13. int n = param.mutable_blobs()->size();

  14. if (n){

  15. const BlobProto& blob = param.blobs(0);

  16. printf("layer: %s weight(%d)", param.name().c_str(), blob.data_size());

  17. fprintf(fmodel, "\nlayer: %s weight(%d)\n", param.name().c_str(), blob.data_size());

  18. writeData(fmodel, blob.data().data(), blob.data_size());

  19. if (n > 1){

  20. const BlobProto& bais = param.blobs(1);

  21. printf(" bais(%d)", bais.data_size());

  22. fprintf(fmodel, "\nlayer: %s bais(%d)\n", param.name().c_str(), bais.data_size());

  23. writeData(fmodel, bais.data().data(), bais.data_size());

  24. }

  25. printf("\n");

  26. }

  27. }

  28. fclose(fmodel);

  29. }

(2)weights可视化

  1. cv::Mat visualize_weights(string prototxt, string caffemodel, int weights_layer_num)

  2. {

  3. ::google::InitGoogleLogging("0");

  4. #ifdef CPU_ONLY

  5. Caffe::set_mode(Caffe::CPU);

  6. #else

  7. Caffe::set_mode(Caffe::GPU);

  8. #endif

  9. Net<float> net(prototxt, TEST);

  10. net.CopyTrainedLayersFrom(caffemodel);

  11. vector<shared_ptr<Blob<float> > > params = net.params();

  12. std::cout << "各层参数的维度信息为:\n";

  13. for (int i = 0; i<params.size(); ++i)

  14. std::cout << params[i]->shape_string() << std::endl;

  15. int width = params[weights_layer_num]->shape(3); //宽度

  16. int height = params[weights_layer_num]->shape(2); //高度

  17. int channel = params[weights_layer_num]->shape(1); //通道数

  18. int num = params[weights_layer_num]->shape(0); //个数

  19. int imgHeight = (int)(1 + sqrt(num))*height;

  20. int imgWidth = (int)(1 + sqrt(num))*width;

  21. Mat img(imgHeight, imgWidth, CV_8UC3, Scalar(0, 0, 0));

  22. float maxValue = -1000, minValue = 10000;

  23. const float* tmpValue = params[weights_layer_num]->cpu_data();

  24. for (int i = 0; i<params[weights_layer_num]->count(); i++){

  25. maxValue = std::max(maxValue, tmpValue[i]);

  26. minValue = std::min(minValue, tmpValue[i]);

  27. }

  28. int kk = 0;

  29. for (int y = 0; y<imgHeight; y += height){

  30. for (int x = 0; x<imgWidth; x += width){

  31. if (kk >= num)

  32. continue;

  33. Mat roi = img(Rect(x, y, width, height));

  34. for (int i = 0; i<height; i++){

  35. for (int j = 0; j<width; j++){

  36. for (int k = 0; k<channel; k++){

  37. float value = params[weights_layer_num]->data_at(kk, k, i, j);

  38. roi.at<Vec3b>(i, j)[k] = (value - minValue) / (maxValue - minValue) * 255; }

  39. }

  40. }

  41. ++kk;

  42. }

  43. }

  44. return img;

  45. }

(3)featuremap可视化

  1. cv::Mat Classifier::visualize_featuremap(const cv::Mat& img,string layer_name)

  2. {

  3. Blob<float>* input_layer = net_->input_blobs()[0];

  4. input_layer->Reshape(1, num_channels_, input_geometry_.height, input_geometry_.width);

  5. net_->Reshape();

  6. std::vector<cv::Mat> input_channels;

  7. WrapInputLayer(&input_channels);

  8. Preprocess(img, &input_channels);

  9. net_->Forward();

  10. std::cout << "网络中的Blobs名称为:\n";

  11. vector<shared_ptr<Blob<float> > > blobs = net_->blobs();

  12. vector<string> blob_names = net_->blob_names();

  13. std::cout << blobs.size() << " " << blob_names.size() << std::endl;

  14. for (int i = 0; i<blobs.size(); i++){

  15. std::cout << blob_names[i] << " " << blobs[i]->shape_string() << std::endl;

  16. }

  17. std::cout << std::endl;

  18. assert(net_->has_blob(layer_name));

  19. shared_ptr<Blob<float> > conv1Blob = net_->blob_by_name(layer_name);

  20. std::cout << "测试图片的特征响应图的形状信息为:" << conv1Blob->shape_string() << std::endl;

  21. float maxValue = -10000000, minValue = 10000000;

  22. const float* tmpValue = conv1Blob->cpu_data();

  23. for (int i = 0; i<conv1Blob->count(); i++){

  24. maxValue = std::max(maxValue, tmpValue[i]);

  25. minValue = std::min(minValue, tmpValue[i]);

  26. }

  27. int width = conv1Blob->shape(3); //响应图的高度

  28. int height = conv1Blob->shape(2); //响应图的宽度

  29. int channel = conv1Blob->shape(1); //通道数

  30. int num = conv1Blob->shape(0); //个数

  31. int imgHeight = (int)(1 + sqrt(channel))*height;

  32. int imgWidth = (int)(1 + sqrt(channel))*width;

  33. cv::Mat img(imgHeight, imgWidth, CV_8UC1, cv::Scalar(0));

  34. int kk = 0;

  35. for (int x = 0; x<imgHeight; x += height){

  36. for (int y = 0; y<imgWidth; y += width){

  37. if (kk >= channel)

  38. continue;

  39. cv::Mat roi = img(cv::Rect(y, x, width, height));

  40. for (int i = 0; i<height; i++){

  41. for (int j = 0; j<width; j++){

  42. float value = conv1Blob->data_at(0, kk, i, j);

  43. roi.at<uchar>(i, j) = (value - minValue) / (maxValue - minValue) * 255;

  44. }

  45. }

  46. kk++;

  47. }

  48. }

  49. return img;

  50. }

运行结果:

(1)

  1. string caffemodel = "lenet_iter_10000.caffemodel";;

  2. string outtxt = "lenet.txt";

  3. parse_caffemodel(caffemodel, outtxt);

(2)

  1. string prototxt = "lenet.prototxt";

  2. string caffemodel = "lenet_iter_10000.caffemodel";

  3. int weights_layer_num = 0;

  4. Mat image=visualize_weights(prototxt, caffemodel, weights_layer_num);

  5. imshow("weights", image);

  6. waitKey(0);

(3)

  1. ::google::InitGoogleLogging(argv[0]);

  2. string model_file = "lenet.prototxt";

  3. string trained_file = "lenet_iter_10000.caffemodel";

  4. Classifier classifier(model_file, trained_file);

  5. string file = "5.jpg";

  6. cv::Mat img = cv::imread(file, -1);

  7. CHECK(!img.empty()) << "Unable to decode image " << file;

  8. cv::Mat feature_map = classifier.visualize_featuremap(img,"conv2");

  9. imshow("feature_map", feature_map);

  10. cv::waitKey(0);

将权值导入matlab中,可以看到权值基本都是服从均值为0,方差很小的分布。

完整程序下载链接:http://download.csdn.net/detail/qq_14845119/9895412

caffe模型weightsfeatureMap 可视化(c++)相关推荐

  1. 使用netron对TensorFlow、Pytorch、Keras、PaddlePaddle、MXNet、Caffe、ONNX、UFF、TNN、ncnn、OpenVINO等模型的可视化

    欢迎大家关注笔者,你的关注是我持续更博的最大动力 原创文章,转载告知,盗版必究 使用netron对TensorFlow.Pytorch.Keras.PaddlePaddle.MXNet.Caffe.O ...

  2. 可视化caffe模型结构及在线可视化

    在线可视化caffe模型结构 http://ethereon.github.io/netscope/#/editor 假设Caffe的目录是$(CAFFE_ROOT) 1.编译caffe的python ...

  3. caffe模型文件解析_「机器学习」截取caffe模型中的某层

    通常情况下,训练好的caffe模型包含两个文件: prototxt:网络结构描述文件,存储了整个网络的图结构: caffemodel:权重文件,存储了模型权重的相关参数和具体信息 对于某些大型的网络, ...

  4. 【超详细】MMLab分类任务mmclassification:环境配置说明、训练、预测及模型结果可视化展示

    本文详细介绍了使用MMLab的mmclassification进行分类任务的环境配置.训练与预测流程. 目录 文件配置说明 下载源码 配置文件 基于预训练模型微调或者续训练自己模型的方式 配置文件说明 ...

  5. python使用matplotlib对比多个模型在测试集上的效果并可视化、设置模型性能可视化结果柱状图(bar plot)标签的小数点位数(例如,强制柱状图标签0.7显示为两位小数0.70)

    python使用matplotlib对比多个模型在测试集上的效果并可视化.设置模型性能可视化结果柱状图(bar plot)标签的小数点位数(例如,强制柱状图标签0.7显示为两位小数0.70) 目录

  6. 为多模型寻找模型最优参数、多模型交叉验证、可视化、指标计算、多模型对比可视化(系数图、误差图、混淆矩阵、校正曲线、ROC曲线、AUC、Accuracy、特异度、灵敏度、PPV、NPV)、结果数据保存

    使用randomsearchcv为多个模型寻找模型最优参数.多模型交叉验证.可视化.指标计算.多模型对比可视化(系数图.误差图.classification_report.混淆矩阵.校正曲线.ROC曲 ...

  7. R语言构建文本分类模型:文本数据预处理、构建词袋模型(bag of words)、构建xgboost文本分类模型、xgboost模型预测推理并使用混淆矩阵评估模型、可视化模型预测的概率分布

    R语言构建文本分类模型:文本数据预处理.构建词袋模型(bag of words).构建xgboost文本分类模型.xgboost模型预测推理并使用混淆矩阵评估模型.可视化模型预测的概率分布 目录

  8. R语言基于glmnet构建分类模型并可视化特征系数(coefficient)以及L1正则化系数(lambda)实战

    R语言基于glmnet构建分类模型并可视化特征系数(coefficient)以及L1正则化系数(lambda)实战 # 导入测试数据集 data(BinomialExample) x <- Bi ...

  9. sklearn RandomForest(随机森林)模型使用RandomSearchCV获取最优参数及模型效能可视化

    sklearn RandomForest(随机森林)模型使用RandomSearchCV获取最优参数及模型效能可视化 随机森林顾名思义,是用随机的方式建立一个森林,森林里面有很多的决策树组成,随机森林 ...

最新文章

  1. arthas-boot.jar 工具的简单使用
  2. JS难点剖析-原型原型链
  3. php html 转xml,用PHP生成XML文档(转义字符)
  4. P5305-[GXOI/GZOI2019]旧词【树链剖分,线段树】
  5. PHPcms框架的Webshell
  6. windows 下查看进程占用
  7. 机器人的动力学有什么用呢?
  8. C++连接MySQL(Windows)
  9. 3.2.1 封装成帧、帧定界、帧同步、透明传输(字符计数法、字符串的首尾填充法、零比特填充的首尾标志法、违规编码法)(转载)
  10. Bootcamp Mac 安装Win10 教程
  11. php模拟登录其他网站,PHP利用Curl模拟登录并获取数据例子
  12. linux安装Drcom客户端,Ubuntu 10.10校园网安装宽带认证客户端Drcom联网
  13. Python贴吧小爬虫
  14. 趣头条面试题:ThreadLocal是什么?怎么用?为什么用它?有什么缺点
  15. 光耦重要参数与常用设计注意事项
  16. 万云网实名认证不成功_头条发文章显示实名认证接口调用失败,无法发送,怎么办才能解决?我实名了的?...
  17. [Android]自己动手做个拼图游戏
  18. Bilibili到底有多少御坂妹?(一)
  19. 时间序列差分后去除空值
  20. 实用指南:如何在Anolis OS上轻松使用 Kata 安全容器?

热门文章

  1. boost::serialization模块实现快速二进制归档的测试程序
  2. boost::mp11::mp_replace_front相关用法的测试程序
  3. boost::mp11::integer_sequence相关用法的测试程序
  4. boost::high_bit_mask_t和boost::low_bits_mask_t用法的测试程序
  5. boost::fusion::result_of::empty用法的测试程序
  6. boost::coroutine模块实现parallel的测试程序
  7. Boost:测试BOOST_BIND_NO_PLACEHOLDERS的程序
  8. ITK:二进制和两个图像
  9. VTK:PolyData之TriangleArea
  10. OpenCV转换PyTorch分类模型并使用OpenCV Python启动