Caffe2 - Python API
A deep learning, cross platform ML framework
arc_cosine_feature_map.py
1 from __future__ import absolute_import
2 from __future__ import division
3 from __future__ import print_function
4 from __future__ import unicode_literals
5 
6 from caffe2.python import schema
7 from caffe2.python.layers.layers import ModelLayer
8 import numpy as np
9 
10 
12  """
13  A general version of the arc-cosine kernel feature map (s = 1 restores
14  the original arc-cosine kernel feature map).
15 
16  Applies H(x) * x^s, where H is the Heaviside step function and x is the
17  input after applying FC (such that x = w * x_orig + b).
18 
19  For more information, see the original paper:
20  http://cseweb.ucsd.edu/~saul/papers/nips09_kernel.pdf
21 
22  Inputs :
23  output_dims -- dimensions of the output vector
24  s -- degree to raise transformed features
25  scale -- amount to scale the standard deviation
26  weight_init -- initialization distribution for weight parameter
27  bias_init -- initialization distribution for bias pararmeter
28  weight_optim -- optimizer for weight params; None for random features
29  bias_optim -- optimizer for bias param; None for random features
30  set_weight_as_global_constant -- if True, initialized random parameters
31  will be constant across all distributed
32  instances of the layer
33  initialize_output_schema -- if True, initialize output schema as Scalar
34  from Arc Cosine; else output schema is None
35  """
36  def __init__(
37  self,
38  model,
39  input_record,
40  output_dims,
41  s=1,
42  scale=1.0,
43  weight_init=None,
44  bias_init=None,
45  weight_optim=None,
46  bias_optim=None,
47  set_weight_as_global_constant=False,
48  initialize_output_schema=True,
49  name='arc_cosine_feature_map',
50  **kwargs):
51 
52  super(ArcCosineFeatureMap, self).__init__(model, name, input_record,
53  **kwargs)
54  assert isinstance(input_record, schema.Scalar), "Incorrect input type"
55  self.params = []
56  self.model = model
57  self.set_weight_as_global_constant = set_weight_as_global_constant
58 
59  self.input_dims = input_record.field_type().shape[0]
60  assert self.input_dims >= 1, "Expected input dimensions >= 1, got %s" \
61  % self.input_dims
62 
63  if initialize_output_schema:
65  (np.float32, (output_dims, )),
66  model.net.NextScopedBlob(name + '_output')
67  )
68 
69  self.output_dims = output_dims
70  assert self.output_dims >= 1, "Expected output dimensions >= 1, got %s" \
71  % self.output_dims
72  self.s = s
73  assert (self.s >= 0), "Expected s >= 0, got %s" % self.s
74  assert isinstance(self.s, int), "Expected s to be type int, got type %s" \
75  % type(self.s)
76 
77  assert (scale > 0.0), "Expected scale > 0, got %s" % scale
78  self.stddev = scale * np.sqrt(1.0 / self.input_dims)
79 
80  # Initialize train_init_net parameters
81  # Random Parameters
82  if set_weight_as_global_constant:
83  w_init = np.random.normal(scale=self.stddev,
84  size=(self.output_dims, self.input_dims))
85  b_init = np.random.uniform(low=-0.5 * self.stddev,
86  high=0.5 * self.stddev,
87  size=self.output_dims)
88  self.random_w = self.model.add_global_constant(
89  name=self.name + "_fixed_rand_W",
90  array=w_init
91  )
92  self.random_b = self.model.add_global_constant(
93  name=self.name + "_fixed_rand_b",
94  array=b_init
95  )
96  else:
97  (self.random_w, self.random_b) = self._initialize_params(
98  'random_w',
99  'random_b',
100  w_init=weight_init,
101  b_init=bias_init,
102  w_optim=weight_optim,
103  b_optim=bias_optim
104  )
105 
106  def _initialize_params(self, w_name, b_name, w_init=None, b_init=None,
107  w_optim=None, b_optim=None):
108  """
109  Initializes the Layer Parameters for weight and bias terms for features
110 
111  Inputs :
112  w_blob -- blob to contain w values
113  b_blob -- blob to contain b values
114  w_init -- initialization distribution for weight parameter
115  b_init -- initialization distribution for bias parameter
116  w_optim -- optimizer to use for w; if None, then will use no optimizer
117  b_optim -- optimizer to user for b; if None, then will use no optimizer
118  """
119 
120  w_init = w_init if w_init else (
121  'GaussianFill', {'mean': 0.0, 'std': self.stddev}
122  )
123  w_optim = w_optim if w_optim else self.model.NoOptim
124 
125  b_init = b_init if b_init else (
126  'UniformFill', {'min': -0.5 * self.stddev, 'max': 0.5 * self.stddev}
127  )
128  b_optim = b_optim if b_optim else self.model.NoOptim
129 
130  w_param = self.create_param(param_name=w_name,
131  shape=(self.output_dims, self.input_dims),
132  initializer=w_init,
133  optimizer=w_optim)
134 
135  b_param = self.create_param(param_name=b_name,
136  shape=[self.output_dims],
137  initializer=b_init,
138  optimizer=b_optim)
139 
140  return [w_param, b_param]
141 
142  def _heaviside_with_power(self, net, input_features, output_blob, s):
143  """
144  Applies Heaviside step function and Relu / exponentiation to features
145  depending on the value of s.
146 
147  Inputs:
148  net -- net with operators
149  input_features -- features to processes
150  output_blob -- output blob reference
151  s -- degree to raise the transformed features
152  """
153  if s == 0:
154  softsign_features = net.Softsign([input_features],
155  net.NextScopedBlob('softsign'))
156  return net.Relu(softsign_features, output_blob)
157  elif s == 1:
158  return net.Relu([input_features],
159  output_blob)
160  else:
161  relu_features = net.Relu([input_features],
162  net.NextScopedBlob('relu_rand'))
163  pow_features = net.Pow([input_features],
164  net.NextScopedBlob('pow_rand'),
165  exponent=float(s - 1))
166  return net.Mul([relu_features, pow_features],
167  output_blob)
168 
169  def add_ops(self, net):
170  input_blob = self.input_record.field_blobs()
171 
172  # Random features: wx + b
173  random_features = net.FC(input_blob + [self.random_w, self.random_b],
174  net.NextScopedBlob('random_features'))
175  # Process random features
176  self._heaviside_with_power(net,
177  random_features,
178  self.output_schema.field_blobs(),
179  self.s)
def _heaviside_with_power(self, net, input_features, output_blob, s)
def create_param(self, param_name, shape, initializer, optimizer, ps_param=None, regularizer=None)
Definition: layers.py:334
def _initialize_params(self, w_name, b_name, w_init=None, b_init=None, w_optim=None, b_optim=None)