Caffe2 - Python API
A deep learning, cross platform ML framework
random_fourier_features.py
1 # Copyright (c) 2016-present, Facebook, Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 ##############################################################################
15 
16 from __future__ import absolute_import
17 from __future__ import division
18 from __future__ import print_function
19 from __future__ import unicode_literals
20 
21 from caffe2.python import schema
22 from caffe2.python.layers.layers import ModelLayer
23 
24 import numpy as np
25 
26 
28  """
29  Implementation of random fourier feature map for feature processing.
30 
31  Applies sqrt(2 / output_dims) * cos(wx+b), where:
32  output_dims is the output feature dimensions, and
33  wx + b applies FC using randomized, fixed weight and bias parameters
34 
35  For more information, see the original paper:
36  https://people.eecs.berkeley.edu/~brecht/papers/07.rah.rec.nips.pdf
37 
38  Inputs:
39  output_dims -- output feature dimensions
40  sigma -- bandwidth for the Gaussian kernel estimator
41  w_init -- initalization options for weight parameter
42  b_init -- initalization options for bias parameter
43 
44  """
45  def __init__(
46  self,
47  model,
48  input_record,
49  output_dims,
50  sigma, # bandwidth
51  w_init=None,
52  b_init=None,
53  name='random_fourier_features',
54  **kwargs):
55 
56  super(RandomFourierFeatures, self).__init__(model, name, input_record,
57  **kwargs)
58  assert isinstance(input_record, schema.Scalar), "Incorrect input type"
59 
60  input_dims = input_record.field_type().shape[0]
61  assert input_dims >= 1, "Expected input dimensions >= 1, got %s" \
62  % input_dims
63  self.output_dims = output_dims
64  assert self.output_dims >= 1, "Expected output dimensions >= 1, got %s" \
65  % self.output_dims
66 
68  (np.float32, (self.output_dims, )),
69  self.get_next_blob_reference('output')
70  )
71 
72  assert sigma > 0.0, "Expected bandwidth > 0, got %s" % sigma
73 
74  # Initialize train_init_net parameters
75  w_init = w_init if w_init else (
76  'GaussianFill', {'mean': 0.0, 'std': 1.0 / sigma}
77  )
78 
79  b_init = b_init if b_init else (
80  'UniformFill', {'min': 0.0, 'max': 2 * np.pi}
81  )
82 
83  self.w = self.create_param(param_name='w',
84  shape=[self.output_dims, input_dims],
85  initializer=w_init,
86  optimizer=model.NoOptim)
87 
88  self.b = self.create_param(param_name='b',
89  shape=[self.output_dims],
90  initializer=b_init,
91  optimizer=model.NoOptim)
92 
93  def add_ops(self, net):
94  # Random features: wx + b
95  cosine_arg = net.FC(self.input_record.field_blobs() + [self.w, self.b],
96  net.NextScopedBlob("cosine_arg"))
97 
98  # Apply cosine to new vectors
99  new_feature_vec = net.Cos([cosine_arg],
100  net.NextScopedBlob('new_feature_vec'))
101 
102  # Multiply each element in vector by sqrt(2/D)
103  scale = np.sqrt(2.0 / self.output_dims)
104  net.Scale([new_feature_vec],
105  self.output_schema.field_blobs(),
106  scale=scale)
def get_next_blob_reference(self, name)
Definition: layers.py:352
def create_param(self, param_name, shape, initializer, optimizer, ps_param=None, regularizer=None)
Definition: layers.py:337