| # @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) |