void ReshapeLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { const int input_start_axis = this->layer_param_.reshape_param().axis(); const int start_axis = (input_start_axis >= 0) ? input_start_axis : bottom[0]->num_axes() + input_start_axis + 1; CHECK_GE(start_axis, 0) << "axis " << input_start_axis << " out of range"; CHECK_LE(start_axis, bottom[0]->num_axes()) << "axis " << input_start_axis << " out of range for " << bottom[0]->num_axes() << "-D input blob"; const int num_axes = this->layer_param_.reshape_param().num_axes(); CHECK_GE(num_axes, -1) << "num_axes must be >= 0, or -1 for all"; const int end_axis = (num_axes == -1) ? bottom[0]->num_axes() : (start_axis + num_axes); CHECK_LE(end_axis, bottom[0]->num_axes()) << "end_axis = axis + num_axes is out of range"; const int num_axes_replaced = end_axis - start_axis; const int num_axes_retained = bottom[0]->num_axes() - num_axes_replaced; const BlobShape& top_blob_shape = this->layer_param_.reshape_param().shape(); const int num_new_axes = top_blob_shape.dim_size(); vector<int> top_shape(num_axes_retained + num_new_axes); int top_shape_index = 0; for (int i = 0; i < start_axis; ++i) { top_shape[top_shape_index++] = bottom[0]->shape(i); } for (int i = 0; i < num_new_axes; ++i) { top_shape[top_shape_index++] = top_blob_shape.dim(i); } for (int i = end_axis; i < bottom[0]->num_axes(); ++i) { top_shape[top_shape_index++] = bottom[0]->shape(i); } CHECK_EQ(top_shape_index, top_shape.size()); for (int i = 0; i < copy_axes_.size(); ++i) { const int copy_axis_index = copy_axes_[i]; CHECK_GT(bottom[0]->num_axes(), start_axis + copy_axis_index) << "new shape contains a 0, but there was no corresponding bottom axis " << "to copy"; top_shape[start_axis + copy_axis_index] = bottom[0]->shape(start_axis + copy_axis_index); } if (inferred_axis_ >= 0) { // A -1 dim was specified; infer the correct dimension by computing the // product of the other dimensions. int explicit_count = constant_count_; explicit_count *= bottom[0]->count(0, start_axis); explicit_count *= bottom[0]->count(end_axis); for (int i = 0; i < copy_axes_.size(); ++i) { const int copy_axis_index = copy_axes_[i]; explicit_count *= top_shape[start_axis + copy_axis_index]; } CHECK_EQ(0, bottom[0]->count() % explicit_count) << "bottom count (" << bottom[0]->count() << ") must be divisible by the product of " << "the specified dimensions (" << explicit_count << ")"; const int inferred_dim = bottom[0]->count() / explicit_count; top_shape[start_axis + inferred_axis_] = inferred_dim; } top[0]->Reshape(top_shape); CHECK_EQ(top[0]->count(), bottom[0]->count()) << "output count must match input count"; top[0]->ShareData(*bottom[0]); top[0]->ShareDiff(*bottom[0]); }
void ReductionLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { axis_ = bottom[0]->CanonicalAxisIndex( this->layer_param_.reduction_param().axis()); // In the output, we'll keep all axes up to the reduction axis, but // throw away any after that. // Note: currently reducing along non-tail axes is not supported; otherwise, // we'd need to also copy any axes following an "end_axis". vector<int> top_shape(bottom[0]->shape().begin(), bottom[0]->shape().begin() + axis_); top[0]->Reshape(top_shape); num_ = bottom[0]->count(0, axis_); dim_ = bottom[0]->count(axis_); CHECK_EQ(num_, top[0]->count()); if (op_ == ReductionParameter_ReductionOp_SUM || op_ == ReductionParameter_ReductionOp_MEAN) { vector<int> sum_mult_shape(1, dim_); sum_multiplier_.Reshape(sum_mult_shape); caffe_set(dim_, Dtype(1), sum_multiplier_.mutable_cpu_data()); } coeff_ = this->layer_param().reduction_param().coeff(); if (op_ == ReductionParameter_ReductionOp_MEAN) { coeff_ /= dim_; } }
void AccuracyLayer<Dtype>::Reshape( const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { CHECK_LE(top_k_, bottom[0]->count() / bottom[1]->count()) << "top_k must be less than or equal to the number of classes."; label_axis_ = bottom[0]->CanonicalAxisIndex(this->layer_param_.accuracy_param().axis()); outer_num_ = bottom[0]->count(0, label_axis_); inner_num_ = bottom[0]->count(label_axis_ + 1); CHECK_EQ(outer_num_ * inner_num_, bottom[1]->count()) << "Number of labels must match number of predictions; " << "e.g., if label axis == 1 and prediction shape is (N, C, H, W), " << "label count (number of labels) must be N*H*W, " << "with integer values in {0, 1, ..., C-1}."; if (bottom.size() == 3) { CHECK_EQ(outer_num_ * inner_num_, bottom[2]->count()) << "Number of loss weights must match number of label."; } vector<int> top_shape(0); // Accuracy is a scalar; 0 axes. top[0]->Reshape(top_shape); if (top.size() > 1) { // Per-class accuracy is a vector; 1 axes. vector<int> top_shape_per_class(1); top_shape_per_class[0] = bottom[0]->shape(label_axis_); top[1]->Reshape(top_shape_per_class); nums_buffer_.Reshape(top_shape_per_class); } }
void EvalDetectionLayer<Dtype>::Reshape( const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { int input_count = bottom[0]->count(1); //13*13*125 / 13*13*425 网络输出 int label_count = bottom[1]->count(1); //30*5 标签 预设30个物体 4边框+1类别 // outputs: classes, iou, coordinates //int tmp_input_count = side_ * side_ * (num_class_ + (1 + 4) * num_object_); int tmp_input_count = side_ * side_ * num_object_ *( num_class_ + 4 + 1 ); //13*13*5*25 // label: isobj, class_label, coordinates //int tmp_label_count = side_ * side_ * (1 + 1 + 1 + 4); int tmp_label_count = 30 * 5;// // LOG(INFO) << " label[0] : " << bottom[1]->count(0) << "================================"; CHECK_EQ(input_count, tmp_input_count);// 确保网络输出 每张图片为 13*13*5*25 大小 // 13*13个格子,每个格子预测5种边框,每种边框预测 20类概率+4边框参数+1置信度 CHECK_EQ(label_count, tmp_label_count);// 而标签输入 每张图片为 30*5 大小 30个物体边框,4个边框参数+1个类别标签 vector<int> top_shape(2, 1);// 两行一列 全1 //vector<int> top_shape(3, 1);// 三行一列 添加一列 存储mAP top_shape[0] = bottom[0]->num();// 图片数量 //top_shape[1] = num_class_ + side_ * side_ * num_object_ * 4; // 20 + 13*13*5*4 标签 得分 TP FP // top_shape[1] = num_class_ + side_ * side_ * num_object_ * 4 + 1; // 各个类别预测数量, 20类检测数量 + 13*13*5*(label + score + tp + fp) + 该图片mAP top_shape[1] = side_ * side_ * num_object_ * 4 + 1; // 13*13*5*(label + score + tp + fp) + 该图片mAP //top_shape[2] = 1;// 添加一列 存储mAP top[0]->Reshape(top_shape); }
void EuclideanAccuracyLayer<Dtype>::Reshape( const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { batch_size_ = bottom[0]->shape(0); CHECK_EQ(batch_size_ , bottom[1]->count()) << "Number of labels must match number of predictions; "; vector<int> top_shape(0); // Accuracy is a scalar; 0 axes. top[0]->Reshape(top_shape); }
void MyAccuracyLayer<Dtype>::Reshape( const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { CHECK_EQ(bottom[0]->num() , bottom[1]->num()); CHECK_EQ(bottom[0]->channels() , bottom[1]->channels()); CHECK_EQ(bottom[0]->height() , bottom[1]->height()); CHECK_EQ(bottom[0]->width() , bottom[1]->width()); vector<int> top_shape(0); // Accuracy is a scalar; 0 axes. top[0]->Reshape(top_shape); }
void ContextDataLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { // Initialize with the first blob. vector<int> top_shape(2); top_shape[0] = bottom[0]->shape(0); top_shape[1] = bottom[1]->shape(1); top[0]->Reshape(top_shape); //1x500 the context vector input to the lstm2 //CHECK_EQ(bottom_count_sum, top[0]->count()); }
void LastRowLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { CHECK_EQ(3, bottom[0]->num_axes()); vector<int> top_shape(3); top_shape[0] = bottom[0]->shape(1); top_shape[1] = 1; top_shape[2] = bottom[0]->shape(2); top[0]->Reshape(top_shape); }
void AccuracyLayer<Dtype>::Reshape( const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { CHECK_LE(top_k_, bottom[0]->count() / bottom[1]->count()) << "top_k must be less than or equal to the number of classes."; CHECK_GE(bottom[0]->num_axes(), bottom[1]->num_axes()); for (int i = 0; i < bottom[1]->num_axes(); ++i) { CHECK_LE(bottom[0]->shape(i), bottom[1]->shape(i)) << "Dimension mismatch between predictions and label."; } vector<int> top_shape(0); // Accuracy is a scalar; 0 axes. top[0]->Reshape(top_shape); }
void SparseInnerProductLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { // The top shape will M_ * N_ vector<int> top_shape(2, M_); top_shape[1] = N_; top[0]->Reshape(top_shape); // Set up the bias multiplier if (bias_term_) { vector<int> bias_shape(1, M_); bias_multiplier_.Reshape(bias_shape); caffe_set(M_, Dtype(1), bias_multiplier_.mutable_cpu_data()); } }
void MultiClassAccuracyLayer<Dtype>::Reshape( const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { label_axis_ = bottom[0]->CanonicalAxisIndex(this->layer_param_.accuracy_param().axis()); vector<int> top_shape(0); // Accuracy is a scalar; 0 axes. top[0]->Reshape(top_shape); top[1]->Reshape(top_shape); top[2]->Reshape(top_shape); top[3]->Reshape(top_shape); top[4]->Reshape(top_shape); CHECK_EQ(bottom[0]->count(), bottom[1]->count()); this->threshold_ = this->layer_param_.accuracy_param().bag_threshold(); }
void Pooling3DLayer<Dtype>::Reshape(const vector<Blob<Dtype> *> &bottom, const vector<Blob<Dtype> *> &top) { CHECK_EQ(5, bottom[0]->num_axes()) << "Input must have 5 axes, " << "corresponding to (num, channels, length, height, width)"; int num = bottom[0]->shape()[0]; int vv[5] = {num, channels_, pooled_length_, pooled_height_, pooled_width_}; vector<int> top_shape(vv, vv+5); top[0]->Reshape(top_shape); // If stochastic pooling, we will initialize the random index part. if (this->layer_param_.pooling3d_param().pool() == Pooling3DParameter_PoolMethod_STOCHASTIC) { rand_idx_.Reshape(top_shape); } }
void ConvolutionLayerSpatial<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { BaseConvolutionLayer<Dtype>::Reshape(bottom, top); height_ = bottom[0]->shape(this->channel_axis_ + 1); width_ = bottom[0]->shape(this->channel_axis_ + 2); output_h_ = (height_ + 2 * pad_h_ - kernel_h_) / stride_h_ + 1; output_w_ = (width_ + 2 * pad_w_ - kernel_w_) / stride_w_ + 1; padded_width_ = width_ + 2 * pad_w_; padded_height_ = height_ + 2 * pad_h_; // Shape the tops. vector<int_tp> top_shape(bottom[0]->shape().begin(), bottom[0]->shape().begin() + this->channel_axis_); top_shape.push_back(this->num_output_); for (int_tp i = 0; i < this->num_spatial_axes_; ++i) { top_shape.push_back(this->output_shape_[i]); } for (int_tp top_id = 0; top_id < top.size(); ++top_id) { top[top_id]->Reshape(top_shape); } CHECK_EQ(2, this->num_spatial_axes_) << "ConvolutionSpatial input must have 2 spatial axes " << "(e.g., height and width). "; const int_tp height_out = top[0]->shape(this->channel_axis_ + 1); const int_tp width_out = top[0]->shape(this->channel_axis_ + 2); N_ = height_out * width_out; // The im2col result buffer will only hold one image at a time to avoid // overly large memory usage. spatial_col_buffer_.Reshape(this->num_, this->channels_, height_ + 2 * pad_h_, width_ + 2 * pad_w_); swizzled_weights_.Reshape(this->num_output_, this->channels_, kernel_h_ + 2 * pad_h_, kernel_w_ + 2 * pad_w_); // Set up the all ones "bias multiplier" for adding biases by BLAS if (this->bias_term_) { bias_multiplier_.Reshape(1, 1, 1, N_); caffe_set(N_, Dtype(1), bias_multiplier_.mutable_cpu_data()); } if (std::is_same<Dtype, float>::value) { this->num_ = bottom[0]->count(0, this->channel_axis_); SetUp(bottom, top, Caffe::GetDefaultDevice()->backend()); } }
void AccuracyLayer<Dtype>::Reshape( const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { CHECK_LE(top_k_, bottom[0]->count() / bottom[1]->count()) << "top_k must be less than or equal to the number of classes."; label_axis_ = bottom[0]->CanonicalAxisIndex(this->layer_param_.accuracy_param().axis()); outer_num_ = bottom[0]->count(0, label_axis_); inner_num_ = bottom[0]->count(label_axis_ + 1); CHECK_EQ(outer_num_ * inner_num_, bottom[1]->count()) << "Number of labels must match number of predictions; " << "e.g., if label axis == 1 and prediction shape is (N, C, H, W), " << "label count (number of labels) must be N*H*W, " << "with integer values in {0, 1, ..., C-1}."; //vector<int> top_shape(0); // Accuracy is a scalar; 0 axes. vector<int> top_shape(1); top_shape[0] = 7; top[0]->Reshape(top_shape); }
void PermuteLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { PermuteParameter permute_param = this->layer_param_.permute_param(); CHECK_EQ(bottom.size(), 1); num_axes_ = bottom[0]->num_axes(); vector<int> orders; // Push the specified new orders. for (int i = 0; i < permute_param.order_size(); ++i) { int order = permute_param.order(i); CHECK_LT(order, num_axes_) << "order should be less than the input dimension."; if (std::find(orders.begin(), orders.end(), order) != orders.end()) { LOG(FATAL) << "there are duplicate orders"; } orders.push_back(order); } // Push the rest orders. And save original step sizes for each axis. for (int i = 0; i < num_axes_; ++i) { if (std::find(orders.begin(), orders.end(), i) == orders.end()) { orders.push_back(i); } } CHECK_EQ(num_axes_, orders.size()); // Check if we need to reorder the data or keep it. need_permute_ = false; for (int i = 0; i < num_axes_; ++i) { if (orders[i] != i) { // As long as there is one order which is different from the natural order // of the data, we need to permute. Otherwise, we share the data and diff. need_permute_ = true; break; } } vector<int> top_shape(num_axes_, 1); permute_order_.Reshape(num_axes_, 1, 1, 1); old_steps_.Reshape(num_axes_, 1, 1, 1); new_steps_.Reshape(num_axes_, 1, 1, 1); for (int i = 0; i < num_axes_; ++i) { permute_order_.mutable_cpu_data()[i] = orders[i]; top_shape[i] = bottom[0]->shape(orders[i]); } top[0]->Reshape(top_shape); }
void ReformLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { CHECK_EQ(bottom[0]->shape(2), bottom[0]->shape(3)) << "only support square for now"; const BlobShape& tbs = this->layer_param_.reform_param().shape(); const int top_num_axes = tbs.dim_size(); vector<int> patch_dim(top_num_axes); patch_dim[0] = 1; patch_dim[1] = 1; patch_dim[2] = patch_size_; patch_dim[3] = patch_size_; top_shape_ = vector<int>(top_num_axes,0); int top_shape_index = 0; vector<int> top_shape(top_num_axes, 0); for (int i = 0; i < top_num_axes; ++i) { top_shape_[top_shape_index++] = tbs.dim(i) * patch_dim[i]; } top[0]->Reshape(top_shape_); CHECK_EQ(top[0]->shape(0), 1)<<"1"; CHECK_EQ(top[0]->shape(1), 2)<<"2"; CHECK_EQ(top[0]->shape(2), 384)<<"3"; CHECK_EQ(top[0]->shape(3), 512)<<"4"; }
void BaseConvolutionLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { if (is_direct_connect_ && !is_direct_intialized_) { direct_num_ = std::min((int)((direct_ratio_)*(num_output_ / (1 - direct_ratio_))), bottom[0]->channels()); this->blobs_.push_back(shared_ptr<Blob<Dtype> >()); vector<int> idx_shape; idx_shape.push_back(direct_num_); int idx_param_idx = this->blobs_.size() - 1; this->blobs_[idx_param_idx].reset(new Blob<Dtype>(idx_shape)); vector<int> idx_tmp; for (int i = 0; i < bottom[0]->channels(); i++) idx_tmp.push_back(i); std::random_shuffle(idx_tmp.begin(), idx_tmp.end()); for (int i = 0; i < direct_num_; i++) //direct_idx_.push_back(idx_tmp[i]); this->blobs_[idx_param_idx]->mutable_cpu_data()[i] = idx_tmp[i]; is_direct_intialized_ = true; } const int first_spatial_axis = channel_axis_ + 1; CHECK_EQ(bottom[0]->num_axes(), first_spatial_axis + num_spatial_axes_) << "bottom num_axes may not change."; num_ = bottom[0]->count(0, channel_axis_); CHECK_EQ(bottom[0]->shape(channel_axis_), channels_) << "Input size incompatible with convolution kernel."; // TODO: generalize to handle inputs of different shapes. for (int bottom_id = 1; bottom_id < bottom.size(); ++bottom_id) { CHECK(bottom[0]->shape() == bottom[bottom_id]->shape()) << "All inputs must have the same shape."; } // Shape the tops. bottom_shape_ = &bottom[0]->shape(); compute_output_shape(); vector<int> top_shape(bottom[0]->shape().begin(), bottom[0]->shape().begin() + channel_axis_); if (is_direct_connect_) top_shape.push_back(num_output_ + direct_num_); else top_shape.push_back(num_output_); for (int i = 0; i < num_spatial_axes_; ++i) { top_shape.push_back(output_shape_[i]); } for (int top_id = 0; top_id < top.size(); ++top_id) { top[top_id]->Reshape(top_shape); } if (reverse_dimensions()) { conv_out_spatial_dim_ = bottom[0]->count(first_spatial_axis); } else { conv_out_spatial_dim_ = top[0]->count(first_spatial_axis); } col_offset_ = kernel_dim_ * conv_out_spatial_dim_; output_offset_ = conv_out_channels_ * conv_out_spatial_dim_ / group_; // Setup input dimensions (conv_input_shape_). vector<int> bottom_dim_blob_shape(1, num_spatial_axes_ + 1); conv_input_shape_.Reshape(bottom_dim_blob_shape); int* conv_input_shape_data = conv_input_shape_.mutable_cpu_data(); for (int i = 0; i < num_spatial_axes_ + 1; ++i) { if (reverse_dimensions()) { conv_input_shape_data[i] = top[0]->shape(channel_axis_ + i); } else { conv_input_shape_data[i] = bottom[0]->shape(channel_axis_ + i); } } // The im2col result buffer will only hold one image at a time to avoid // overly large memory usage. In the special case of 1x1 convolution // it goes lazily unused to save memory. col_buffer_shape_.clear(); col_buffer_shape_.push_back(kernel_dim_ * group_); for (int i = 0; i < num_spatial_axes_; ++i) { if (reverse_dimensions()) { col_buffer_shape_.push_back(input_shape(i + 1)); } else { col_buffer_shape_.push_back(output_shape_[i]); } } col_buffer_.Reshape(col_buffer_shape_); bottom_dim_ = bottom[0]->count(channel_axis_); if (is_direct_connect_) top_dim_ = top[0]->count(channel_axis_) * num_output_ / (direct_num_ + num_output_); else top_dim_ = top[0]->count(channel_axis_); num_kernels_im2col_ = conv_in_channels_ * conv_out_spatial_dim_; num_kernels_col2im_ = reverse_dimensions() ? top_dim_ : bottom_dim_; // Set up the all ones "bias multiplier" for adding biases by BLAS out_spatial_dim_ = top[0]->count(first_spatial_axis); if (bias_term_) { vector<int> bias_multiplier_shape(1, out_spatial_dim_); bias_multiplier_.Reshape(bias_multiplier_shape); caffe_set(bias_multiplier_.count(), Dtype(1), bias_multiplier_.mutable_cpu_data()); } }
void BaseConvolutionLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { const int_tp first_spatial_axis = channel_axis_ + 1; CHECK_EQ(bottom[0]->num_axes(), first_spatial_axis + num_spatial_axes_) << "bottom num_axes may not change."; num_ = bottom[0]->count(0, channel_axis_); CHECK_EQ(bottom[0]->shape(channel_axis_), channels_) << "Input size incompatible with convolution kernel."; // TODO: generalize to handle inputs of different shapes. for (int_tp bottom_id = 1; bottom_id < bottom.size(); ++bottom_id) { CHECK(bottom[0]->shape() == bottom[bottom_id]->shape()) << "All inputs must have the same shape."; } // Shape the tops. bottom_shape_ = &bottom[0]->shape(); compute_output_shape(); vector<int_tp> top_shape(bottom[0]->shape().begin(), bottom[0]->shape().begin() + channel_axis_); top_shape.push_back(num_output_); for (int_tp i = 0; i < num_spatial_axes_; ++i) { top_shape.push_back(output_shape_[i]); } for (int_tp top_id = 0; top_id < top.size(); ++top_id) { top[top_id]->Reshape(top_shape); } if (reverse_dimensions()) { conv_out_spatial_dim_ = bottom[0]->count(first_spatial_axis); } else { conv_out_spatial_dim_ = top[0]->count(first_spatial_axis); } col_offset_ = kernel_dim_ * conv_out_spatial_dim_; output_offset_ = conv_out_channels_ * conv_out_spatial_dim_ / group_; // Setup input dimensions (conv_input_shape_). vector<int_tp> bottom_dim_blob_shape(1, num_spatial_axes_ + 1); conv_input_shape_.Reshape(bottom_dim_blob_shape); int_tp* conv_input_shape_data = conv_input_shape_.mutable_cpu_data(); for (int_tp i = 0; i < num_spatial_axes_ + 1; ++i) { if (reverse_dimensions()) { conv_input_shape_data[i] = top[0]->shape(channel_axis_ + i); } else { conv_input_shape_data[i] = bottom[0]->shape(channel_axis_ + i); } } // The im2col result buffer will only hold one image at a time to avoid // overly large memory usage. In the special case of 1x1 convolution // it goes lazily unused to save memory. col_buffer_shape_.clear(); col_buffer_shape_.push_back(kernel_dim_ * group_); for (int_tp i = 0; i < num_spatial_axes_; ++i) { if (reverse_dimensions()) { col_buffer_shape_.push_back(input_shape(i + 1)); } else { col_buffer_shape_.push_back(output_shape_[i]); } } col_buffer_.Reshape(col_buffer_shape_); if (Caffe::mode() == Caffe::Brew::GPU) { // Shared column buffer per device-queue across all layers on that device for (int_tp i = 0; i < this->device_->num_queues(); ++i) { shared_ptr<Blob<Dtype> > buffer = this->device_ ->template Buffer<Dtype>(i); buffer->Reshape(col_buffer_shape_); } } bottom_dim_ = bottom[0]->count(channel_axis_); top_dim_ = top[0]->count(channel_axis_); num_kernels_im2col_ = conv_in_channels_ * conv_out_spatial_dim_; num_kernels_col2im_ = reverse_dimensions() ? top_dim_ : bottom_dim_; // Set up the all ones "bias multiplier" for adding biases by BLAS out_spatial_dim_ = top[0]->count(first_spatial_axis); if (bias_term_) { vector<int_tp> bias_multiplier_shape(1, out_spatial_dim_); bool reshaped = bias_multiplier_.Reshape(bias_multiplier_shape); // This will trigger a memory copy if in GPU mode, // which may not be necessary. // Thus omit to set the values if not necessary. if (reshaped) { caffe_set(bias_multiplier_.count(), Dtype(1), bias_multiplier_.mutable_cpu_data()); } } }
void BaseConvolutionLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { const int num_axes = bottom[0]->num_axes(); // Setting forced_3d_ in LayerSetup() alone is not sufficient as that can be // skipped and Reshape() is directed called. if (num_axes == 5 && channel_axis_ == 1 && bottom[0]->shape(2) == 1) { forced_3d_ = true; } else { forced_3d_ = false; } const int first_spatial_axis = channel_axis_ + 1 + forced_3d_; CHECK_EQ(num_axes, first_spatial_axis + num_spatial_axes_) << "bottom num_axes may not change."; num_ = bottom[0]->count(0, channel_axis_); CHECK_EQ(bottom[0]->shape(channel_axis_), channels_) << "Input size incompatible with convolution kernel."; // TODO: generalize to handle inputs of different shapes. for (int bottom_id = 1; bottom_id < bottom.size(); ++bottom_id) { CHECK(bottom[0]->shape() == bottom[bottom_id]->shape()) << "shape mismatch - bottom[0]: " << bottom[0]->shape_string() << " vs. bottom[" << bottom_id << "]: " << bottom[bottom_id]->shape_string(); } // Shape the tops. bottom_shape_ = &bottom[0]->shape(); compute_output_shape(); vector<int> top_shape(bottom[0]->shape().begin(), bottom[0]->shape().begin() + channel_axis_); top_shape.push_back(num_output_); if (forced_3d_) top_shape.push_back(1); // in place of length for (int i = 0; i < num_spatial_axes_; ++i) { top_shape.push_back(output_shape_[i]); } for (int top_id = 0; top_id < top.size(); ++top_id) { top[top_id]->Reshape(top_shape); } if (reverse_dimensions()) { conv_out_spatial_dim_ = bottom[0]->count(first_spatial_axis); } else { conv_out_spatial_dim_ = top[0]->count(first_spatial_axis); } col_offset_ = kernel_dim_ * conv_out_spatial_dim_; output_offset_ = conv_out_channels_ * conv_out_spatial_dim_ / group_; // Setup input dimensions (conv_input_shape_). vector<int> bottom_dim_blob_shape(1, num_spatial_axes_ + 1); conv_input_shape_.Reshape(bottom_dim_blob_shape); int* conv_input_shape_data = conv_input_shape_.mutable_cpu_data(); for (int i = 0; i < num_spatial_axes_ + 1; ++i) { if (reverse_dimensions()) { conv_input_shape_data[i] = top[0]->shape(channel_axis_ + i + forced_3d_); } else { conv_input_shape_data[i] = bottom[0]->shape(channel_axis_ + i + forced_3d_); } } // The im2col result buffer will only hold one image at a time to avoid // overly large memory usage. In the special case of 1x1 convolution // it goes lazily unused to save memory. col_buffer_shape_.clear(); col_buffer_shape_.push_back(kernel_dim_ * group_); for (int i = 0; i < num_spatial_axes_; ++i) { if (reverse_dimensions()) { col_buffer_shape_.push_back(input_shape(i + 1)); } else { col_buffer_shape_.push_back(output_shape_[i]); } } col_buffer_.Reshape(col_buffer_shape_); bottom_dim_ = bottom[0]->count(channel_axis_); top_dim_ = top[0]->count(channel_axis_); num_kernels_im2col_ = conv_in_channels_ * conv_out_spatial_dim_; num_kernels_col2im_ = reverse_dimensions() ? top_dim_ : bottom_dim_; // Set up the all ones "bias multiplier" for adding biases by BLAS out_spatial_dim_ = top[0]->count(first_spatial_axis); if (bias_term_) { vector<int> bias_multiplier_shape(1, out_spatial_dim_); bias_multiplier_.Reshape(bias_multiplier_shape); caffe_set(bias_multiplier_.count(), Dtype(1), bias_multiplier_.mutable_cpu_data()); } }
void ReshapeOp::Forward() { const auto *bottom = bottoms<float>(0); auto *top = mutable_tops<float>(0); CHECK_NE(bottom, top); int inferred_axis = -1, constant_count = 1; VecInt copy_axes; for (int d = 0; d < shape_.size(); ++d) { int top_dim = shape_[d]; if (top_dim == 0) { copy_axes.push_back(d); } else if (top_dim == -1) { CHECK_EQ(inferred_axis, -1); inferred_axis = d; } else { constant_count *= top_dim; } } int start_axis = (axis_ >= 0) ? axis_ : (bottom->num_axes() + axis_ + 1); CHECK_GE(start_axis, 0); CHECK_LE(start_axis, bottom->num_axes()); int end_axis = (num_axes_ == -1) ? bottom->num_axes() : (start_axis + num_axes_); CHECK_LE(end_axis, bottom->num_axes()); int num_axes_replaced = end_axis - start_axis; int num_axes_retained = bottom->num_axes() - num_axes_replaced; VecInt top_shape(num_axes_retained + shape_.size()); int top_shape_index = 0; for (int d = 0; d < start_axis; ++d) { top_shape[top_shape_index++] = bottom->shape(d); } for (auto dim : shape_) { top_shape[top_shape_index++] = dim; } for (int d = end_axis; d < bottom->num_axes(); ++d) { top_shape[top_shape_index++] = bottom->shape(d); } CHECK_EQ(top_shape_index, top_shape.size()); for (auto d : copy_axes) { CHECK_GT(bottom->num_axes(), start_axis + d); top_shape[start_axis + d] = bottom->shape(start_axis + d); } if (inferred_axis >= 0) { int explicit_count = constant_count; explicit_count *= bottom->count(0, start_axis); explicit_count *= bottom->count(end_axis); for (auto d : copy_axes) { explicit_count *= top_shape[start_axis + d]; } CHECK_EQ(0, bottom->count() % explicit_count); top_shape[start_axis + inferred_axis] = bottom->count() / explicit_count; } top->clear(); top->set_shape(top_shape); CHECK_EQ(top->count(), bottom->count()); top->share_data(*bottom); }