caffe源码学习之Proto数据格式【1】
前言:
由于业务需要,接触caffe已经有接近半年,一直忙着阅读各种论文,重现大大小小的模型. 期间也总结过一些caffe源码学习笔记,断断续续,这次打算系统的记录一下caffe源码学习笔记,巩固一下C++,同时也梳理一下自己之前的理解。
正文:
我们先不看caffe的框架结构,先介绍一下caffe.proto,是google开源的一种数据交互格式--Google Protobuf,这种数据的格式,我们可以看到caffe.proto中内容:
syntax = "proto2"; package caffe; //caffe.prto中的各个结构封装在caffe包中,可以通过using namespace caffe; 或者caffe::** 调用 // Specifies the shape (dimensions) of a Blob.
message BlobShape {
repeated int64 dim = [packed = true];
} message BlobProto {
optional BlobShape shape = ;
repeated float data = [packed = true];
repeated float diff = [packed = true];
repeated double double_data = [packed = true];
repeated double double_diff = [packed = true]; // 4D dimensions -- deprecated. Use "shape" instead.
optional int32 num = [default = ];
optional int32 channels = [default = ];
optional int32 height = [default = ];
optional int32 width = [default = ];
} .......
当我们在编译完成caffe之后,会自动在src/caffe/proto中生成两个文件caffe.pb.h 和caffe.pb.cc
那么这种数据格式在程序中是如何被使用的呢? 我们举一个简单的例子,来演示caffe.proto生成caffe.pb.h和caffe.pb.cc以及被调用的过程
如果你之前能够编译caffe成功,则说明你已经成功安装了Protobuf,那么我简单的编写一个使用Protobuf的例子吧.
我们先编写一个文件caffe.proto:
package caffe;
message student
{
required int32 age = ; //ID required 表示必要字段
required string name = ; //str 必要字段
optional int32 grade = ; //optional field 可选字段,可以有无,最多b
}
然后我们执行如下操作。
protoc -I=. --cpp_out=. ./caffe.proto
protobuf会自动生成.cc和.h文件
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: caffe.proto #ifndef PROTOBUF_caffe_2eproto__INCLUDED
#define PROTOBUF_caffe_2eproto__INCLUDED #include <string> #include <google/protobuf/stubs/common.h> #if GOOGLE_PROTOBUF_VERSION < 2005000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 2005000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.
#endif #include <google/protobuf/generated_message_util.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/unknown_field_set.h>
// @@protoc_insertion_point(includes) namespace caffe { // Internal implementation detail -- do not call these.
void protobuf_AddDesc_caffe_2eproto();
void protobuf_AssignDesc_caffe_2eproto();
void protobuf_ShutdownFile_caffe_2eproto(); class student; // =================================================================== class student : public ::google::protobuf::Message {
public:
student();
virtual ~student(); student(const student& from); inline student& operator=(const student& from) {
CopyFrom(from);
return *this;
} inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
} inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
} static const ::google::protobuf::Descriptor* descriptor();
static const student& default_instance(); void Swap(student* other); // implements Message ---------------------------------------------- student* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const student& from);
void MergeFrom(const student& from);
void Clear();
bool IsInitialized() const; int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
public: ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- // required int32 age = 1;
inline bool has_age() const;
inline void clear_age();
static const int kAgeFieldNumber = ;
inline ::google::protobuf::int32 age() const;
inline void set_age(::google::protobuf::int32 value); // required string name = 2;
inline bool has_name() const;
inline void clear_name();
static const int kNameFieldNumber = ;
inline const ::std::string& name() const;
inline void set_name(const ::std::string& value);
inline void set_name(const char* value);
inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name); // optional int32 grade = 3;
inline bool has_grade() const;
inline void clear_grade();
static const int kGradeFieldNumber = ;
inline ::google::protobuf::int32 grade() const;
inline void set_grade(::google::protobuf::int32 value); // @@protoc_insertion_point(class_scope:caffe.student)
private:
inline void set_has_age();
inline void clear_has_age();
inline void set_has_name();
inline void clear_has_name();
inline void set_has_grade();
inline void clear_has_grade(); ::google::protobuf::UnknownFieldSet _unknown_fields_; ::std::string* name_;
::google::protobuf::int32 age_;
::google::protobuf::int32 grade_; mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[( + ) / ]; friend void protobuf_AddDesc_caffe_2eproto();
friend void protobuf_AssignDesc_caffe_2eproto();
friend void protobuf_ShutdownFile_caffe_2eproto(); void InitAsDefaultInstance();
static student* default_instance_;
};
// =================================================================== // =================================================================== // student // required int32 age = 1;
inline bool student::has_age() const {
return (_has_bits_[] & 0x00000001u) != ;
}
inline void student::set_has_age() {
_has_bits_[] |= 0x00000001u;
}
inline void student::clear_has_age() {
_has_bits_[] &= ~0x00000001u;
}
inline void student::clear_age() {
age_ = ;
clear_has_age();
}
inline ::google::protobuf::int32 student::age() const {
return age_;
}
inline void student::set_age(::google::protobuf::int32 value) {
set_has_age();
age_ = value;
} // required string name = 2;
inline bool student::has_name() const {
return (_has_bits_[] & 0x00000002u) != ;
}
inline void student::set_has_name() {
_has_bits_[] |= 0x00000002u;
}
inline void student::clear_has_name() {
_has_bits_[] &= ~0x00000002u;
}
inline void student::clear_name() {
if (name_ != &::google::protobuf::internal::kEmptyString) {
name_->clear();
}
clear_has_name();
}
inline const ::std::string& student::name() const {
return *name_;
}
inline void student::set_name(const ::std::string& value) {
set_has_name();
if (name_ == &::google::protobuf::internal::kEmptyString) {
name_ = new ::std::string;
}
name_->assign(value);
}
inline void student::set_name(const char* value) {
set_has_name();
if (name_ == &::google::protobuf::internal::kEmptyString) {
name_ = new ::std::string;
}
name_->assign(value);
}
inline void student::set_name(const char* value, size_t size) {
set_has_name();
if (name_ == &::google::protobuf::internal::kEmptyString) {
name_ = new ::std::string;
}
name_->assign(reinterpret_cast<const char*>(value), size);
}
inline ::std::string* student::mutable_name() {
set_has_name();
if (name_ == &::google::protobuf::internal::kEmptyString) {
name_ = new ::std::string;
}
return name_;
}
inline ::std::string* student::release_name() {
clear_has_name();
if (name_ == &::google::protobuf::internal::kEmptyString) {
return NULL;
} else {
::std::string* temp = name_;
name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
return temp;
}
}
inline void student::set_allocated_name(::std::string* name) {
if (name_ != &::google::protobuf::internal::kEmptyString) {
delete name_;
}
if (name) {
set_has_name();
name_ = name;
} else {
clear_has_name();
name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
}
} // optional int32 grade = 3;
inline bool student::has_grade() const {
return (_has_bits_[] & 0x00000004u) != ;
}
inline void student::set_has_grade() {
_has_bits_[] |= 0x00000004u;
}
inline void student::clear_has_grade() {
_has_bits_[] &= ~0x00000004u;
}
inline void student::clear_grade() {
grade_ = ;
clear_has_grade();
}
inline ::google::protobuf::int32 student::grade() const {
return grade_;
}
inline void student::set_grade(::google::protobuf::int32 value) {
set_has_grade();
grade_ = value;
} // @@protoc_insertion_point(namespace_scope) } // namespace caffe #ifndef SWIG
namespace google {
namespace protobuf { } // namespace google
} // namespace protobuf
#endif // SWIG // @@protoc_insertion_point(global_scope) #endif // PROTOBUF_caffe_2eproto__INCLUDED
caffe.pb.h
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: caffe.proto #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
#include "caffe.pb.h" #include <algorithm> #include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
// @@protoc_insertion_point(includes) namespace caffe { namespace { const ::google::protobuf::Descriptor* student_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
student_reflection_ = NULL; } // namespace void protobuf_AssignDesc_caffe_2eproto() {
protobuf_AddDesc_caffe_2eproto();
const ::google::protobuf::FileDescriptor* file =
::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
"caffe.proto");
GOOGLE_CHECK(file != NULL);
student_descriptor_ = file->message_type();
static const int student_offsets_[] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(student, age_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(student, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(student, grade_),
};
student_reflection_ =
new ::google::protobuf::internal::GeneratedMessageReflection(
student_descriptor_,
student::default_instance_,
student_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(student, _has_bits_[]),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(student, _unknown_fields_),
-,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
sizeof(student));
} namespace { GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
inline void protobuf_AssignDescriptorsOnce() {
::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
&protobuf_AssignDesc_caffe_2eproto);
} void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
student_descriptor_, &student::default_instance());
} } // namespace void protobuf_ShutdownFile_caffe_2eproto() {
delete student::default_instance_;
delete student_reflection_;
} void protobuf_AddDesc_caffe_2eproto() {
static bool already_here = false;
if (already_here) return;
already_here = true;
GOOGLE_PROTOBUF_VERIFY_VERSION; ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n\013caffe.proto\022\005caffe\"3\n\007student\022\013\n\003age\030\001"
" \002(\005\022\014\n\004name\030\002 \002(\t\022\r\n\005grade\030\003 \001(\005", );
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"caffe.proto", &protobuf_RegisterTypes);
student::default_instance_ = new student();
student::default_instance_->InitAsDefaultInstance();
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_caffe_2eproto);
} // Force AddDescriptors() to be called at static initialization time.
struct StaticDescriptorInitializer_caffe_2eproto {
StaticDescriptorInitializer_caffe_2eproto() {
protobuf_AddDesc_caffe_2eproto();
}
} static_descriptor_initializer_caffe_2eproto_; // =================================================================== #ifndef _MSC_VER
const int student::kAgeFieldNumber;
const int student::kNameFieldNumber;
const int student::kGradeFieldNumber;
#endif // !_MSC_VER student::student()
: ::google::protobuf::Message() {
SharedCtor();
} void student::InitAsDefaultInstance() {
} student::student(const student& from)
: ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
} void student::SharedCtor() {
_cached_size_ = ;
age_ = ;
name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
grade_ = ;
::memset(_has_bits_, , sizeof(_has_bits_));
} student::~student() {
SharedDtor();
} void student::SharedDtor() {
if (name_ != &::google::protobuf::internal::kEmptyString) {
delete name_;
}
if (this != default_instance_) {
}
} void student::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* student::descriptor() {
protobuf_AssignDescriptorsOnce();
return student_descriptor_;
} const student& student::default_instance() {
if (default_instance_ == NULL) protobuf_AddDesc_caffe_2eproto();
return *default_instance_;
} student* student::default_instance_ = NULL; student* student::New() const {
return new student;
} void student::Clear() {
if (_has_bits_[ / ] & (0xffu << ( % ))) {
age_ = ;
if (has_name()) {
if (name_ != &::google::protobuf::internal::kEmptyString) {
name_->clear();
}
}
grade_ = ;
}
::memset(_has_bits_, , sizeof(_has_bits_));
mutable_unknown_fields()->Clear();
} bool student::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
::google::protobuf::uint32 tag;
while ((tag = input->ReadTag()) != ) {
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// required int32 age = 1;
case : {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
input, &age_)));
set_has_age();
} else {
goto handle_uninterpreted;
}
if (input->ExpectTag()) goto parse_name;
break;
} // required string name = 2;
case : {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
parse_name:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_name()));
::google::protobuf::internal::WireFormat::VerifyUTF8String(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::PARSE);
} else {
goto handle_uninterpreted;
}
if (input->ExpectTag()) goto parse_grade;
break;
} // optional int32 grade = 3;
case : {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
parse_grade:
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
input, &grade_)));
set_has_grade();
} else {
goto handle_uninterpreted;
}
if (input->ExpectAtEnd()) return true;
break;
} default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
DO_(::google::protobuf::internal::WireFormat::SkipField(
input, tag, mutable_unknown_fields()));
break;
}
}
}
return true;
#undef DO_
} void student::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
// required int32 age = 1;
if (has_age()) {
::google::protobuf::internal::WireFormatLite::WriteInt32(, this->age(), output);
} // required string name = 2;
if (has_name()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE);
::google::protobuf::internal::WireFormatLite::WriteString(
, this->name(), output);
} // optional int32 grade = 3;
if (has_grade()) {
::google::protobuf::internal::WireFormatLite::WriteInt32(, this->grade(), output);
} if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
} ::google::protobuf::uint8* student::SerializeWithCachedSizesToArray(
::google::protobuf::uint8* target) const {
// required int32 age = 1;
if (has_age()) {
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(, this->age(), target);
} // required string name = 2;
if (has_name()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE);
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
, this->name(), target);
} // optional int32 grade = 3;
if (has_grade()) {
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(, this->grade(), target);
} if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
return target;
} int student::ByteSize() const {
int total_size = ; if (_has_bits_[ / ] & (0xffu << ( % ))) {
// required int32 age = 1;
if (has_age()) {
total_size += +
::google::protobuf::internal::WireFormatLite::Int32Size(
this->age());
} // required string name = 2;
if (has_name()) {
total_size += +
::google::protobuf::internal::WireFormatLite::StringSize(
this->name());
} // optional int32 grade = 3;
if (has_grade()) {
total_size += +
::google::protobuf::internal::WireFormatLite::Int32Size(
this->grade());
} }
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
} void student::MergeFrom(const ::google::protobuf::Message& from) {
GOOGLE_CHECK_NE(&from, this);
const student* source =
::google::protobuf::internal::dynamic_cast_if_available<const student*>(
&from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
MergeFrom(*source);
}
} void student::MergeFrom(const student& from) {
GOOGLE_CHECK_NE(&from, this);
if (from._has_bits_[ / ] & (0xffu << ( % ))) {
if (from.has_age()) {
set_age(from.age());
}
if (from.has_name()) {
set_name(from.name());
}
if (from.has_grade()) {
set_grade(from.grade());
}
}
mutable_unknown_fields()->MergeFrom(from.unknown_fields());
} void student::CopyFrom(const ::google::protobuf::Message& from) {
if (&from == this) return;
Clear();
MergeFrom(from);
} void student::CopyFrom(const student& from) {
if (&from == this) return;
Clear();
MergeFrom(from);
} bool student::IsInitialized() const {
if ((_has_bits_[] & 0x00000003) != 0x00000003) return false; return true;
} void student::Swap(student* other) {
if (other != this) {
std::swap(age_, other->age_);
std::swap(name_, other->name_);
std::swap(grade_, other->grade_);
std::swap(_has_bits_[], other->_has_bits_[]);
_unknown_fields_.Swap(&other->_unknown_fields_);
std::swap(_cached_size_, other->_cached_size_);
}
} ::google::protobuf::Metadata student::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
::google::protobuf::Metadata metadata;
metadata.descriptor = student_descriptor_;
metadata.reflection = student_reflection_;
return metadata;
} // @@protoc_insertion_point(namespace_scope) } // namespace caffe // @@protoc_insertion_point(global_scope)
caffe.pb.cc
生成之后,我们编写一个读取文件caffeReader.cpp
#include "caffe.pb.h"
#include<iostream>
#include<ios> using namespace std; void InfoStudents(const caffe::student & stu){
cout<< "student info:"<<endl;
cout<<"name: "<<stu.name()<<endl;
cout<<"age: "<<stu.age()<<endl;
cout<<"grade: "<<stu.grade()<<endl;
} int main(void)
{
caffe::student stu;
stu.set_age();
stu.set_name("gongxijun");
stu.set_grade();
InfoStudents(stu);
return ;
}
编译完成之后,我们执行如下命令:
g++ caffeRead.cpp -o caffeReader caffe.pb.cc -I /usr/local/protobuf/include -L /usr/local/protobuf/lib -lprotobuf -pthread
生成二进制执行文件caffeReader.我们运行该文件就会显示如下信息:
知道了proto文件是如何使用之,再去caffe.proto中看看caffe中定义的结构体:
message 表示需要传输的的参数的结构体.
caffe.proto中保存的有二进制大文件Blob的结构信息:BlobProto, BlobProtoVector, Datum
BlobProto:
// Specifies the shape (dimensions) of a Blob.
//用来表示图片的shape
message BlobShape {
repeated int64 dim = [packed = true];
} message BlobProto {
optional BlobShape shape = ; //现在用来替换下面的num,channels ,height,width,推荐使用
repeated float data = [packed = true]; //forward计算数据
repeated float diff = [packed = true]; //backward的残差数据
repeated double double_data = [packed = true]; //双精度forward计算数据
repeated double double_diff = [packed = true]; //双精度backward的残差数据 // 4D dimensions -- deprecated. Use "shape" instead.
optional int32 num = [default = ]; // 图片个数or 维度
optional int32 channels = [default = ]; //通过比如rgb便是3维
optional int32 height = [default = ]; //图片高度
optional int32 width = [default = ]; //图片宽度
}
BlobProtoVector:BlobProto的动态数组
message BlobProtoVector {
repeated BlobProto blobs = ;
}
Datum是lmdb的数据格式,详情可以看这里 http://blog.csdn.net/u010668907/article/details/51834411
message Datum {//lmdb中的数据格式
optional int32 channels = ;//图片通道数比如rgb的通道数为3
optional int32 height = ;//图片的高度
optional int32 width = ;//图片的宽度
// the actual image data, in bytes
optional bytes data = ;//图片的数据.比如rgb的三维数组格式
optional int32 label = ;//这张图片对应的标签,或者这块图像对应的标签[比如20个分类转换成数字之后对应的[0~19]
// Optionally, the datum could also hold float data.
repeated float float_data = ;//图片的数据,有时候图片在转换过程中会变成浮点型
// If true data contains an encoded image that need to be decoded
optional bool encoded = [default = false];//是否需要解码
}
剩下的大部分都是Layer部分和Net部分和Solver部分的参数,关于Blob和Layer,Net还有Solver这四个部分的关系:
blob作为贯穿整个框架的数据单元,Sovler通过sovler.prototxt【我觉得我可能需要说明一下:.proto和.prototxt的区别吧,这两个都是google protobuff的文件,.proto用来定义结构体参数,.prototxt用来相应的.proto中的结构体的初始化数据】配置初始化Net,然后Net通过调用trainval.prototxt这些参数,来调用对应的Layer,并将数据blob输入到相应的Layer中,Layer来对流入的数据进行计算处理,然后再将计算后的blob数据返回,通过Net流向下一个Layer,每次执行一次,Solver就会计数一次,然后调整learn_rate,descay_weith等权值,参考的是caffe论坛上的这个话题:这里附上链接
http://www.caffecn.cn/?/question/123&sort_key=agree_count&sort=DESC
caffe源码学习之Proto数据格式【1】的更多相关文章
- caffe源码学习
本文转载自:https://buptldy.github.io/2016/10/09/2016-10-09-Caffe_Code/ Caffe简介 Caffe作为一个优秀的深度学习框架网上已经有很多内 ...
- Caffe源码中caffe.proto文件分析
Caffe源码(caffe version:09868ac , date: 2015.08.15)中有一些重要文件,这里介绍下caffe.proto文件. 在src/caffe/proto目录下有一个 ...
- caffe源码阅读
参考网址:https://www.cnblogs.com/louyihang-loves-baiyan/p/5149628.html 1.caffe代码层次熟悉blob,layer,net,solve ...
- Underscore.js 源码学习笔记(下)
上接 Underscore.js 源码学习笔记(上) === 756 行开始 函数部分. var executeBound = function(sourceFunc, boundFunc, cont ...
- vscode下调试caffe源码
caffe目录: ├── build -> .build_release // make生成目录,生成各种可执行bin文件,直接调用入口: ├── cmake ├── CMakeLists.tx ...
- 『TensorFlow』SSD源码学习_其一:论文及开源项目文档介绍
一.论文介绍 读论文系列:Object Detection ECCV2016 SSD 一句话概括:SSD就是关于类别的多尺度RPN网络 基本思路: 基础网络后接多层feature map 多层feat ...
- caffe源码整个训练过程
Caffe源码 Blob protected: shared_ptr<SyncedMemory> data_; shared_ptr<SyncedMemory> diff_; ...
- Caffe源码-几种优化算法
SGD简介 caffe中的SGDSolver类中实现了带动量的梯度下降法,其原理如下,\(lr\)为学习率,\(m\)为动量参数. 计算新的动量:history_data = local_rate * ...
- [阿里DIN] 从论文源码学习 之 embedding层如何自动更新
[阿里DIN] 从论文源码学习 之 embedding层如何自动更新 目录 [阿里DIN] 从论文源码学习 之 embedding层如何自动更新 0x00 摘要 0x01 DIN源码 1.1 问题 1 ...
随机推荐
- Set up HTTP/2 server with Spring Boot 【基于Spring boot搭建http2.0服务器】
1. Server side With spring boot, we can set up a http server easily. Restcontroller make it easier t ...
- HDU4497GCD and LMC最大公约数与最小公倍数
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4497 题目大意: 求gcd(x,y,z)=G且lcm(x,y,z)=L的方法数. 题目分析: 起初这 ...
- [UWP]实用的Shape指南
在UWP UI系统中,使用Shape是绘制2D图形最简单的方式,小到图标,大到图表都用到Shape的派生类,可以说有举足轻重的地位.幸运的是从Silverlight以来Shape基本没有什么大改动,简 ...
- Memcached for windows x64 x32 安装
Memcached for windows 一.安装Memcached 1.下载 Memcached32位:http://s3.amazonaws.com/downloads.northscale.c ...
- winXP/win7/win10系统关闭445端口方法全攻略
近日有多个高校发布了关于连接校园网的电脑大面积中勒索病毒的消息,这种病毒致使许多高校毕业生的毕业论文(设计)被锁.受害机器的磁盘文件会被篡改为相应的后缀,图片.文档.视频.压缩包等各类资料都无法正常打 ...
- 区块链入门(1):搭建(Ubuntu系统)Truffle v3.2.1 开发和测试环境
本文主要讲解ubuntu 16.04下, truffle开发测试环境的搭建. 第一步:安装nodejs 和 npm,有两种比较常见的方法. 方法1:直接在nodejs官网下载nodejs-v6.10 ...
- 深入理解Struts2----类型转换
之前的一系列文章主要介绍了有关Struts2的一些基本用法和部分的简单原理,但是始终没有介绍有关拦截器的相关内容,从本篇开始我们将从另一个角度去深入理解框架的使用,核心还是拦截器,但本篇首先 ...
- 如何显示mnist中的数据(tensroflow)
在使用mnist数据集的时候,一直想看看数据中原来的图片,还有卷积层.池化层中的图片,经过不断的捣鼓,最后终于显示了出来.只看数据集中的图片用如下代码就好了: import tensorflow. ...
- VR全景加盟-了解VR就来全景智慧城市
关于什么是真正的VR说了这么多,面对刚刚起步的VR,如何辨别判断一个真正的VR形式呢.除了我们所说几个参数或者大家关注的眩晕感.临场感,真正的VR究竟带给大家什么样的特性呢?这个就要从VR的本质谈起. ...
- 关于关系型数据库(MySQL)的一些概念
主键:关系型数据库中的一条记录中有若干个属性,若其中某一个属性组(注意是组)能唯一标识一条记录, 该属性组就可以成为一个主键,主键不允许为空,主键只能有同一个 外键:如果一个表的某个属性是另一个表的主 ...