欢迎分享,转载请注明来源:内存溢出
一般都是在py环境下训练,并且把weights和net都保存到一个protobuf的graph里脊尘闹,c++可以new个session,readbinaryProto,再session->create一下py当时的graph就恢复了,然后一样是session->run,feed数据,fetch拿到结果,tf使用bazel编译的,那堆工具链老复杂樱罩了,兄胡慢慢研究吧Caffe是目前深度学习比较优秀好用的一个开源库,采样c++和CUDA实现,具有速度快,模型燃慎定义方便等优点。学习了几天过后,发现也有一个不方便的地方,就是在我的程序中调用Caffe做图像分类没有直接的接口。Caffe的数据层可以从数据库(支持leveldb、lmdb、hdf5)、图片、和内存中读入。我们要在程序中使禅运用,当然得从内存中读入,我们首先在模型定义文件中定义数据层:layers { name: "mydata" type: MEMORY_DATA top: "data" top: "label" transform_param { scale: 0.00390625 } memory_data_param { batch_size: 10 channels: 1 height: 24 width: 24 }}这里必须设置memory_data_param中的四个参数,对应这些参数可以参见源码中caffe.proto文件。现在,我们可以设计一个Classifier类来封装一下:#ifndef CAFFE_CLASSIFIER_H#define CAFFE_CLASSIFIER_H#include #include #include "caffe/net.hpp"#include "caffe/data_layers.hpp"#include using cv::Matnamespace caffe {template class Classifier {public: explicit Classifier(const string&param_file, const string&weights_file)Dtype test(vector &images, vector &labels, int iter_num)virtual ~Classifier() {} inline shared_ptr net() { return net_} void predict(vector &images, vector *labels)void predict(vector &data, vector *labels, int num)void extract_feature(vector &images, vector *out)protected: shared_ptr net_MemoryDataLayer *m_layer_int batch_size_int channels_int height_int width_DISABLE_COPY_AND_ASSIGN(Classifier)}}//namespace #endif //CAFFE_CLASSIFIER_H构造函数中我们通过模型定义文件(.prototxt)和训练好的模型(.caffemodel)文件构造一个Net对象,并用m_layer_指向Net中的memory data层,以便待会调用MemoryDataLayer中AddMatVector和Reset函数加入数据。#include #include #include #include #include "caffe/net.hpp"#include "caffe/proto/caffe.pb.h"#include "caffe/util/io.hpp"#include "caffe/util/math_functions.hpp"#include "caffe/util/upgrade_proto.hpp"贺段梁#include "caffe_classifier.h"namespace caffe {template Classifier::Classifier(const string&param_file, const string&weights_file) : net_(){ net_.reset(new Net(param_file, TEST))net_->CopyTrainedLayersFrom(weights_file)//m_layer_ = (MemoryDataLayer*)net_->layer_by_name("mnist").get()m_layer_ = (MemoryDataLayer*)net_->layers()[0].get()batch_size_ = m_layer_->batch_size()channels_ = m_layer_->channels()height_ = m_layer_->height()width_ = m_layer_->width()}template Dtype Classifier::test(vector &images, vector &labels, int iter_num){ m_layer_->AddMatVector(images, labels) // int iterations = iter_num vector bottom_vecvector test_score_output_idvector test_scoreDtype loss = 0for (int i = 0i &result = net_->Forward(bottom_vec, &iter_loss) loss += iter_loss int idx = 0 for (int j = 0j cpu_data()for (int k = 0k count()++k, ++idx) { const Dtype score = result_vec[k] if (i == 0) { test_score.push_back(score)test_score_output_id.push_back(j) } else { test_score[idx] += score } const std::string&output_name = net_->blob_names()[ net_->output_blob_indices()[j]] LOG(INFO) void Classifier::predict(vector &images, vector *labels){ int original_length = images.size() if(original_length == 0) return int valid_length = original_length / batch_size_ * batch_size_ if(original_length != valid_length) { valid_length += batch_size_ for(int i = original_lengthi valid_labels, predicted_labels valid_labels.resize(valid_length, 0) m_layer_->AddMatVector(images, valid_labels) vector bottom_vec for(int i = 0i &result = net_->Forward(bottom_vec) const Dtype * result_vec = result[1]->cpu_data() for(int j = 0j count()j++) { predicted_labels.push_back(result_vec[j]) } } if(original_length != valid_length) { images.erase(images.begin()+original_length, images.end()) } labels->resize(original_length, 0) std::copy(predicted_labels.begin(), predicted_labels.begin() + original_length, labels->begin())}template void Classifier::predict(vector &data, vector *labels, int num){ int size = channels_*height_*width_ CHECK_EQ(data.size(), num*size) int original_length = num if(original_length == 0) return int valid_length = original_length / batch_size_ * batch_size_ if(original_length != valid_length) { valid_length += batch_size_ for(int i = original_lengthi predicted_labels Dtype * label_ = new Dtype[valid_length] memset(label_, 0, valid_length) m_layer_->Reset(data.data(), label_, valid_length) vector bottom_vec for(int i = 0i &result = net_->Forward(bottom_vec) const Dtype * result_vec = result[1]->cpu_data() for(int j = 0j count()j++) { predicted_labels.push_back(result_vec[j]) } } if(original_length != valid_length) { data.erase(data.begin()+original_length*size, data.end()) } delete [] label_ labels->resize(original_length, 0) std::copy(predicted_labels.begin(), predicted_labels.begin() + original_length, labels->begin())}template void Classifier::extract_feature(vector &images, vector *out){ int original_length = images.size() if(original_length == 0) return int valid_length = original_length / batch_size_ * batch_size_ if(original_length != valid_length) { valid_length += batch_size_ for(int i = original_lengthi valid_labels valid_labels.resize(valid_length, 0) m_layer_->AddMatVector(images, valid_labels) vector bottom_vec out->clear() for(int i = 0i &result = net_->Forward(bottom_vec) const Dtype * result_vec = result[0]->cpu_data() const int dim = result[0]->count(1) for(int j = 0j num()j++) { const Dtype * ptr = result_vec + j * dim vector one_ for(int k = 0k push_back(one_) } } if(original_length != valid_length) { images.erase(images.begin()+original_length, images.end()) out->erase(out->begin()+original_length, out->end()) }}INSTANTIATE_CLASS(Classifier)} // namespace caffe由于加入的数据个数必须是batch_size的整数倍,所以我们在加入数据时采用填充的方式。CHECK_EQ(num % batch_size_, 0) <<"The added data must be a multiple of the batch size." //AddMatVector在模型文件的最后,我们把训练时的loss层改为argmax层:layers { name: "predicted" type: ARGMAX bottom: "prob" top: "predicted"}
赞
(0)
打赏
微信扫一扫
支付宝扫一扫
西安市招投标gzb是什么意思?
上一篇
2023-05-24
苹果电脑装系统后驱动用不了怎么办
下一篇
2023-05-24
评论列表(0条)