Score normalization redesign
This is the initial redesign of the score-normalization pipeline.
I basically dropped all the old code and made the score normalization stuff as a post-processor
where such a post-processor is a BaseEstimator. In such a way, we can leverage Checkpointing and Dasking wrappers avoiding the implementation of custom features.
Furthermore, it will be easier to implement other calibration strategies.
ZNorm is already working and giving the same results as before but with way less code.
Still a WIP, though.
Closes #166 (closed)
Merge request reports
Activity
64 Transformer that will post process the scores 65 66 score_writer: 67 68 69 """ 70 71 def __init__( 72 self, 73 vanilla_biometrics_pipeline, 74 post_processor, 75 score_writer=FourColumnsScoreWriter("./scores.txt"), 76 ): 77 self.vanilla_biometrics_pipeline = vanilla_biometrics_pipeline 78 self.biometric_algorithm = self.vanilla_biometrics_pipeline.biometric_algorithm 79 self.transformer = self.vanilla_biometrics_pipeline.transformer 110 self.post_processor.fit([post_process_samples, biometric_references]) 111 112 # Transformer 113 post_processed_scores = self.post_processor.transform(raw_scores) 114 115 return raw_scores, post_processed_scores 116 117 def train_background_model(self, background_model_samples): 118 return self.vanilla_biometrics_pipeline.train_background_model( 119 background_model_samples 120 ) 121 122 def create_biometric_reference(self, biometric_reference_samples): 123 return self.vanilla_biometrics_pipeline.create_biometric_reference( 124 biometric_reference_samples 125 ) Looks you would benefit a lot by inheritance here. Instead of:
>>> vanilla_biometrics_pipeline = VanillaBiometricsPipeline(transformer, biometric_algorithm) >>> zt_pipeline = ZTNormPipeline(vanilla_biometrics_pipeline) >>> zt_pipeline(...) #doctest: +SKIP
wouldn't be better to have:
>>> zt_pipeline = ZTNormPipeline(transformer, biometric_algorithm)
IMO aggregation is more appropriate in this case, because all our
entrypoints
are already "wrapped" with theVanillaBiometricsPipeline
. Changing the design ofScoreNormalizationPipeline
to inheritance would force us to add a whole set of entrypoints to work with this pipeline. Furthermore, semantically aggregation makes more sense; you are "aggregating" score normalization to the regular pipelines.
229 def transform(self, sample_sets, y=None): 230 231 logger.debug("CheckpointPostProcessor.transform") 232 transformed_sample_sets = [] 233 for s in sample_sets: 234 235 path = self.make_path(s) 236 if os.path.exists(path): 237 sset = uncompress_unpickle(path) 238 else: 239 sset = self.estimator.transform([s])[0] 240 pickle_compress(path, sset) 241 242 transformed_sample_sets.append(sset) 243 244 return transformed_sample_sets I suggest you take advantage of bob.pipelines!70 (merged) and add this option there.
Score normalization redesigned.
I need to:
- Write the sphinx documentation of it
- There is some minor design issue with the checkpoints that I need to find an elegant way to implement it.
Edited by Tiago de Freitas Pereiraadded 1 commit
- 8e00f466 - Implemented calibration by category using different calibrators
enabled an automatic merge when the pipeline for 0e0c6685 succeeds
mentioned in issue #166 (closed)
mentioned in commit 77f8cfa2