最后是最特别的一层: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以上的东西,Solver以及Caffe里“简单”的多卡训练。