首先,查看相关的结构体的定义
Net:
Net类的数据结构
构造函数(从NetPatameter构造或者从net.prototxt中构造),初始化函数,NetParameter;
前向传播,反向传播
Net的读取与保存(序列化)
返回Blobs, Layers的名称,是否需要反向传播,权值和相关参数等
查找当前网络是否包含指定名称的Blob,Layer
初始化Init()
构建所有的Layer:CreateLayer(param.layer(layer_id));
确定Layer的输入Blob和输出Blob,从而将各个layer通过Bolb连接起来
调用Layer->Setup函数
初始化各层权值Blob
前向传播Forward
net->ForwardFromTo调用相应层的layer_[i]->Forward(bottom_vecs_[i],top_vecs_[i])
Blob:
Blob用于存储4维数据。4个维度分别为(num,channel,height,width).
public:
构造函数
Reshape,打印Bolob的shape,获取某一维度的尺寸,根据n计算偏移量,Blob中的元素数目
获取指定位置的data或diff,获取cpu_data或cpu_diff
Blob的序列化或反序列化
protected:
指向data_,diff_的指针
形状信息shape_
存放有效元素数目的信息count_,Blob的容量信息capacity_.
src/caffe.blob.cpp
Reshape(),变维函数
构造函数
获得cpu_data,cpu_diff,gpu_data,gpu_diff的指针
共享另一个Blob的data,diff指针
Update来更新网络中的参数(data = data-diff)
Blob的序列化与反序列化
Blob的基础功能有:定义一个Blob,打印Blob的shape,重定义该Blob的shape(Blob的大小可以不一致),修改和获取Blob在各个位置的参数值
#include <vector>
#include <iostream>
#include <caffe/blob.hpp>
using namespace caffe;
using namespace std;
int main(void)
{
Blob<float> a;#定义一个Blob
cout<<"Size : "<< a.shape_string()<<endl;#获取该Blob的size
a.Reshape(1, 2, 3, 4);#Reshape该Blob
cout<<"Size : "<< a.shape_string()<<endl;
#修改Blob指定位置元素的值
float * p = a.mutable_cpu_data();
for(int i = 0; i < a.count(); i++)
{
p[i] = i;
}
#获取病打印Blob各个元素的值
for(int u = 0; u < a.num(); u++)
{
for(int v = 0; v < a.channels(); v++)
{
for(int w = 0; w < a.height(); w++)
{
for(int x = 0; x < a.width(); x++)
{
cout<<"a["<<u<<"]["<<v<<"]["<<w<<"]["<<x<<"] = "<< a.data_at(u, v, w, x)<<endl;
}
}
}
}
return 0;
}
Blob的进阶功能有:修改Blob的diff,根据data=data-diff来更新Blob
Net的基本功能有:读取xxx.prototxt文件来设置网络,获取并修改Net的权值(如W,b,即训练参数),读取和设置网络的输入,前向传播后读取网络的输出
#include <caffe/caffe.hpp>
#include <algorithm>
#include <iosfwd>
#include <memory>
#include <string>
#include <utility>
#include <vector>
using namespace caffe; // NOLINT(build/namespaces)
using std::string;
int main(int argc, char** argv) {
//从model_file(xxx.prototxt)中初始化网络结构
shared_ptr<Net<float> > net_;
net_.reset(new Net<float>("./net.prototxt", TEST));
//设置网络的权重参数,如使用训练好的网络来初始化网络参数,或自己手动设置网络权重所在的Blob
//由于我们的网络只有一层卷积,一层卷积只有两个网络参数,第一个是W(num_output,num_input,height,width),第二个是b(num_output)
const vector<shared_ptr<Blob<float> > >& net_params = net_->params();
std::cout<<net_params.size()<<std::endl;#表示有多少个网络参数(多少个W+多少个b)
const vector<int>& shape = net_params[0]->shape();#得到第一个网络参数W的Blob
std::cout<<shape.size()<<std::endl;#打印W的维度,4维
std::cout<<shape[0] <<shape[1] <<shape[2]<<shape[3]<<std::endl;#打印W各个维度(num_output,num_input,height,width)
float *p = net_params[0]->mutable_cpu_data();#获取和设置W所在的Blob
for(int i =0;i<net_params[0]->count();i++)
{
p[i]=i%2==0?1:1;
}
for(int u =0;u<net_params[0]->channels();u++)
{
for(int v =0;v<net_params[0]->height();v++)
{
for(int w =0;w<net_params[0]->width();w++)
{
std::cout<<net_params[0]->data_at(0,u,v,w)<<std::endl;
}
}
}
//设置网络的输入Blob
// 获取和设置输入Blob
Blob<float>* input_layer = net_->input_blobs()[0];//输入Blob可能有多个,[0]表示获取第一个Blob
float *p2 = input_layer->mutable_cpu_data();
int num_channels_ = input_layer->channels();
for(int i2 =0;i2<input_layer->count();i2++)
{
p2[i2]=(i2%2==0)?2:5;
}
for(int u =0;u<input_layer->channels();u++)
{
for(int v =0;v<input_layer->height();v++)
{
for(int w =0;w<input_layer->width();w++)
{
std::cout<<"input_layer"<<u<<v<<w<<" "<<input_layer->data_at(0,u,v,w)<<std::endl;
}
}
}
#网络执行前向传播并得到输出Blob
net_->Forward();
Blob<float>* out_layer = net_->output_blobs()[0];
float *p4 = out_layer->mutable_cpu_data();
for (int x =0;x<out_layer->num();x++)
{
for(int u =0;u<out_layer->channels();u++)
{
for(int v =0;v<out_layer->height();v++)
{
for(int w =0;w<out_layer->width();w++)
{
std::cout<<"out_layer"<<x<<u<<v<<w<<" "<<out_layer->data_at(x,u,v,w)<<std::endl;
}
}
}
}
}
用于创建网络模型的xxx.prototxt
1.数据输入层
不指定数据,指定数据的维度
input: "data"
input_dim: 1
input_dim: 1
input_dim: 10
input_dim: 10
图像语义分割的输入,需要自己创建DenseImageData层
layer {
name: "ImageData1"
type: "DenseImageData"
top: "ImageData1"
top: "ImageData2"
dense_image_data_param {
source: "/media/mlxuan/LinuxH/project/SegNet/SegNet-Tutorial-master/CamVid/train.txt"
batch_size: 1
shuffle: true
}
}
图像分类的输入
其他
2.卷积层
layer {
name: "Convolution1"
type: "Convolution"
bottom: "data"
top: "Convolution1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 1
pad: 0
kernel_size: 3
stride: 1
dilation: 1
weight_filler {
type: "msra"
}
bias_filler {
type: "constant"
}
}
}