src/caffe/proto/caffe.proto 中LayerParameter部分

  1 // NOTE
  2 // Update the next available ID when you add a new LayerParameter field.
  3 // 如果增加一个新的LayerParameter域,需要更新下一个可用的ID
  4 // LayerParameter next available layer-specific ID: 147 (last added: recurrent_param)
  5 message LayerParameter {
  6   optional string name = 1; // the layer name 名称
  7   optional string type = 2; // the layer type 类型
  8   repeated string bottom = 3; // the name of each bottom blob 输入的Bottom Blob的名称
  9   repeated string top = 4; // the name of each top blob 输出的Top Blob名称
 10 
 11   // The train / test phase for computation.当前阶段TRAIN或TEST
 12   optional Phase phase = 10;
 13 
 14   // The amount of weight to assign each top blob in the objective.
 15   // Each layer assigns a default value, usually of either 0 or 1,
 16   // to each top blob.
 17   // 为每个输出Top Blob分配对损失函数的权重,每个Layer都有默认值,0表示不参与计算,1表示参与损失函数计算
 18   repeated float loss_weight = 5;
 19 
 20   // Specifies training parameters (multipliers on global learning constants,
 21   // and the name and other settings used for weight sharing).
 22   // 指定训练参数(例如相对全局学习常熟的缩放因子,以及用于权值共享的名称或其他设置)
 23   repeated ParamSpec param = 6;
 24 
 25   // The blobs containing the numeric parameters of the layer.
 26   // 承载该曾数值参数的Blob
 27   repeated BlobProto blobs = 7;
 28 
 29   // Specifies whether to backpropagate to each bottom. If unspecified,
 30   // Caffe will automatically infer whether each input needs backpropagation
 31   // to compute parameter gradients. If set to true for some inputs,
 32   // backpropagation to those inputs is forced; if set false for some inputs,
 33   // backpropagation to those inputs is skipped.
 34   // 是否对Bottom Blob进行反向传播过程。该字段维度应与Bottom Blob个数一致。
 35   // The size must be either 0 or equal to the number of bottoms.
 36   repeated bool propagate_down = 11;
 37 
 38   // Rules controlling whether and when a layer is included in the network,
 39   // based on the current NetState.  You may specify a non-zero number of rules
 40   // to include OR exclude, but not both.  If no include or exclude rules are
 41   // specified, the layer is always included.  If the current NetState meets
 42   // ANY (i.e., one or more) of the specified rules, the layer is
 43   // included/excluded.
 44   // 控制某个层在某个时刻是否包含在网络中(基于当前的NetState)
 45   // 可以为include或exclude指定非零值(不能同时)
 46   // 如果没有规则,该层一直包含在网络中
 47   // 如果当前的NetState满足一定条件,那么该层被包含或被排斥
 48   repeated NetStateRule include = 8;
 49   repeated NetStateRule exclude = 9;
 50 
 51   // Parameters for data pre-processing. 数据预处理参数
 52   optional TransformationParameter transform_param = 100;
 53 
 54   // Parameters shared by loss layers. 所有损失层共享的参数
 55   optional LossParameter loss_param = 101;
 56 
 57   // Layer type-specific parameters.特定类型层参数
 58   // 注意:一些层实现时可能有多于一种计算引擎,这些层通过选择引擎类型和引擎参数来实现。
 59   // 默认引擎是在编译阶段由引擎开关设置的
 60   // Note: certain layers may have more than one computational engine
 61   // for their implementation. These layers include an Engine type and
 62   // engine parameter for selecting the implementation.
 63   // The default for the engine is set by the ENGINE switch at compile-time.
 64   optional AccuracyParameter accuracy_param = 102;
 65   optional ArgMaxParameter argmax_param = 103;
 66   optional BatchNormParameter batch_norm_param = 139;
 67   optional BiasParameter bias_param = 141;
 68   optional ConcatParameter concat_param = 104;
 69   optional ContrastiveLossParameter contrastive_loss_param = 105;
 70   optional ConvolutionParameter convolution_param = 106;
 71   optional CropParameter crop_param = 144;
 72   optional DataParameter data_param = 107;
 73   optional DropoutParameter dropout_param = 108;
 74   optional DummyDataParameter dummy_data_param = 109;
 75   optional EltwiseParameter eltwise_param = 110;
 76   optional ELUParameter elu_param = 140;
 77   optional EmbedParameter embed_param = 137;
 78   optional ExpParameter exp_param = 111;
 79   optional FlattenParameter flatten_param = 135;
 80   optional HDF5DataParameter hdf5_data_param = 112;
 81   optional HDF5OutputParameter hdf5_output_param = 113;
 82   optional HingeLossParameter hinge_loss_param = 114;
 83   optional ImageDataParameter image_data_param = 115;
 84   optional InfogainLossParameter infogain_loss_param = 116;
 85   optional InnerProductParameter inner_product_param = 117;
 86   optional InputParameter input_param = 143;
 87   optional LogParameter log_param = 134;
 88   optional LRNParameter lrn_param = 118;
 89   optional MemoryDataParameter memory_data_param = 119;
 90   optional MVNParameter mvn_param = 120;
 91   optional ParameterParameter parameter_param = 145;
 92   optional PoolingParameter pooling_param = 121;
 93   optional PowerParameter power_param = 122;
 94   optional PReLUParameter prelu_param = 131;
 95   optional PythonParameter python_param = 130;
 96   optional RecurrentParameter recurrent_param = 146;
 97   optional ReductionParameter reduction_param = 136;
 98   optional ReLUParameter relu_param = 123;
 99   optional ReshapeParameter reshape_param = 133;
100   optional ScaleParameter scale_param = 142;
101   optional SigmoidParameter sigmoid_param = 124;
102   optional SoftmaxParameter softmax_param = 125;
103   optional SPPParameter spp_param = 132;
104   optional SliceParameter slice_param = 126;
105   optional TanHParameter tanh_param = 127;
106   optional ThresholdParameter threshold_param = 128;
107   optional TileParameter tile_param = 138;
108   optional WindowDataParameter window_data_param = 129;
109 }

 include/caffe/layer.hpp

  1 #ifndef CAFFE_LAYER_H_
  2 #define CAFFE_LAYER_H_
  3 
  4 #include <algorithm>
  5 #include <string>
  6 #include <vector>
  7 
  8 #include "caffe/blob.hpp"
  9 #include "caffe/common.hpp"
 10 #include "caffe/layer_factory.hpp"
 11 #include "caffe/proto/caffe.pb.h"
 12 #include "caffe/util/math_functions.hpp"
 13 
 14 /**
 15  Forward declare boost::thread instead of including boost/thread.hpp
 16  to avoid a boost/NVCC issues (#1009, #1010) on OSX.
 17  */
 18 namespace boost { class mutex; }
 19 
 20 namespace caffe {
 21 
 22 /**
 23  * @brief An interface for the units of computation which can be composed into a
 24  *        Net.
 25  *
 26  * Layer%s must implement a Forward function, in which they take their input
 27  * (bottom) Blob%s (if any) and compute their output Blob%s (if any).
 28  * They may also implement a Backward function, in which they compute the error
 29  * gradients with respect to their input Blob%s, given the error gradients with
 30  * their output Blob%s.
 31  */
 32 template <typename Dtype>
 33 class Layer {
 34  public:
 35   /**
 36    * You should not implement your own constructor. Any set up code should go
 37    * to SetUp(), where the dimensions of the bottom blobs are provided to the
 38    * layer.
 39    */
 40    // 显式构造函数,从LayerParameter中加载配置
 41   explicit Layer(const LayerParameter& param)
 42     : layer_param_(param) {
 43       // Set phase and copy blobs (if there are any).
 44       phase_ = param.phase();//设置当前阶段(训练或预测)
 45       if (layer_param_.blobs_size() > 0) {
 46         blobs_.resize(layer_param_.blobs_size());
 47         //按照layer_param_设置本身Blob对象个数,并依次把每个Blob对象尺寸调整为与layer_param_中Blob尺寸一致
 48         for (int i = 0; i < layer_param_.blobs_size(); ++i) {
 49           blobs_[i].reset(new Blob<Dtype>());
 50           blobs_[i]->FromProto(layer_param_.blobs(i));
 51         }
 52       }
 53     }
 54   virtual ~Layer() {}
 55 
 56   /**
 57    * @brief Implements common layer setup functionality.
 58    *
 59    * @param bottom the preshaped input blobs
 60    * @param top
 61    *     the allocated but unshaped output blobs, to be shaped by Reshape
 62    *
 63    * Checks that the number of bottom and top blobs is correct.
 64    * Calls LayerSetUp to do special layer setup for individual layer types,
 65    * followed by Reshape to set up sizes of top blobs and internal buffers.
 66    * Sets up the loss weight multiplier blobs for any non-zero loss weights.
 67    * This method may not be overridden.
 68    */
 69    //配置函数,实现常用层配置借口,不可被覆盖
 70   void SetUp(const vector<Blob<Dtype>*>& bottom,
 71       const vector<Blob<Dtype>*>& top) {
 72     CheckBlobCounts(bottom, top);//检查blob
 73     LayerSetUp(bottom, top);     //与层类型相关的配置过程
 74     Reshape(bottom, top);        //对TopBlob进行变形
 75     SetLossWeights(top);         //设置损失权值因子Blob
 76   }
 77 
 78   /**
 79    * @brief Does layer-specific setup: your layer should implement this function
 80    *        as well as Reshape.
 81    *
 82    * @param bottom
 83    *     the preshaped input blobs, whose data fields store the input data for
 84    *     this layer
 85    * @param top
 86    *     the allocated but unshaped output blobs
 87    *
 88    * This method should do one-time layer specific setup. This includes reading
 89    * and processing relevent parameters from the <code>layer_param_</code>.
 90    * Setting up the shapes of top blobs and internal buffers should be done in
 91    * <code>Reshape</code>, which will be called before the forward pass to
 92    * adjust the top blob sizes.
 93    */
 94    //层配置虚函数,做特定类型层相关配置,由该类型层自己实现
 95   virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
 96       const vector<Blob<Dtype>*>& top) {}
 97 
 98   /**
 99    * @brief Adjust the shapes of top blobs and internal buffers to accommodate
100    *        the shapes of the bottom blobs.
101    *
102    * @param bottom the input blobs, with the requested input shapes
103    * @param top the top blobs, which should be reshaped as needed
104    *
105    * This method should reshape top blobs as needed according to the shapes
106    * of the bottom (input) blobs, as well as reshaping any internal buffers
107    * and making any other necessary adjustments so that the layer can
108    * accommodate the bottom blobs.
109    */
110    //纯虚函数。变形函数,修改Top Blob以及内部Blob缓冲区形状
111   virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
112       const vector<Blob<Dtype>*>& top) = 0;
113 
114   /**
115    * @brief Given the bottom blobs, compute the top blobs and the loss.
116    *
117    * @param bottom
118    *     the input blobs, whose data fields store the input data for this layer
119    * @param top
120    *     the preshaped output blobs, whose data fields will store this layers'
121    *     outputs
122    * \return The total loss from the layer.
123    *
124    * The Forward wrapper calls the relevant device wrapper function
125    * (Forward_cpu or Forward_gpu) to compute the top blob values given the
126    * bottom blobs.  If the layer has any non-zero loss_weights, the wrapper
127    * then computes and returns the loss.
128    *
129    * Your layer should implement Forward_cpu and (optionally) Forward_gpu.
130    */
131    // 前向传播函数
132    // 给定Bottom Blob,计算TopBlob和loss,返回值为当前层的loss
133    // 该函数会调用相应设备包装函数,如Forward_cpu or Forward_gpu来实现真正计算过程
134    // 如果该层有非零loss权重参数,包装函数会计算并返回loss
135    // 派生类应该实现Forward_cpu,Forward_gpu(可选)
136   inline Dtype Forward(const vector<Blob<Dtype>*>& bottom,
137       const vector<Blob<Dtype>*>& top);
138 
139   /**
140    * @brief Given the top blob error gradients, compute the bottom blob error
141    *        gradients.
142    *
143    * @param top
144    *     the output blobs, whose diff fields store the gradient of the error
145    *     with respect to themselves
146    * @param propagate_down
147    *     a vector with equal length to bottom, with each index indicating
148    *     whether to propagate the error gradients down to the bottom blob at
149    *     the corresponding index
150    * @param bottom
151    *     the input blobs, whose diff fields will store the gradient of the error
152    *     with respect to themselves after Backward is run
153    *
154    * The Backward wrapper calls the relevant device wrapper function
155    * (Backward_cpu or Backward_gpu) to compute the bottom blob diffs given the
156    * top blob diffs.
157    *
158    * Your layer should implement Backward_cpu and (optionally) Backward_gpu.
159    */
160    //反向传播函数
161    //给定输出的Top Blob误差梯度,计算输入的Bottom Blob的误差梯度
162    //propagate_down为多路开关,与Bottom Blob矢量维度相同,每个值表示是否将误差梯度传递到对应的Bottom Blob
163    //该函数会调用相应设备包装函数,如Backward_cpu and (可选) Backward_gpu实现计算过程,由派生类负责实现
164   inline void Backward(const vector<Blob<Dtype>*>& top,
165       const vector<bool>& propagate_down,
166       const vector<Blob<Dtype>*>& bottom);
167 
168   /**
169    * @brief Returns the vector of learnable parameter blobs.
170    */
171   vector<shared_ptr<Blob<Dtype> > >& blobs() {
172     return blobs_;//返回Layer内部可训练的权值、偏置项Blob向量
173   }
174 
175   /**
176    * @brief Returns the layer parameter.
177    */
178    //返回Layer初始化参数(由ProtoBuffer提供)
179   const LayerParameter& layer_param() const { return layer_param_; }
180 
181   /**
182    * @brief Writes the layer parameter to a protocol buffer
183    */
184    //将Layer初始化参数写入ProtoBuffer缓冲区
185   virtual void ToProto(LayerParameter* param, bool write_diff = false);
186 
187   /**
188    * @brief Returns the scalar loss associated with a top blob at a given index.
189    */
190    //返回与某个Top Blob相关的标量loss值
191   inline Dtype loss(const int top_index) const {
192     return (loss_.size() > top_index) ? loss_[top_index] : Dtype(0);
193   }
194 
195   /**
196    * @brief Sets the loss associated with a top blob at a given index.
197    */
198    //设置与某个Top Blob相关的标量loss值
199   inline void set_loss(const int top_index, const Dtype value) {
200     if (loss_.size() <= top_index) {
201       loss_.resize(top_index + 1, Dtype(0));
202     }
203     loss_[top_index] = value;
204   }
205 
206   /**
207    * @brief Returns the layer type.
208    */
209    //返回层类型字符串,便于识别,由派生类实现
210   virtual inline const char* type() const { return ""; }
211 
212   /**
213    * @brief Returns the exact number of bottom blobs required by the layer,
214    *        or -1 if no exact number is required.
215    *
216    * This method should be overridden to return a non-negative value if your
217    * layer expects some exact number of bottom blobs.
218    */
219    //返回Layer需要的输入Bottom Blob数目,-1表示不关心,需要派生类实现
220   virtual inline int ExactNumBottomBlobs() const { return -1; }
221   /**
222    * @brief Returns the minimum number of bottom blobs required by the layer,
223    *        or -1 if no minimum number is required.
224    *
225    * This method should be overridden to return a non-negative value if your
226    * layer expects some minimum number of bottom blobs.
227    */
228   virtual inline int MinBottomBlobs() const { return -1; }
229   /**
230    * @brief Returns the maximum number of bottom blobs required by the layer,
231    *        or -1 if no maximum number is required.
232    *
233    * This method should be overridden to return a non-negative value if your
234    * layer expects some maximum number of bottom blobs.
235    */
236   virtual inline int MaxBottomBlobs() const { return -1; }
237   /**
238    * @brief Returns the exact number of top blobs required by the layer,
239    *        or -1 if no exact number is required.
240    *
241    * This method should be overridden to return a non-negative value if your
242    * layer expects some exact number of top blobs.
243    */
244   //返回Layer需要的输出Top Blob数目,-1表示不关心,需要派生类实现
245   virtual inline int ExactNumTopBlobs() const { return -1; }
246   /**
247    * @brief Returns the minimum number of top blobs required by the layer,
248    *        or -1 if no minimum number is required.
249    *
250    * This method should be overridden to return a non-negative value if your
251    * layer expects some minimum number of top blobs.
252    */
253   virtual inline int MinTopBlobs() const { return -1; }
254   /**
255    * @brief Returns the maximum number of top blobs required by the layer,
256    *        or -1 if no maximum number is required.
257    *
258    * This method should be overridden to return a non-negative value if your
259    * layer expects some maximum number of top blobs.
260    */
261   virtual inline int MaxTopBlobs() const { return -1; }
262   /**
263    * @brief Returns true if the layer requires an equal number of bottom and
264    *        top blobs.
265    *
266    * This method should be overridden to return true if your layer expects an
267    * equal number of bottom and top blobs.
268    */
269    //返回Layer是否有相同的输入输出Blob,需要派生类实现
270   virtual inline bool EqualNumBottomTopBlobs() const { return false; }
271 
272   /**
273    * @brief Return whether "anonymous" top blobs are created automatically
274    *        by the layer.
275    *
276    * If this method returns true, Net::Init will create enough "anonymous" top
277    * blobs to fulfill the requirement specified by ExactNumTopBlobs() or
278    * MinTopBlobs().
279    */
280    //返回是否允许匿名Top Blob,即由该层自动创建。
281    //如果为真,Net::Init 会创建足够多的匿名Top Blob来满足 ExactNumTopBlobs() or MinTopBlobs()需求
282   virtual inline bool AutoTopBlobs() const { return false; }
283 
284   /**
285    * @brief Return whether to allow force_backward for a given bottom blob
286    *        index.
287    *
288    * If AllowForceBackward(i) == false, we will ignore the force_backward
289    * setting and backpropagate to blob i only if it needs gradient information
290    * (as is done when force_backward == false).
291    */
292    //是否允许强制反向传播。如果AllowForceBackward(i) == false,忽略force_backward设定
293   virtual inline bool AllowForceBackward(const int bottom_index) const {
294     return true;
295   }
296 
297   /**
298    * @brief Specifies whether the layer should compute gradients w.r.t. a
299    *        parameter at a particular index given by param_id.
300    *
301    * You can safely ignore false values and always compute gradients
302    * for all parameters, but possibly with wasteful computation.
303    */
304    //该Layer是否计算相对权值或偏置项的梯度,具体相对谁由param_id指定
305   inline bool param_propagate_down(const int param_id) {
306     return (param_propagate_down_.size() > param_id) ?
307         param_propagate_down_[param_id] : false;
308   }
309   /**
310    * @brief Sets whether the layer should compute gradients w.r.t. a
311    *        parameter at a particular index given by param_id.
312    */
313    //设置该Layer是否计算相对权值或偏置项的梯度,具体相对谁由param_id指定
314   inline void set_param_propagate_down(const int param_id, const bool value) {
315     if (param_propagate_down_.size() <= param_id) {
316       param_propagate_down_.resize(param_id + 1, true);
317     }
318     param_propagate_down_[param_id] = value;
319   }
320 
321 
322  protected:
323   /** The protobuf that stores the layer parameters */
324   LayerParameter layer_param_;//保存Layer参数的ProtoBuffer对象
325   /** The phase: TRAIN or TEST */
326   Phase phase_;//Layer当前所属阶段,可选TRAIN或TEST
327   /** The vector that stores the learnable parameters as a set of blobs. */
328   vector<shared_ptr<Blob<Dtype> > > blobs_;//Layer内部权值偏置项,由Blob组织
329   /** Vector indicating whether to compute the diff of each param blob. */
330   vector<bool> param_propagate_down_;//标志位,是否计算对应的参数的误差梯度
331 
332   /** The vector that indicates whether each top blob has a non-zero weight in
333    *  the objective function. */
334   vector<Dtype> loss_;//标志位,在目标函数中是否每个Top Blob都有非零权值
335 
336   //以下四个函数会在派生类中经常看到
337   
338   /** @brief Using the CPU device, compute the layer output. */
339   virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
340       const vector<Blob<Dtype>*>& top) = 0;
341   /**
342    * @brief Using the GPU device, compute the layer output.
343    *        Fall back to Forward_cpu() if unavailable.
344    */
345   virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
346       const vector<Blob<Dtype>*>& top) {
347     // LOG(WARNING) << "Using CPU code as backup.";
348     return Forward_cpu(bottom, top);
349   }
350 
351   /**
352    * @brief Using the CPU device, compute the gradients for any parameters and
353    *        for the bottom blobs if propagate_down is true.
354    */
355   virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
356       const vector<bool>& propagate_down,
357       const vector<Blob<Dtype>*>& bottom) = 0;
358   /**
359    * @brief Using the GPU device, compute the gradients for any parameters and
360    *        for the bottom blobs if propagate_down is true.
361    *        Fall back to Backward_cpu() if unavailable.
362    */
363   virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
364       const vector<bool>& propagate_down,
365       const vector<Blob<Dtype>*>& bottom) {
366     // LOG(WARNING) << "Using CPU code as backup.";
367     Backward_cpu(top, propagate_down, bottom);
368   }
369 
370   /**
371    * Called by the parent Layer's SetUp to check that the number of bottom
372    * and top Blobs provided as input match the expected numbers specified by
373    * the {ExactNum,Min,Max}{Bottom,Top}Blobs() functions.
374    */
375    //校验输入输出Blob数目是否满足Layer要求
376   virtual void CheckBlobCounts(const vector<Blob<Dtype>*>& bottom,
377                                const vector<Blob<Dtype>*>& top) {
378     if (ExactNumBottomBlobs() >= 0) {
379       CHECK_EQ(ExactNumBottomBlobs(), bottom.size())
380           << type() << " Layer takes " << ExactNumBottomBlobs()
381           << " bottom blob(s) as input.";
382     }
383     if (MinBottomBlobs() >= 0) {
384       CHECK_LE(MinBottomBlobs(), bottom.size())
385           << type() << " Layer takes at least " << MinBottomBlobs()
386           << " bottom blob(s) as input.";
387     }
388     if (MaxBottomBlobs() >= 0) {
389       CHECK_GE(MaxBottomBlobs(), bottom.size())
390           << type() << " Layer takes at most " << MaxBottomBlobs()
391           << " bottom blob(s) as input.";
392     }
393     if (ExactNumTopBlobs() >= 0) {
394       CHECK_EQ(ExactNumTopBlobs(), top.size())
395           << type() << " Layer produces " << ExactNumTopBlobs()
396           << " top blob(s) as output.";
397     }
398     if (MinTopBlobs() >= 0) {
399       CHECK_LE(MinTopBlobs(), top.size())
400           << type() << " Layer produces at least " << MinTopBlobs()
401           << " top blob(s) as output.";
402     }
403     if (MaxTopBlobs() >= 0) {
404       CHECK_GE(MaxTopBlobs(), top.size())
405           << type() << " Layer produces at most " << MaxTopBlobs()
406           << " top blob(s) as output.";
407     }
408     if (EqualNumBottomTopBlobs()) {
409       CHECK_EQ(bottom.size(), top.size())
410           << type() << " Layer produces one top blob as output for each "
411           << "bottom blob input.";
412     }
413   }
414 
415   /**
416    * Called by SetUp to initialize the weights associated with any top blobs in
417    * the loss function. Store non-zero loss weights in the diff blob.
418    */
419    //该函数在Layer的Setup函数中调用,主要目的是初始化与TopBlob相关的loss权重,放到top blob的diff域
420    //实际由Forward()计算loss
421    //loss_weight==0 表示当前层不参与loss计算,大部分layer属于这一类
422    //loss_weight==1 表示当前层参与loss计算,损失层(LossLayer)属于这一类
423   inline void SetLossWeights(const vector<Blob<Dtype>*>& top) {
424     //从ProtoBuffer对象中获得Layer参数,这里需要loss_weight参数
425     const int num_loss_weights = layer_param_.loss_weight_size();
426     if (num_loss_weights) {//如果ProtoBuffer中至少有一个loss_weight 参数
427       //loss_weight个数应该与TopBlob相同,或者不要Loss_weigth参数
428       CHECK_EQ(top.size(), num_loss_weights) << "loss_weight must be "
429           "unspecified or specified once per top blob.";
430       //遍历每一个Top Blob
431       for (int top_id = 0; top_id < top.size(); ++top_id) {
432         //从ProtoBuffer对象中获得loss_weight参数(0或者1)
433         const Dtype loss_weight = layer_param_.loss_weight(top_id);
434         if (loss_weight == Dtype(0)) { continue; }//为0,跳过
435         this->set_loss(top_id, loss_weight);//不为0,进行网络的相关设置
436         const int count = top[top_id]->count();//本地记录loss_weight的值
437         Dtype* loss_multiplier = top[top_id]->mutable_cpu_diff();
438         //将loss_weight写入TopBlob的diff中,传递到需要使用的地方,实现远程同步
439         caffe_set(count, loss_weight, loss_multiplier);
440       }
441     }
442   }
443 
444  private:
445   DISABLE_COPY_AND_ASSIGN(Layer);//禁用拷贝构造函数和赋值运算函数
446 };  // class Layer
447 
448 // Forward and backward wrappers. You should implement the cpu and
449 // gpu specific implementations instead, and should not change these
450 // functions.
451 //前向传播函数、后向传播函数的包装,不需要修改这两个函数
452 //使用时只需要在派生类中改写Forward_cpu等
453 template <typename Dtype>
454 inline Dtype Layer<Dtype>::Forward(const vector<Blob<Dtype>*>& bottom,
455     const vector<Blob<Dtype>*>& top) {
456   Dtype loss = 0;
457   Reshape(bottom, top);
458   switch (Caffe::mode()) {//判断计算设备
459   case Caffe::CPU://在CPU上执行Forward计算
460     Forward_cpu(bottom, top);//调用CPU版本的Forward
461     //如果需要计算loss还需要进一步操作
462     for (int top_id = 0; top_id < top.size(); ++top_id) {
463       if (!this->loss(top_id)) { continue; }
464       const int count = top[top_id]->count();
465       //若为损失层,则已经通过Forward函数计算出全局损失函数,放在Top Blob data中
466       const Dtype* data = top[top_id]->cpu_data();
467       //若loss_weight不为0,则已经在SetLossWeight中将loss权重放在Top Blob diff 中
468       const Dtype* loss_weights = top[top_id]->cpu_diff();
469       loss += caffe_cpu_dot(count, data, loss_weights);//加权loss之和,得到标量loss
470     }
471     break;
472   case Caffe::GPU:
473     Forward_gpu(bottom, top);
474 #ifndef CPU_ONLY
475     for (int top_id = 0; top_id < top.size(); ++top_id) {
476       if (!this->loss(top_id)) { continue; }
477       const int count = top[top_id]->count();
478       const Dtype* data = top[top_id]->gpu_data();
479       const Dtype* loss_weights = top[top_id]->gpu_diff();
480       Dtype blob_loss = 0;
481       caffe_gpu_dot(count, data, loss_weights, &blob_loss);
482       loss += blob_loss;
483     }
484 #endif
485     break;
486   default:
487     LOG(FATAL) << "Unknown caffe mode.";
488   }
489   return loss;
490 }
491 //反向传播函数,直接调用对应设备函数
492 template <typename Dtype>
493 inline void Layer<Dtype>::Backward(const vector<Blob<Dtype>*>& top,
494     const vector<bool>& propagate_down,
495     const vector<Blob<Dtype>*>& bottom) {
496   switch (Caffe::mode()) {
497   case Caffe::CPU:
498     Backward_cpu(top, propagate_down, bottom);
499     break;
500   case Caffe::GPU:
501     Backward_gpu(top, propagate_down, bottom);
502     break;
503   default:
504     LOG(FATAL) << "Unknown caffe mode.";
505   }
506 }
507 //将层配置参数序列化为ProtoBuffer
508 // Serialize LayerParameter to protocol buffer
509 template <typename Dtype>
510 void Layer<Dtype>::ToProto(LayerParameter* param, bool write_diff) {
511   param->Clear();
512   param->CopyFrom(layer_param_);
513   param->clear_blobs();
514   for (int i = 0; i < blobs_.size(); ++i) {
515     blobs_[i]->ToProto(param->add_blobs(), write_diff);
516   }//权值偏置项也会保存
517 }
518 
519 }  // namespace caffe
520 
521 #endif  // CAFFE_LAYER_H_

 

 待更新

 

 

 

摘抄参考赵永科《深度学习 21天实战caffe》