Caffe2 - C++ API
A deep learning, cross platform ML framework
sinusoid_position_encoding_op.h
1 #ifndef CAFFE2_OPERATORS_SINUSOID_POSITION_ENCODING_OP_H_
2 #define CAFFE2_OPERATORS_SINUSOID_POSITION_ENCODING_OP_H_
3 
4 #ifdef _MSC_VER
5 #define _USE_MATH_DEFINES
6 #endif // _MSC_VER
7 #include <cmath>
8 
9 #include "caffe2/core/operator.h"
10 
11 #include "Eigen/Core"
12 
13 namespace caffe2 {
14 
15 template <class Context>
16 class SinusoidPositionEncodingOp : public Operator<Context> {
17  public:
18  SinusoidPositionEncodingOp(const OperatorDef& operator_def, Workspace* ws)
19  : Operator<Context>(operator_def, ws),
20  embedding_size_(OperatorBase::template GetSingleArgument<int>(
21  "embedding_size",
22  100)),
23  alpha_(OperatorBase::template GetSingleArgument<float>("alpha", 10000)),
24  amplitude_(
25  OperatorBase::template GetSingleArgument<float>("amplitude", 1)) {}
26  USE_OPERATOR_CONTEXT_FUNCTIONS;
27 
28  bool RunOnDevice() override {
30  this, OperatorBase::Input<TensorCPU>(0));
31  }
32 
33  template <typename Index>
34  bool DoRunWithType() {
35  auto& positions = Input(0);
36  auto* output = Output(0);
37 
38  CAFFE_ENFORCE_EQ(positions.ndim(), 2, "POSITIONS should be a 2-D tensor");
39 
40  auto shape = positions.dims();
41  shape.push_back(embedding_size_);
42  output->Resize(shape);
43 
44  int M = shape[0];
45  int K = shape[1];
46  const Index* idxs = positions.template data<Index>();
47  float* out = output->template mutable_data<float>();
48 
49  float log_alpha = std::log(alpha_);
50  float max_alpha_pow =
51  ((float)embedding_size_ - 1.0f) / (float)embedding_size_;
52 
53  for (int i = 0; i < M; ++i) {
54  float pos = (float)idxs[i * K];
55 
56  // Compute the embedding for position i, example 0 first
57  float* row = &out[i * K * embedding_size_];
58  Eigen::Map<Eigen::VectorXf> row_map(row, embedding_size_, 1);
59  auto row_array = row_map.array();
60 
61  float log_pos = std::log(pos);
62  row_array.setLinSpaced(
63  embedding_size_, log_pos, log_pos - log_alpha * max_alpha_pow);
64  row_array = row_array.exp().eval();
65  // row_array[k] == pos / alpha^(k / embedding_size)
66 
67  // Phase shift so that alternating elements are cosines
68  for (int k = 1; k < embedding_size_; k += 2) {
69  row[k] += (float)M_PI_2;
70  }
71  row_array = amplitude_ * row_array.sin().eval();
72 
73  // Copy the embedding to position i in the other examples
74  for (int j = 1; j < K; ++j) {
75  int base = i * K * embedding_size_;
76  std::copy(
77  &out[base],
78  &out[base + embedding_size_],
79  &out[base + j * embedding_size_]);
80  }
81  }
82  return true;
83  }
84 
85  protected:
86  int embedding_size_;
87  float alpha_;
88  float amplitude_;
89 };
90 
91 } // namespace caffe2
92 
93 #endif // CAFFE2_OPERATORS_SINUSOID_POSITION_ENCODING_OP_H_
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
Definition: workspace.h:47
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...