几个月前的微信公众号留言置顶红包留言前几天还有,这两天在看的时候就成了默认的了,怎么回事,是有人改了吗

(Caffe,LeNet)初始化训练网络(三) - 简书
(Caffe,LeNet)初始化训练网络(三)
本文从CSDN上转移过来地址:
1. Solver到Net
在SGDSolver的构造函数中,主要执行了其父类Solver的构造函数,接着执行Solver::Init()函数,在Init()中,有两个函数值得注意:InitTrainNet()和InitTestNets()分别初始化训练网络和测试网络。
InitTrainNet
首先,ReadNetParamsFromTextFileOrDie(param_.net(), &net_param)把param_.net()(即examples/mnist/lenet_train_test.prototxt)中的信息读入net_param。
其次,net_.reset(new Net&Dtype&(net_param))重新构建网络,调用Net的构造方法。
然后,在构造方法中执行Net::init(),开始正式创建网络。其主要代码如下:
template &typename Dtype&
void Net&Dtype&::Init(const NetParameter& in_param) {
for (int layer_id = 0; layer_id & param.layer_size(); ++layer_id) {
// Setup layer.
const LayerParameter& layer_param = param.layer(layer_id);
layers_.push_back(LayerRegistry&Dtype&::CreateLayer(layer_param));
// Figure out this layer's input and output
for (int bottom_id = 0; bottom_id & layer_param.bottom_size();
++bottom_id) {
const int blob_id = AppendBottom(param, layer_id, bottom_id, &available_blobs, &blob_name_to_idx);
// If a blob needs backward, this layer should provide it.
need_backward |= blob_need_backward_[blob_id];
int num_top = layer_param.top_size();
for (int top_id = 0; top_id & num_ ++top_id) {
AppendTop(param, layer_id, top_id, &available_blobs, &blob_name_to_idx);
layers_[layer_id]-&SetUp(bottom_vecs_[layer_id], top_vecs_[layer_id]);
for (int param_id = 0; param_id & num_param_ ++param_id) {
AppendParam(param, layer_id, param_id);
Lenet5在caffe中共有9层,即param.layer_size() == 5,以上代码每一次for循环创建一个网络层
每层网络是通过LayerRegistry::CreateLayer()创建的,类似与Solver的创建(详见本系列博文(二))
14行Net::AppendBottom(),对于layer_id这层,从Net::blob_中取出blob放入该层对应的bottom_vecs_[layer_id]中
20行Net::AppendTop(),对于layer_id这层,创建blob(未包含数据)并放入Net::blob_中
Layer::SetUp()
AppendParam中把每层网络的训练参数与网络变量learnable_params_绑定,在lenet中,只有conv1,conv2,ip1,ip2四层有参数,每层分别有参数与偏置参数两项参数,因而learnable_params_的size为8.
InitTestNets&font color="red"&该部分内容见本系列博文:。&/font&
2 训练网络结构
layer Type Bottom
Blob Shape
data&&label
64 1 28 28 (50176) && 64 (64)
Convolution
64 20 24 24 (737280)
64 20 12 12 (184320)
Convolution
64 50 8 8 (204800)
64 50 4 4 (51200)
InnerProduct
64 500 (32000)
ip1(in-place)
64 500 (32000)
InnerProduct
64 10 (640)
SoftmaxWithLoss
ip2&&label
注:Top Blob Shape格式为:BatchSize,ChannelSize,Height,Width(Total Count)
3 第一层:Data Layer
3.1 protobuff定义
训练网络的第一层protobuff定义为:
name: "mnist"
type: "Data"
top: "data"
top: "label"
phase: TRAIN
transform_param {
data_param {
source: "examples/mnist/mnist_train_lmdb"
batch_size: 64
backend: LMDB
3.2 函数LayerRegistry::CreateLayer
第1节中代码第一次通过调用LayerRegistry::CreateLayer()创建了DataLayer类,DataLayer类的继承关系如下图所示,详见[1]:
由继承图可知,调用DataLayer()的构造函数,依次执行的顺序为其基类构造函数:Layer()、BaseDataLayer()、InternalThread()(详见 )、BasePrefetchingDataLayer()、及DataLayer()。
其中,值得注意的是DataLayer(),在调用基类构造函数BasePrefetchingDataLayer()之后,对 DataReader reader_ 进行赋值,在该DataLayer对象中维护了一个DataReader对象reader_,其作用是添加读取数据任务至,一个专门读取数据库(examples/mnist/mnist_train_lmdb)的线程(若还不存在该线程,则创建该线程),此处一共取出了464个样本至`BlockingQueue&Datum& DataReader::QueuePair::full_`。详见
template &typename Dtype&
DataLayer&Dtype&::DataLayer(const LayerParameter& param)
: BasePrefetchingDataLayer&Dtype&(param),
reader_(param) {
3.3 函数Layer::SetUp
此处按程序执行顺序值得关注的有:在DataLayer::DataLayerSetUp中根据3.2DataReader中介绍的读取的数据中取出一个样本推测blob的形状
BasePrefetchingDataLayer::LayerSetUp如下代码prefetch_[i].data_.mutable_cpu_data()用到了涉及到gpu、cpu间复制数据的问题,见及引用[2]
// Before starting the prefetch thread, we make cpu_data and gpu_data
// calls so that the prefetch thread does not accidentally make simultaneous
// cudaMalloc calls when the main thread is running. In some GPUs this
// seems to cause failures if we do not so.
for (int i = 0; i & PREFETCH_COUNT; ++i) {
prefetch_[i].data_.mutable_cpu_data();
if (this-&output_labels_) {
prefetch_[i].label_.mutable_cpu_data();
BasePrefetchingDataLayer类继承了InternalThread,BasePrefetchingDataLayer&Dtype&::LayerSetUp中通过调用StartInternalThread()开启了一个新线程,从而执行BasePrefetchingDataLayer::InternalThreadEntry
BasePrefetchingDataLayer::InternalThreadEntry关键代码如下,其中load_batch(batch)为,从2.2介绍的BlockingQueue&Datum*& DataReader::QueuePair::full_(包含从数据库读出的数据)中读取一个batch_size的数据到BlockingQueue&Batch&Dtype&*& BasePrefetchingDataLayer::prefetch_full_中。由于该线程在prefetch_free_为空时将挂起等待(PREFETCH_COUNT=3),prefetch_full_中用完的Batch将放回prefetch_free_中。该线程何时停止?
while (!must_stop()) {
Batch&Dtype&* batch = prefetch_free_.pop();
load_batch(batch);
#ifndef CPU_ONLY
if (Caffe::mode() == Caffe::GPU) {
batch-&data_.data().get()-&async_gpu_push(stream);
CUDA_CHECK(cudaStreamSynchronize(stream));
prefetch_full_.push(batch);
关于线程的总结:
此外一共涉及到两个线程,分别为都是继承了InnerThread的BasePrefetchingDataLayer(DataLayer)类和DataReader中的Body类
Body为面向数据库的线程,不断从某个数据库中读出数据,存放至缓存为队列DataReader::QueuePair::BlockingQueue&Datum*&,一般保存4*64个单位数据,单位为Datum
BasePrefetchingDataLayer为面向网络的线程,从Body的缓存中不断读取数据。BasePrefetchingDataLayer的缓存为队列BlockingQueue&Batch*&,一般存放3个单位的数据,单位为Batch
static const int PREFETCH_COUNT = 3;
Batch&Dtype& prefetch_[PREFETCH_COUNT];
BlockingQueue&Batch&Dtype&*& prefetch_free_;
BlockingQueue&Batch&Dtype&*& prefetch_full_;
template &typename Dtype&
BasePrefetchingDataLayer&Dtype&::BasePrefetchingDataLayer(
const LayerParameter& param)
: BaseDataLayer&Dtype&(param),
prefetch_free_(), prefetch_full_() {
for (int i = 0; i & PREFETCH_COUNT; ++i) {
prefetch_free_.push(&prefetch_[i]);
prefetch_full_与prefetch_free_中的元素由prefetch_提供
4 第二层:Convolution Layer
4.1 protobuff定义
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
lr_mult: 1
lr_mult: 2
convolution_param {
num_output: 20
kernel_size: 5
weight_filler {
type: "xavier"
bias_filler {
type: "constant"
4.2 函数LayerRegistry::CreateLayer
这里写图片描述
不像DataLayer 直接执行的是构造函数,此时执行的是GetConvolutuionLayer(),然后调用ConvolutionLayer(),原因如下:REGISTER_LAYER_CREATOR(Convolution, GetConvolutionLayer);
4.3 Layer::SetUp
在Layer::SetUp中,调用了ConvolutionLayer的基类BaseConvolutionLayer的LayerSetUp及Reshape函数,该类的主要成员变量如下:
* @brief Abstract base class that factors out the BLAS code common to
ConvolutionLayer and DeconvolutionLayer.
template &typename Dtype&
class BaseConvolutionLayer : public Layer&Dtype& {
explicit BaseConvolutionLayer(const LayerParameter& param)
: Layer&Dtype&(param) {}
virtual void LayerSetUp(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top);
virtual void Reshape(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top);
/// @brief The spatial dimensions of a filter kernel.
Blob&int& kernel_shape_;
/// @brief The spatial dimensions of the stride.
Blob&int& stride_;
/// @brief The spatial dimensions of the padding.
Blob&int& pad_;
/// @brief The spatial dimensions of the dilation.
Blob&int& dilation_;
/// @brief The spatial dimensions of the convolution input.
Blob&int& conv_input_shape_;
/// @brief The spatial dimensions of the col_buffer.
vector&int& col_buffer_shape_;
/// @brief The spatial dimensions of the output.
vector&int& output_shape_;
const vector&int&* bottom_shape_;
LayerSetUp函数中,主要是初始化了kernel_shape_、stride_、pad_、dilation_以及初始化网络参数,并存放与Layer::blobs_中。
Reshape函数中,conv_input_shape_、bottom_shape_等
5 第三层:Pooling Layer
5.1 protobuff定义
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
kernel_size: 2
5.2 Layer::SetUp
通过调用虚函数LayerSetUp及Reshape对以下成员变量进行初始化
* @brief Pools the input image by taking the max, average, etc. within regions.
* TODO(dox): thorough documentation for Forward, Backward, and proto params.
template &typename Dtype&
class PoolingLayer : public Layer&Dtype& {
int kernel_h_, kernel_w_;
int stride_h_, stride_w_;
int pad_h_, pad_w_;
int channels_;
int height_, width_;
int pooled_height_, pooled_width_;
bool global_pooling_;
Blob&Dtype& rand_idx_;
Blob&int& max_idx_;
6 第四层、第五层
基本同第二层、第三层
7 第六层:InnerProduct Layer
7.1 protobuff定义
name: "ip1"
type: "InnerProduct"
bottom: "pool2"
top: "ip1"
lr_mult: 1
lr_mult: 2
inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
bias_filler {
type: "constant"
7.2 Layer::SetUp
* @brief Also known as a "fully-connected" layer, computes an inner product
with a set of learned weights, and (optionally) adds biases.
* TODO(dox): thorough documentation for Forward, Backward, and proto params.
template &typename Dtype&
class InnerProductLayer : public Layer&Dtype& {
bool bias_term_;
Blob&Dtype& bias_multiplier_;
N_为输出大小,即等于protobuff中定义的num_output
K_为输入大小,对于该层Bottom Blob形状为(N, C, H, W),N为batch_size,K_=CHW,M_=N。其中只有C、H、W跟内积相关
8 第七层:ReLU Layer
8.1 protobuff定义
name: "relu1"
type: "ReLU"
bottom: "ip1"
top: "ip1"
ReLULayer主要是用来做计算的,其继承关系如下,详细参加[4]、[5]
9 第八层:InnerProduct Layer
10 第九层:SoftmaxWithLoss Layer
10.1 protobuff定义
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
top: "loss"
10.2 LayerRegistry::CreateLayer
这里写图片描述
10.3 Layer::SetUp
值得注意的是:
类SoftmaxWithLossLayer包含类SoftmaxLayer的实例 shared_ptr&Layer&Dtype& & softmax_layer_
softmax_layer_在LayerSetUp中赋值。
此函数内调用Layer::SetLossWeights初始化了该层的Top Blob(loss)
两个类间的关系如下图:
这里写图片描述
成员变量prob_作为Softmaxlayer的top blob
bottom blob[0]作为softmaxlayer的bottom blob
所以经过softmaxlayer计算之后,得出64*10(每个样本的每个类别上的概率)存放在prob_中
11 剩余的工作
至此,训练网络基本创建完毕,接下来剩下的工作主要有:
反向检查一次网络,看哪些blobs会对loss产生影响,在LeNet5中,前面的9层均有影响
初始化权值共享
Implementation Details[3].[4].[5].
ReLU / Rectified-Linear and Leaky-ReLU
程序猿一枚。3175人阅读
Caffe学习笔记(5)
本文是学习Caffe官方文档&ImageNet Tutorial&时做的,同样由于是Windows版本的原因,很多shell脚本不能直接使用,走了不少弯路,但是收获也不少。比如:如何让shell脚本在Windows系统上直接运行、如何去用Caffe给图像resize来统一大小,如何去构建train.txt和val.txt等等。具体流程均记录如下。
1.准备数据
我从网上下载了两类图片,一类为猫,一类为鸟,分别存在名为bird和cat的文件夹里,每类60张(50张做为训练集,10张做为测试集)。【分开存放,在做train.txt时,方便打标签。等做完标签再将100张训练图片一起放在新建的train文件下里,下面会详述。】
猫:(已经过批量重命名。ps:我选图还是比较讲究的,不好看的、不清楚的、不奇怪的我不选,哈哈)
鸟:(已经过批量重命名)
2.构建train.txt和val.txt
首先是重命名图片,从搜索引擎下载下来的图片的名称都是则乱无章,我们需要用批量重命名的方法去先给它们命名。
批量重命名可以通过一个bat文件实现,代码如下:
修改其中的“bird”位置,运行。比如,我将“bird”改为“Cat”,运行bat文件,效果如下:
可以看到图片名字被统一的修改了,并且生成了一个list文件夹,通过txt文件的查找-替换,给每个文件打上标签(比如Cat为0,Bird为1),截图如下:
下面的工作自己做就行了,将cat和bird的txt文档,合在一起,组成train.txt。同理,完成val.txt。我的train.txt和val.txt的截图如下(我标签用了1和2):
3.数据处理
数据处理要进行三项:1.将图片统一转化成256X256大小。2.将数据转化为LEVELDB格式。3.求数据均值。
看了一些博客,在将图片统一转化成256大小这儿曲线救国,想了很多方法。其实第1步和第2步可以一起完成,只要调用examples\imagenet\create_imagenet.sh就可以一起完成。但是shell脚本在Windows下如何运行呢?是可以的,只需要安装Git即可在Windows环境下运行shell脚本!Git下载链接:/downloads/
根据具体情况,对create_imagenet.sh,做一些修改(需要修改处均用红色方框标出,五角星处即是caffe自带的resize图片的地方,一定要设为true):
打开git,运行create_imagenet.sh即可,查看文件夹,出现imagenet_train_leveldb和imagene_val_leveldb:
接下来是进行第三步,求图像均值了。在进行这一步时,我使用\examples\imagenet\make_imagenet_mean.sh时,是成功求得了均值文件imagenet_mean.binaryproto,但在之后训练时,一直报错,提示均值文件无法读取。故还是换用了compute_image_mean.exe,来求得均值文件,具体步骤,之前的文章已经记录了,不再赘述。
再从\models\bvlc_reference_caffenet中,将train_val.prototxt和solver.prototxt复制过来,这样所有文件都准备齐全了:
4.配置训练所需文件
首先,根据具体情况修改,train_val.prototxt:
修改solver.prototxt:
关于solver里面的参数,我认为应该根据具体情况就修改就好了,这一部分我还不是很熟悉,慢慢积累吧。
5.进行训练
写一个bat文件,进行训练即可!bat文件代码如下:
6.训练结果
因为我的电脑配置很低很低。。所以训练起来很慢,我调小了很多参数,训练了两天还是没训完。。。贴一张训练中的截图吧:
这次主要是为了自己感受一下用Windows Caffe训练自己数据的整个过程,也没有去追求准确率,也没有考虑去跟踪训练过程去调参等等。这些经验方面的知识,接下来慢慢继续积累吧。经过这次学习,起码能把整个过程跑下来了,收获很多。
参考文档:
1.Caffe官方文档:
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:25856次
积分:1343
积分:1343
排名:千里之外
原创:119篇
评论:25条
(1)(3)(33)(46)(29)(9) 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
caffe学习笔记4_学习搭建自己的网络——MNIST在caffe上进行训练与学习-薛开宇
下载积分:1500
内容提示:caffe学习笔记4_学习搭建自己的网络——MNIST在caffe上进行训练与学习-薛开宇
文档格式:PDF|
浏览次数:99|
上传日期: 14:42:51|
文档星级:
全文阅读已结束,如果下载本文需要使用
 1500 积分
下载此文档
该用户还上传了这些文档
caffe学习笔记4_学习搭建自己的网络——MNIST在caffe
官方公共微信君,已阅读到文档的结尾了呢~~
本次学习笔记作用比较大,也是重点,知道如何在caffe上搭建自己的数据库。
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
caffe学习笔记3
用自己的数据训练和测试-薛开宇
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口

我要回帖

更多关于 微信公众号留言点赞 的文章

 

随机推荐