秒速飞艇投注彩客网: 秒速飞艇计划app

北京 切换校区

全国24小时免费热线

400-009-1906

Caffe源码阅读——Net组装

时间:2019-03-05   来源:尚学堂   阅读:63
? ? ? ? Net是Caffe代码中一个比较核心的类,往下看它封装了所有的Layer,构建起了整个神经网络;往上看它对外提供了前向后向计算,以及核心数据结构的访问结构,使得再上层的Solver可以利用Net比较轻松地实现Train和Test的策略。当然,正是因为它的重要性,组装Net是一个比较复杂的部分。这一回我们就来看看Net的内容。
? ? ? ? 当然,说在前面,看Net组装的代码有两个目的:

? ? ? ? 了解作为一个成熟的CNN模型框架需要考虑的一些问题;

? ? ? ? 如果想对网络结构做扩展,如写一个新的Layer,其中的一些数据是如何在Layer和Net之间流动的

? ? ? ? 首先,为了使问题不那么复杂,我们先从训练模型时输出的log看看Net组装的几个关键步骤,然后再把这个过程慢慢展开,了解组装的所有细节。
? ? ? ? Log眼中的Net组装
? ? ? ? 为了更好地展示Net组装的一些细节,我们在这里选取了一个实际例子,就是Caffe的examples里面的siamese model。关于这个model的细节这里就不多说了,感兴趣的可以去看官方或者非官方的文档,这里只提一点:这个网络除了包含其他正常网络中的一些特性之外,还具有网络参数复用的特点,在后面的分析中我们会用到。
? ? ? ? 下面我们要看的就是Net组装的Log。这段Log一般都是大家在训练网络时一闪而过的大段Log,当然如果它没有一闪而过而是停下来了,有可能是你的网络定义有问题爆出了错误。这段Log内容比较多,总体来说就是Train阶段和Test阶段的两个网络组装起来。我们重点关注其中的几个片段,来大概了解Net组装的一些核心内容,也是那些比较值得打印出来的内容。
? ? ? ? 首先是一个正常的卷积层conv1,Log如下所示(以下代码的行号可能会有不同,但位置是相近的):
layer_factory.hpp:77] Creating layer conv1

net.cpp:92] Creating Layer conv1

net.cpp:428] conv1 <- data

net.cpp:402] conv1 -> conv1

net.cpp:144] Setting up conv1

net.cpp:151] Top shape: 64 20 24 24 (737280)

net.cpp:159] Memory required for data: 3752192

? ? ? ? 这其中第一行是创建这个Layer实例的代码,具体的创建过程在layer_factory里面。为了方便创建Layer,Caffe采用了工厂方法的设计模式,只要提供Layer的名字(在配置文件中参数叫type),就可以根据名字和对应参数实例化一个Layer。这部分的细节只要认真看一下就会明白。

 

? ? ? ? 第3,4行显示了创建当前层的bottom和top数据的过程。这里涉及到net.cpp中的AppendBottom和AppendTop两个方法,因为每一个bottom blob和top blob都有名字,这里就将他们之间的关系输出在了这里。

 

? ? ? ? 第5行看上去没什么干货,但是它代表了Layer的Setup函数已经调用完成(或者Layer被share)。Layer的Setup函数是Layer初始化的关键函数,这里面涉及到以下几个具体的操作:

CheckBlobCounts(bottom, top);

LayerSetUp(bottom, top);

Reshape(bottom, top);

SetLossWeights(top);

? ? ? ? ?总结地说,这四句完成了:

对bottom blob, top blob数量的检查,父类实现。

对Layer内部相关变量的初始化,由具体的子类实现

传入时bottom blob的维度已经确定,Layer需要根据自己要做的计算确定top blob的纬度。比方说这一层是卷积层,维度是20*5*5,输入图像是1*28*28,也就是bottom blob的维度,那么输出的维度就是20*24*24,这也是上面log里面算出的结果,只不过还加了一个batch size。这个函数由具体的子类实现。

对Layer是否输出loss以及输出loss要做的操作进行初始化。父类实现。必须说一句,Caffe中关于Loss Layer中Loss_weight,loss_,top.cpu_diff的数据设定还是有点绕且有点trick的。

? ? ? ? 好了回到上面的log。接下来的那一句告诉了我们top层应该输出的维度。这里输出了维度就是为了让不放心的朋友算一下,看看和你想的是否一样。当然,输出这句log的循环不是只做了这件事,它的主要工作就是设置top blob的loss_weight。

? ? ? ? 最后一句计算了该层top blob所占用的内存??梢钥闯鼋刂恋秸庖徊?,内存消耗大约是3M多,还不算大。

? ? ? ? 好,这就是一个最典型的Layer的初始化,下面这个ReLU层就稍微有些不同了:

layer_factory.hpp:77] Creating layer relu1

net.cpp:92] Creating Layer relu1

net.cpp:428] relu1 <- ip1

net.cpp:389] relu1 -> ip1 (in-place)

net.cpp:144] Setting up relu1

net.cpp:151] Top shape: 64 500 (32000)

net.cpp:159] Memory required for data: 5769472

? ? ? ? 这里面最不同的就是第4行结尾的(in-place),这说明relu的bottom blob和top blob是同一个数据,这和我们在网络中的定义是一样的。in-place的好处就是减少内存的操作,但是这里在统计内存消耗时并没有考虑in-place带来的节省。

 

? ? ? ?接下来就是共享网络的conv1_p了:

layer_factory.hpp:77] Creating layer conv1_p

net.cpp:92] Creating Layer conv1_p

net.cpp:428] conv1_p <- data_p

net.cpp:402] conv1_p -> conv1_p

net.cpp:144] Setting up conv1_p

net.cpp:151] Top shape: 64 20 24 24 (737280)

net.cpp:159] Memory required for data: 8721664

net.cpp:488] Sharing parameters 'conv1_w' owned by layer 'conv1', param index 0

net.cpp:488] Sharing parameters 'conv1_b' owned by layer 'conv1', param index 1

? ? ? ? 这一段最有特点的是最后两句“Sharing”,因为siamese model中拥有参数完全相同的两个网络,所以在构建时候,第二个网络检测到参数名字已经存在,说明该层的参数和其他层共享,于是在这里打印出来告诉用户这一点。当然,这一句之前没有打印出来的内容告诉了我们,实际上Net类中还负责了参数相关的初始化。这部分的内容实际上还挺多,除了参数共享,还有对参数learning rate,weight decay的设定。

? ? ? ?最后是最特别的一层:loss层

net.cpp:92] Creating Layer loss

net.cpp:428] loss <- feat

net.cpp:428] loss <- feat_p

net.cpp:428] loss <- sim

net.cpp:402] loss -> loss

net.cpp:144] Setting up loss

net.cpp:151] Top shape: (1)

net.cpp:154] ? ? with loss weight 1

net.cpp:159] Memory required for data: 10742020

? ? ? ?这一层看上去没有什么特别,该有的和前面一样,但是唯一不同的就是它的倒数第二行,这说明这一层是有loss weight的。至于有loss weight有什么用,以后我们会详细说这个事情。这里简单说一下,有loss weight表示这个blob会被用于计算loss。

 

? ? ? ?前面的log主要解决了网络的组装和前向的一些计算,从log中,我们可以看出Net完成了以下的事情:

? ? ? ?实例化Layer

? ? ? ?创建bottom blob,top blob

? ? ? ?Setup Layer(初始化Layer,确定top blob维度)

? ? ? ?确定layer的loss_weight

? ? ? ?确定layer的参数是否共享,不共享则创建新的

 

? ? ? ?从上面的过程也可以看出,整个网络中所有的流动性变量(bottom blob,top blob)都保存在Net中,同时对于各层的参数,根据各层的共享关系做了标记。这样好处是集中管理了网络中的数据,方便对数据进行操作。

? ? ? ?再往下面,我们可以截取一小段log来:

net.cpp:220] pool1 needs backward computation.

net.cpp:220] conv1 needs backward computation.

net.cpp:222] slice_pair does not need backward computation.

net.cpp:222] pair_data does not need backward computation.

net.cpp:264] This network produces output loss

net.cpp:277] Network initialization done.

? ? ? ? 接下来是统计一个层次是否需要进行反向传播的计算。一般来说我们的层是都需要计算的,但是也会有一些层不需要计算,比方说数据层,就像上面的log那样,还有就是一些希望固定的层,这个一般在finetune网络的时候用的上。因为反向计算一般比前向计算慢,如果有不需要计算的Layer,直接跳过计算是可以节省时间的。

 

? ? ? ?最后是整个网络产生的输出,这个输出会在训练迭代中显示出来的。

 

? ? ? ?了解了这些,我们就对Net装载有了大概的了解,再去看它的代码就会轻松些。

 

? ? ? ?最后,关于Net类中所有的成员变量与它们之间的关系,我们可以用下面的一张图来理解就好:

Net类

? ? ? ?把Net的初始化理解后,其实Net以下的架构方面的问题就不多了。下面我再看看Net以上的东西,Solver以及Caffe里“简单”的多卡训练。

相关资讯

  • 北京校区
  • 山西校区
  • 郑州校区
  • 武汉校区
  • 四川校区
  • 长沙校区
  • 深圳校区
  • 上海校区
  • 广州校区
  • 保定招生办

北京海淀区校区(总部):北京市海淀区西三旗街道建材城西路中腾建华商务大厦东侧二层尚学堂
北京京南校区:北京亦庄经济开发区科创十四街6号院1号楼 赛蒂国际工业园
咨询电话:400-009-1906 / 010-56233821
面授课程: JavaEE培训、 大数据就业班培训、 大数据云计算周末班培训、 零基础大数据连读班培训、 大数据云计算高手班培训、 人工智能周末班培训、人工智能+Python全栈培训、 H5+PHP全栈工程师培训

山西学区地址:山西省晋中市榆次区大学城大学生活广场万科商业A1座702

郑州学区地址:河南电子商务产业园6号楼4层407
咨询电话:0371-55177956

武汉学区地址:湖北省武汉市江夏区江夏大道26号 宏信悦谷创业园4楼
咨询电话:027-87989193

四川学区地址:成都市高新区锦晖西一街99号布鲁明顿大厦2栋1003室
咨询电话:028-65176856 / 13880900114

网址://www.cssxt.com/
咨询电话:0731-83072091

深圳校区地址:深圳市宝安区航城街道航城大道航城创新创业园A4栋210(固戍地铁站C出口)
咨询电话:0755-23061965 / 18898413781

上海尚学堂松江校区地址:上海市松江区荣乐东路2369弄45号绿地伯顿大厦2层
咨询电话:021-67690939

广州校区地址:广州市天河区元岗横路31号慧通产业广场B区B1栋6楼尚学堂(地铁3号线或6号线到“天河客运站”D出口,右拐直走约800米)
咨询电话:020-2989 6995

保定招生办公室

地址:河北省保定市竞秀区朝阳南大街777号鸿悦国际1101室

电话:15132423123

Copyright 2006-2019 北京尚学堂科技有限公司  京ICP备13018289号-19  京公网安备11010802015183  
媒体联系:18610174079 闫老师  

Java基础班,免费试学三周

813| 988| 990| 880| 459| 85| 239| 318| 365| 852|