| #ifndef CAFFE2_FILLER_H_ |
| #define CAFFE2_FILLER_H_ |
| |
| #include <sstream> |
| |
| #include "caffe2/core/logging.h" |
| #include "caffe2/core/tensor.h" |
| #include "caffe2/utils/math.h" |
| |
| namespace caffe2 { |
| |
| // TODO: replace filler distribution enum with a better abstraction |
| enum FillerDistribution { FD_UNIFORM, FD_FIXEDSUM, FD_SYNTHETIC }; |
| |
| class TensorFiller { |
| public: |
| template <class Type, class Context> |
| void Fill(Tensor* tensor, Context* context) const { |
| CAFFE_ENFORCE(context, "context is null"); |
| CAFFE_ENFORCE(tensor, "tensor is null"); |
| auto min = (min_ < (double)std::numeric_limits<Type>::min()) |
| ? std::numeric_limits<Type>::min() |
| : static_cast<Type>(min_); |
| auto max = (max_ > (double)std::numeric_limits<Type>::max()) |
| ? std::numeric_limits<Type>::max() |
| : static_cast<Type>(max_); |
| CAFFE_ENFORCE_LE(min, max); |
| |
| Tensor temp_tensor(shape_, Context::GetDeviceType()); |
| std::swap(*tensor, temp_tensor); |
| Type* data = tensor->template mutable_data<Type>(); |
| |
| // select distribution |
| switch (dist_) { |
| case FD_UNIFORM: { |
| math::RandUniform<Type, Context>( |
| tensor->numel(), min, max, data, context); |
| break; |
| } |
| case FD_FIXEDSUM: { |
| auto fixed_sum = static_cast<Type>(fixed_sum_); |
| CAFFE_ENFORCE_LE(min * tensor->numel(), fixed_sum); |
| CAFFE_ENFORCE_GE(max * tensor->numel(), fixed_sum); |
| math::RandFixedSum<Type, Context>( |
| tensor->numel(), min, max, fixed_sum_, data, context); |
| break; |
| } |
| case FD_SYNTHETIC: { |
| math::RandSyntheticData<Type, Context>( |
| tensor->numel(), min, max, data, context); |
| break; |
| } |
| } |
| } |
| |
| TensorFiller& Dist(FillerDistribution dist) { |
| dist_ = dist; |
| return *this; |
| } |
| |
| template <class Type> |
| TensorFiller& Min(Type min) { |
| min_ = (double)min; |
| return *this; |
| } |
| |
| template <class Type> |
| TensorFiller& Max(Type max) { |
| max_ = (double)max; |
| return *this; |
| } |
| |
| template <class Type> |
| TensorFiller& FixedSum(Type fixed_sum) { |
| dist_ = FD_FIXEDSUM; |
| fixed_sum_ = (double)fixed_sum; |
| return *this; |
| } |
| |
| // A helper function to construct the lengths vector for sparse features |
| // We try to pad least one index per batch unless the total_length is 0 |
| template <class Type> |
| TensorFiller& SparseLengths(Type total_length) { |
| return FixedSum(total_length) |
| .Min(std::min(static_cast<Type>(1), total_length)) |
| .Max(total_length); |
| } |
| |
| // a helper function to construct the segments vector for sparse features |
| template <class Type> |
| TensorFiller& SparseSegments(Type max_segment) { |
| CAFFE_ENFORCE(dist_ != FD_FIXEDSUM); |
| return Min(0).Max(max_segment).Dist(FD_SYNTHETIC); |
| } |
| |
| TensorFiller& Shape(const std::vector<int64_t>& shape) { |
| shape_ = shape; |
| return *this; |
| } |
| |
| template <class Type> |
| TensorFiller(const std::vector<int64_t>& shape, Type fixed_sum) |
| : shape_(shape), dist_(FD_FIXEDSUM), fixed_sum_((double)fixed_sum) {} |
| |
| TensorFiller(const std::vector<int64_t>& shape) |
| : shape_(shape), dist_(FD_UNIFORM), fixed_sum_(0) {} |
| |
| TensorFiller() : TensorFiller(std::vector<int64_t>()) {} |
| |
| std::string DebugString() const { |
| std::stringstream stream; |
| stream << "shape = [" << shape_ << "]; min = " << min_ |
| << "; max = " << max_; |
| switch (dist_) { |
| case FD_FIXEDSUM: |
| stream << "; dist = FD_FIXEDSUM"; |
| break; |
| case FD_SYNTHETIC: |
| stream << "; dist = FD_SYNTHETIC"; |
| break; |
| default: |
| stream << "; dist = FD_UNIFORM"; |
| break; |
| } |
| return stream.str(); |
| } |
| |
| private: |
| std::vector<int64_t> shape_; |
| // TODO: type is unknown until a user starts to fill data; |
| // cast everything to double for now. |
| double min_ = 0.0; |
| double max_ = 1.0; |
| FillerDistribution dist_; |
| double fixed_sum_; |
| }; |
| |
| } // namespace caffe2 |
| |
| #endif // CAFFE2_FILLER_H_ |