1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
| class Layer {
protected: LayerParameter layer_param_; Phase phase_; vector<shared_ptr<Blob<Dtype>>> blobs_; vector<bool> param_propagate_down_; vector<Dtype> loss_;
public: explicit Layer(const LayerParameter& param) : layer_param_(param) { phase_ = param.phase(); if (layer_param_.blobs_size() > 0) { blobs_.resize(layer_param_.blobs_size()); for (int i = 0; i < layer_param_.blobs_size(); ++i) { blobs_[i].reset(new Blob<Dtype>()); blobs_[i]->FromProto(layer_param_.blobs(i)); } } } virtual ~Layer() {}
void SetUp(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { CheckBlobCounts(bottom, top); LayerSetUp(bottom, top); Reshape(bottom, top); SetLossWeights(top); }
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) = 0;
inline Dtype Forward(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top);
inline void Backward(const vector<Blob<Dtype>*>& top, const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
vector<shared_ptr<Blob<Dtype> > >& blobs() { return blobs_; }
const LayerParameter& layer_param() const { return layer_param_; }
virtual void ToProto(LayerParameter* param, bool write_diff = false);
inline Dtype loss(const int top_index) const { return (loss_.size() > top_index) ? loss_[top_index] : Dtype(0); }
inline void set_loss(const int top_index, const Dtype value) { if (loss_.size() <= top_index) { loss_.resize(top_index + 1, Dtype(0)); } loss_[top_index] = value; }
virtual inline const char* type() const { return ""; }
virtual inline int ExactNumBottomBlobs() const { return -1; } virtual inline int MinBottomBlobs() const { return -1; } virtual inline int MaxBottomBlobs() const { return -1; } virtual inline int ExactNumTopBlobs() const { return -1; } virtual inline int MinTopBlobs() const { return -1; } virtual inline int MaxTopBlobs() const { return -1; }
virtual inline bool EqualNumBottomTopBlobs() const { return false; }
virtual inline bool AutoTopBlobs() const { return false; }
virtual inline bool AllowForceBackward(const int bottom_index) const { return true; }
inline bool param_propagate_down(const int param_id) { return (param_propagate_down_.size() > param_id) ? param_propagate_down_[param_id] : false; }
inline void set_param_propagate_down(const int param_id, const bool value) { if (param_propagate_down_.size() <= param_id) { param_propagate_down_.resize(param_id + 1, true); } param_propagate_down_[param_id] = value; }
protected:
virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) = 0; virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { return Forward_cpu(bottom, top); } virtual void Backward_cpu(const vector<Blob<Dtype>*>& top, const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) = 0; virtual void Backward_gpu(const vector<Blob<Dtype>*>& top, const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) { Backward_cpu(top, propagate_down, bottom); }
virtual void CheckBlobCounts(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { if (ExactNumBottomBlobs() >= 0) { CHECK_EQ(ExactNumBottomBlobs(), bottom.size()) << type() << " Layer takes " << ExactNumBottomBlobs() << " bottom blob(s) as input."; } if (MinBottomBlobs() >= 0) { CHECK_LE(MinBottomBlobs(), bottom.size()) << type() << " Layer takes at least " << MinBottomBlobs() << " bottom blob(s) as input."; } if (MaxBottomBlobs() >= 0) { CHECK_GE(MaxBottomBlobs(), bottom.size()) << type() << " Layer takes at most " << MaxBottomBlobs() << " bottom blob(s) as input."; } if (ExactNumTopBlobs() >= 0) { CHECK_EQ(ExactNumTopBlobs(), top.size()) << type() << " Layer produces " << ExactNumTopBlobs() << " top blob(s) as output."; } if (MinTopBlobs() >= 0) { CHECK_LE(MinTopBlobs(), top.size()) << type() << " Layer produces at least " << MinTopBlobs() << " top blob(s) as output."; } if (MaxTopBlobs() >= 0) { CHECK_GE(MaxTopBlobs(), top.size()) << type() << " Layer produces at most " << MaxTopBlobs() << " top blob(s) as output."; } if (EqualNumBottomTopBlobs()) { CHECK_EQ(bottom.size(), top.size()) << type() << " Layer produces one top blob as output for each " << "bottom blob input."; } }
inline void SetLossWeights(const vector<Blob<Dtype>*>& top) { const int num_loss_weights = layer_param_.loss_weight_size(); if (num_loss_weights) { CHECK_EQ(top.size(), num_loss_weights) << "loss_weight must be " "unspecified or specified once per top blob."; for (int top_id = 0; top_id < top.size(); ++top_id) { const Dtype loss_weight = layer_param_.loss_weight(top_id); if (loss_weight == Dtype(0)) { continue; } this->set_loss(top_id, loss_weight); const int count = top[top_id]->count(); Dtype* loss_multiplier = top[top_id]->mutable_cpu_diff(); caffe_set(count, loss_weight, loss_multiplier); } } }
private: DISABLE_COPY_AND_ASSIGN(Layer); };
|