| 419 | |
| 420 | template <typename Dtype> |
| 421 | void Net<Dtype>::AppendParam(const NetParameter& param, const int layer_id, |
| 422 | const int param_id) { |
| 423 | const LayerParameter& layer_param = layers_[layer_id]->layer_param(); |
| 424 | const int param_size = layer_param.param_size(); |
| 425 | string param_name = |
| 426 | (param_size > param_id) ? layer_param.param(param_id).name() : ""; |
| 427 | if (param_name.size()) { |
| 428 | param_display_names_.push_back(param_name); |
| 429 | } else { |
| 430 | ostringstream param_display_name; |
| 431 | param_display_name << param_id; |
| 432 | param_display_names_.push_back(param_display_name.str()); |
| 433 | } |
| 434 | const int net_param_id = params_.size(); |
| 435 | params_.push_back(layers_[layer_id]->blobs()[param_id]); |
| 436 | param_id_vecs_[layer_id].push_back(net_param_id); |
| 437 | param_layer_indices_.push_back(make_pair(layer_id, param_id)); |
| 438 | ParamSpec default_param_spec; |
| 439 | const ParamSpec* param_spec = (layer_param.param_size() > param_id) ? |
| 440 | &layer_param.param(param_id) : &default_param_spec; |
| 441 | if (!param_size || !param_name.size() || (param_name.size() && |
| 442 | param_names_index_.find(param_name) == param_names_index_.end())) { |
| 443 | // This layer "owns" this parameter blob -- it is either anonymous |
| 444 | // (i.e., not given a param_name) or explicitly given a name that we |
| 445 | // haven't already seen. |
| 446 | param_owners_.push_back(-1); |
| 447 | if (param_name.size()) { |
| 448 | param_names_index_[param_name] = net_param_id; |
| 449 | } |
| 450 | const int learnable_param_id = learnable_params_.size(); |
| 451 | learnable_params_.push_back(params_[net_param_id].get()); |
| 452 | learnable_param_ids_.push_back(learnable_param_id); |
| 453 | has_params_lr_.push_back(param_spec->has_lr_mult()); |
| 454 | has_params_decay_.push_back(param_spec->has_decay_mult()); |
| 455 | params_lr_.push_back(param_spec->lr_mult()); |
| 456 | params_weight_decay_.push_back(param_spec->decay_mult()); |
| 457 | } else { |
| 458 | // Named param blob with name we've seen before: share params |
| 459 | const int owner_net_param_id = param_names_index_[param_name]; |
| 460 | param_owners_.push_back(owner_net_param_id); |
| 461 | const pair<int, int>& owner_index = |
| 462 | param_layer_indices_[owner_net_param_id]; |
| 463 | const int owner_layer_id = owner_index.first; |
| 464 | const int owner_param_id = owner_index.second; |
| 465 | LOG_IF(INFO, Caffe::root_solver()) << "Sharing parameters '" << param_name |
| 466 | << "' owned by " |
| 467 | << "layer '" << layer_names_[owner_layer_id] << "', param " |
| 468 | << "index " << owner_param_id; |
| 469 | Blob<Dtype>* this_blob = layers_[layer_id]->blobs()[param_id].get(); |
| 470 | Blob<Dtype>* owner_blob = |
| 471 | layers_[owner_layer_id]->blobs()[owner_param_id].get(); |
| 472 | const int param_size = layer_param.param_size(); |
| 473 | if (param_size > param_id && (layer_param.param(param_id).share_mode() == |
| 474 | ParamSpec_DimCheckMode_PERMISSIVE)) { |
| 475 | // Permissive dimension checking -- only check counts are the same. |
| 476 | CHECK_EQ(this_blob->count(), owner_blob->count()) |
| 477 | << "Cannot share param '" << param_name << "' owned by layer '" |
| 478 | << layer_names_[owner_layer_id] << "' with layer '" |