(self, model, input_record, seed=0, modulo=None,
use_hashing=True, use_divide_mod=False, divisor=None, name='sparse_feature_hash', **kwargs)
| 21 | class SparseFeatureHash(ModelLayer): |
| 22 | |
| 23 | def __init__(self, model, input_record, seed=0, modulo=None, |
| 24 | use_hashing=True, use_divide_mod=False, divisor=None, name='sparse_feature_hash', **kwargs): |
| 25 | super().__init__(model, name, input_record, **kwargs) |
| 26 | |
| 27 | assert use_hashing + use_divide_mod < 2, "use_hashing and use_divide_mod cannot be set true at the same time." |
| 28 | |
| 29 | if use_divide_mod: |
| 30 | assert divisor >= 1, 'Unexpected divisor: {}'.format(divisor) |
| 31 | |
| 32 | self.divisor = self.create_param(param_name='divisor', |
| 33 | shape=[1], |
| 34 | initializer=('GivenTensorInt64Fill', {'values': np.array([divisor])}), |
| 35 | optimizer=model.NoOptim) |
| 36 | |
| 37 | self.seed = seed |
| 38 | self.use_hashing = use_hashing |
| 39 | self.use_divide_mod = use_divide_mod |
| 40 | |
| 41 | if schema.equal_schemas(input_record, IdList): |
| 42 | self.modulo = modulo or self.extract_hash_size(input_record.items.metadata) |
| 43 | metadata = schema.Metadata( |
| 44 | categorical_limit=self.modulo, |
| 45 | feature_specs=input_record.items.metadata.feature_specs if input_record.items.metadata else None, |
| 46 | expected_value=input_record.items.metadata.expected_value if input_record.items.metadata else None |
| 47 | ) |
| 48 | with core.NameScope(name): |
| 49 | self.output_schema = schema.NewRecord(model.net, IdList) |
| 50 | self.output_schema.items.set_metadata(metadata) |
| 51 | |
| 52 | elif schema.equal_schemas(input_record, IdScoreList): |
| 53 | self.modulo = modulo or self.extract_hash_size(input_record.keys.metadata) |
| 54 | metadata = schema.Metadata( |
| 55 | categorical_limit=self.modulo, |
| 56 | feature_specs=input_record.keys.metadata.feature_specs, |
| 57 | expected_value=input_record.keys.metadata.expected_value |
| 58 | ) |
| 59 | with core.NameScope(name): |
| 60 | self.output_schema = schema.NewRecord(model.net, IdScoreList) |
| 61 | self.output_schema.keys.set_metadata(metadata) |
| 62 | |
| 63 | else: |
| 64 | assert False, "Input type must be one of (IdList, IdScoreList)" |
| 65 | |
| 66 | assert self.modulo >= 1, 'Unexpected modulo: {}'.format(self.modulo) |
| 67 | if input_record.lengths.metadata: |
| 68 | self.output_schema.lengths.set_metadata(input_record.lengths.metadata) |
| 69 | |
| 70 | # operators in this layer do not have CUDA implementation yet. |
| 71 | # In addition, since the sparse feature keys that we are hashing are |
| 72 | # typically on CPU originally, it makes sense to have this layer on CPU. |
| 73 | self.tags.update([Tags.CPU_ONLY]) |
| 74 | |
| 75 | def extract_hash_size(self, metadata): |
| 76 | if metadata.feature_specs and metadata.feature_specs.desired_hash_size: |
nothing calls this directly
no test coverage detected