blob: 9aec2735b44c1f2ebac5d86dc3db0e3b37a037de [file]
# @package adaptive_weight
# Module caffe2.fb.python.layers.adaptive_weight
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from caffe2.python import core, schema
from caffe2.python.layers.layers import ModelLayer
import numpy as np
'''
Implementation of adaptive weighting: https://arxiv.org/pdf/1705.07115.pdf
'''
class AdaptiveWeight(ModelLayer):
def __init__(
self,
model,
input_record,
name='adaptive_weight',
optimizer=None,
weights=None,
**kwargs
):
super(AdaptiveWeight,
self).__init__(model, name, input_record, **kwargs)
self.output_schema = schema.Scalar(
np.float32, self.get_next_blob_reference('adaptive_weight')
)
self.data = self.input_record.field_blobs()
self.num = len(self.data)
# mu_i = log(sigma_i^2)
if weights is None:
# mu_i is set such that all initial weights are 1. / num
initializer = ('ConstantFill', {'value': np.log(self.num / 2.)})
else:
assert len(weights) == self.num
weights = np.array(weights).astype(np.float32)
assert min(weights) > 0, 'initial weights must be non-negative'
values = np.log(1. / 2. / weights)
initializer = (
'GivenTensorFill', {
'values': values,
'dtype': core.DataType.FLOAT
}
)
self.mu = self.create_param(
param_name='mu',
shape=[self.num],
initializer=initializer,
optimizer=optimizer,
)
def concat_data(self, net):
reshaped = [
net.NextScopedBlob('reshaped_data_%d' % i) for i in range(self.num)
]
# coerce shape for single real values
for i in range(self.num):
net.Reshape(
[self.data[i]],
[reshaped[i], net.NextScopedBlob('new_shape_%d' % i)],
shape=[1]
)
concated = net.NextScopedBlob('concated_data')
net.Concat(
reshaped, [concated, net.NextScopedBlob('concated_new_shape')],
axis=0
)
return concated
def compute_adaptive_sum(self, x, net):
mu_exp = net.NextScopedBlob('mu_exp')
net.Exp(self.mu, mu_exp)
mu_exp_double = net.NextScopedBlob('mu_exp_double')
net.Scale(mu_exp, mu_exp_double, scale=2.0)
weighted_x = net.NextScopedBlob('weighted_x')
net.Div([x, mu_exp_double], weighted_x)
weighted_elements = net.NextScopedBlob('weighted_elements')
net.Add([weighted_x, self.mu], weighted_elements)
net.SumElements(weighted_elements, self.output_schema())
def add_ops(self, net):
data = self.concat_data(net)
self.compute_adaptive_sum(data, net)