Download lib/python3.9/site-packages/caffe2/python/layers/fc.py from camenduru/slahmr-test: direct link, hf CLI and curl.
- Browser
- Download file 9.3 kB
-
https://huggingface.co/camenduru/slahmr-test/resolve/main/lib/python3.9/site-packages/caffe2/python/layers/fc.py
- Command line
-
hf download hf://camenduru/slahmr-test/lib/python3.9/site-packages/caffe2/python/layers/fc.py
-
curl -L -o fc.py https://huggingface.co/camenduru/slahmr-test/resolve/main/lib/python3.9/site-packages/caffe2/python/layers/fc.py
9.3 kB
| ## @package fc | |
| # Module caffe2.python.layers.fc | |
| from caffe2.python.helpers.arg_scope import get_current_scope | |
| from caffe2.python import schema | |
| from caffe2.python.layers.layers import ModelLayer | |
| from caffe2.python.layers.sampling_trainable_mixin import SamplingTrainableMixin | |
| import math | |
| import numpy as np | |
| def get_fc_predictor_version(fc_version): | |
| assert fc_version in ["fp32", "fp16"], ( | |
| "Only support fp32 and fp16 for the fully connected layer " | |
| "in the predictor net, the provided FC precision is {}".format(fc_version) | |
| ) | |
| return fc_version | |
| class FC(SamplingTrainableMixin, ModelLayer): | |
| def __init__(self, model, input_record, output_dims, weight_init=None, | |
| bias_init=None, weight_optim=None, bias_optim=None, name='fc', | |
| weight_reg=None, bias_reg=None, clip_param=None, | |
| max_fc_size=None, axis=1, transposed=False, | |
| uniform_weight_init_scale_numerator=1.0, | |
| **kwargs): | |
| super(FC, self).__init__(model, name, input_record, **kwargs) | |
| assert isinstance(input_record, schema.Scalar), ( | |
| "Incorrect input type {}".format(input_record)) | |
| assert len(input_record.field_types()[0].shape) > 0, ( | |
| "FC expects limited dimensions of the input tensor") | |
| assert axis >= 1, "axis {} should >= 1.".format(axis) | |
| self.axis = axis | |
| input_dims = np.prod(input_record.field_types()[0].shape[axis - 1:]) | |
| assert input_dims > 0, ( | |
| "FC expects input dimensions > 0, got {}".format(input_dims)) | |
| self.clip_args = None | |
| if (clip_param is not None): | |
| assert len(clip_param) == 2, ( | |
| 'clip_param must be a tuple / list ' | |
| 'of length 2 and in the form of (clip_min, clip max)' | |
| ) | |
| clip_min, clip_max = clip_param | |
| assert clip_min is not None or clip_max is not None, ( | |
| 'clip_min, and clip_max in clip_param cannot both be None' | |
| ) | |
| assert ( | |
| (clip_min is None or clip_max is None) or clip_min < clip_max | |
| ), ( | |
| 'clip_param = [clip_min, clip_max] must have clip_min < clip_max' | |
| ) | |
| self.clip_args = {} | |
| if clip_min is not None: | |
| self.clip_args['min'] = clip_min | |
| if clip_max is not None: | |
| self.clip_args['max'] = clip_max | |
| if uniform_weight_init_scale_numerator is None: | |
| uniform_weight_init_scale_numerator = 1.0 | |
| scale = math.sqrt(uniform_weight_init_scale_numerator / input_dims) | |
| weight_init = weight_init if weight_init else ( | |
| 'UniformFill', {'min': -scale, 'max': scale}) | |
| bias_init = bias_init if bias_init else ( | |
| 'UniformFill', {'min': -scale, 'max': scale}) | |
| self.output_dim_vec = FC.calculate_fc_output_dims( | |
| max_fc_size, input_dims, output_dims) | |
| self.transposed = transposed | |
| if self.output_dim_vec is None or len(self.output_dim_vec) == 1: | |
| weight_shape = [input_dims, output_dims] if transposed else [output_dims, input_dims] | |
| self.w = self.create_param(param_name='w', | |
| shape=weight_shape, | |
| initializer=weight_init, | |
| optimizer=weight_optim, | |
| regularizer=weight_reg) | |
| self.b = self.create_param(param_name='b', | |
| shape=[output_dims, ], | |
| initializer=bias_init, | |
| optimizer=bias_optim, | |
| regularizer=bias_reg) | |
| else: | |
| self.w_vec = [] | |
| self.b_vec = [] | |
| for idx, output_dim in enumerate(self.output_dim_vec): | |
| weight_shape = [input_dims, output_dim] if transposed else [output_dim, input_dims] | |
| self.w_vec.append(self.create_param(param_name='w_sub_{}'.format(idx), | |
| shape=weight_shape, | |
| initializer=weight_init, | |
| optimizer=weight_optim, | |
| regularizer=weight_reg)) | |
| self.b_vec.append(self.create_param(param_name='b_sub_{}'.format(idx), | |
| shape=[output_dim, ], | |
| initializer=weight_init, | |
| optimizer=weight_optim, | |
| regularizer=weight_reg)) | |
| if axis == 1: | |
| output_shape = (output_dims, ) | |
| else: | |
| output_shape = list(input_record.field_types()[0].shape)[0: axis - 1] | |
| output_shape = tuple(output_shape + [output_dims]) | |
| self.output_schema = schema.Scalar( | |
| (np.float32, output_shape), | |
| self.get_next_blob_reference('output') | |
| ) | |
| def calculate_fc_output_dims(max_fc_size, input_dim, output_dim): | |
| if not max_fc_size or max_fc_size < 0: | |
| return None | |
| assert max_fc_size >= input_dim, "Currently we split along the output " \ | |
| "dimension. So we need max_fc_size >= input_dim. But, max_fc_size: " \ | |
| "{}, input_dim: {}".format(max_fc_size, input_dim) | |
| output_dim_allowed = int(np.floor(max_fc_size / input_dim)) | |
| num_fc = int(np.floor((output_dim - 1) / output_dim_allowed) + 1) | |
| output_dim_vec = [output_dim_allowed] * (num_fc - 1) | |
| output_dim_vec.append(output_dim - sum(output_dim_vec)) | |
| return output_dim_vec | |
| def _insert_fc_ops(self, net, params, outputs, version): | |
| """ | |
| Args: | |
| net: the caffe2 net to insert operator | |
| params: weight and bias for FC | |
| outputs: the output blobs | |
| version: support fp32 and fp16 for now. | |
| """ | |
| if version == "fp32": | |
| if self.transposed: | |
| return net.FCTransposed( | |
| self.input_record.field_blobs() + params, | |
| outputs, | |
| axis=self.axis, | |
| **self.kwargs | |
| ) | |
| else: | |
| return net.FC( | |
| self.input_record.field_blobs() + params, | |
| outputs, | |
| axis=self.axis, | |
| **self.kwargs | |
| ) | |
| elif version == "fp16": | |
| return net.FbFCPacked( | |
| self.input_record.field_blobs() + params, | |
| outputs, | |
| axis=self.axis, | |
| **self.kwargs | |
| ) | |
| else: | |
| raise Exception("unsupported FC type version {}".format(version)) | |
| def _add_ops(self, net, params, version): | |
| """ | |
| Args: | |
| params : the weight and bias, | |
| passed by either add_ops or add_train_ops function | |
| version : fp16 or fp32, might support in8 in the future. | |
| """ | |
| if self.clip_args is not None: | |
| clipped_params = [net.NextScopedBlob( | |
| 'clipped_%s' % str(p)) for p in params] | |
| for p, cp in zip(params, clipped_params): | |
| net.Clip([p], [cp], **self.clip_args) | |
| params = clipped_params | |
| if self.output_dim_vec is None or len(self.output_dim_vec) == 1: | |
| self._insert_fc_ops(net, params, self.output_schema.field_blobs(), version) | |
| else: | |
| w_vec = params[:int(len(params) / 2)] | |
| b_vec = params[int(len(params) / 2):] | |
| assert len(w_vec) == len(b_vec) | |
| output_blob_vec = [] | |
| for i in range(len(self.output_dim_vec)): | |
| output_blob = net.NextScopedBlob( | |
| 'output_sub_{}'.format(i)) | |
| insert_ret = self._insert_fc_ops( | |
| net, [w_vec[i], b_vec[i]], [output_blob], version | |
| ) | |
| output_blob_vec.append(insert_ret) | |
| net.Concat(output_blob_vec, | |
| self.output_schema.field_blobs() + | |
| [self.output_schema.field_blobs()[0] + "_concat_dims"]) | |
| def add_ops(self, net): | |
| """Both the predict net and the eval net will call this function | |
| """ | |
| version_info = get_current_scope().get( | |
| get_fc_predictor_version.__name__, {'fc_version': 'fp32'} | |
| ) | |
| predictor_fc_fp_version = version_info['fc_version'] | |
| self._add_ops(net, self.param_blobs, predictor_fc_fp_version) | |
| def add_train_ops(self, net): | |
| # use the train_param_blobs to be consistent with the SamplingTrain unittest | |
| self._add_ops(net, self.train_param_blobs, "fp32") | |
| def get_fp16_compatible_parameters(self): | |
| if self.output_dim_vec is None or len(self.output_dim_vec) == 1: | |
| return [self.w] | |
| else: | |
| return self.w_vec | |
| def param_blobs(self): | |
| if self.output_dim_vec is None or len(self.output_dim_vec) == 1: | |
| return [self.w, self.b] | |
| else: | |
| return self.w_vec + self.b_vec | |