from typing import Any import numpy as np import torch import torch.nn as nn from tqdm import tqdm from .base_postprocessor import BasePostprocessor class ReactPostprocessor(BasePostprocessor): def __init__(self, config): super(ReactPostprocessor, self).__init__(config) self.args = self.config.postprocessor.postprocessor_args self.percentile = self.args.percentile self.args_dict = self.config.postprocessor.postprocessor_sweep self.setup_flag = False def setup(self, net: nn.Module, id_loader_dict, ood_loader_dict): if not self.setup_flag: activation_log = [] net.eval() with torch.no_grad(): for batch in tqdm(id_loader_dict['val'], desc='Setup: ', position=0, leave=True): data = batch['data'].cuda() data = data.float() _, feature = net(data, return_feature=True) activation_log.append(feature.data.cpu().numpy()) self.activation_log = np.concatenate(activation_log, axis=0) self.setup_flag = True else: pass self.threshold = np.percentile(self.activation_log.flatten(), self.percentile) @torch.no_grad() def postprocess(self, net: nn.Module, data: Any): output = net.forward_threshold(data, self.threshold) score = torch.softmax(output, dim=1) _, pred = torch.max(score, dim=1) energyconf = torch.logsumexp(output.data.cpu(), dim=1) return pred, energyconf def set_hyperparam(self, hyperparam: list): self.percentile = hyperparam[0] self.threshold = np.percentile(self.activation_log.flatten(), self.percentile) print('Threshold at percentile {:2d} over id data is: {}'.format( self.percentile, self.threshold)) def get_hyperparam(self): return self.percentile