| import scipy.spatial.distance as spd |
| import scipy as sp |
| import numpy as np |
| try: |
| from .libMR import libmr |
| except ImportError: |
| print ("LibMR not installed or libmr.so not found") |
| print ("Install libmr: cd libMR/; ./compile.sh") |
| |
| def computeOpenMaxProbability(openmax_fc8, openmax_score_u, n_classes): |
| """ Convert the scores in probability value using openmax |
| |
| Input: |
| --------------- |
| openmax_fc8 : modified FC8 layer from Weibull based computation |
| openmax_score_u : degree |
| Output: |
| --------------- |
| modified_scores : probability values modified using OpenMax framework, |
| by incorporating degree of uncertainity/openness for a given class |
| |
| """ |
| prob_scores, prob_unknowns = [], [] |
| channel_scores, channel_unknowns = [], [] |
| for category in range(n_classes): |
| channel_scores += [sp.exp(openmax_fc8[category])] |
|
|
| total_denominator = sp.sum(sp.exp(openmax_fc8[:])) + sp.exp(sp.sum(openmax_score_u[:])) |
|
|
| prob_scores += [channel_scores / total_denominator] |
|
|
| prob_unknowns += [sp.exp(sp.sum(openmax_score_u[:]))/total_denominator] |
| |
| prob_scores = sp.asarray(prob_scores) |
| prob_unknowns = sp.asarray(prob_unknowns) |
| |
| scores = sp.mean(prob_scores, axis = 0) |
| unknowns = sp.mean(prob_unknowns, axis=0) |
| modified_scores = scores.tolist() + [unknowns] |
| |
| return modified_scores |
|
|
| def compute_distance(MAV, query_channel, distance_type): |
| |
| if distance_type == 'eucos': |
| query_distance = spd.euclidean(MAV, query_channel) / 200. + spd.cosine(MAV, query_channel) / 200. |
| elif distance_type == 'euclidean': |
| query_distance = spd.euclidean(MAV, query_channel) |
| elif distance_type == 'cosine': |
| query_distance = spd.cosine(MAV, query_channel) |
| else: |
| print ("distance type not known: enter either of eucos, euclidean or cosine") |
| return query_distance |
|
|
| def weibull_tailfitting(mean_vecs, distance_values, num_labels, |
| tailsize = 20): |
| |
| weibull_model = {} |
| |
| for category in range(num_labels): |
| weibull_model[category] = {} |
| distances = distance_values[category] |
| means = mean_vecs[category] |
| weibull_model[category]['distances'] = distances |
| weibull_model[category]['mean_vec'] = means |
| |
| mr = libmr.MR() |
| |
| tailtofit = distances[-tailsize:] |
| mr.fit_high(tailtofit, len(tailtofit)) |
| weibull_model[category]['weibull_model'] = mr |
|
|
| return weibull_model |
|
|
| def query_weibull(category_name, weibull_model): |
| """ Query through dictionary for Weibull model. |
| Return in the order: [mean_vec, distances, weibull_model] |
| |
| Input: |
| ------------------------------ |
| category_name : name of ImageNet category in WNET format. E.g. n01440764 |
| weibull_model: dictonary of weibull models for |
| """ |
|
|
| category_weibull = [] |
| category_weibull += [weibull_model[category_name]['mean_vec']] |
| category_weibull += [weibull_model[category_name]['distances']] |
| category_weibull += [weibull_model[category_name]['weibull_model']] |
|
|
| return category_weibull |
|
|
| def recalibrate_scores(weibull_model, num_labels, textarr, layer = 'fc8', alpharank = 5, distance_type = 'eucos'): |
| |
| txtlayer = textarr[layer] |
| ranked_list = textarr['scores'].argsort().ravel()[::-1] |
| alpha_weights = [((alpharank+1) - i)/float(alpharank) for i in range(1, alpharank+1)] |
| |
| ranked_alpha = sp.zeros(num_labels) |
|
|
| for i in range(len(alpha_weights)): |
| ranked_alpha[ranked_list[i]] = alpha_weights[i] |
|
|
| |
| |
| |
| openmax_fc8, openmax_score_u = [], [] |
|
|
| cha_scores = txtlayer |
| openmax_fc8_channel = [] |
| openmax_fc8_unknown = [] |
| |
| for categoryid in range(num_labels): |
| |
| category_weibull = query_weibull(categoryid, weibull_model) |
| distance = compute_distance(txtlayer, category_weibull[0], distance_type) |
| |
| |
| |
| |
| wscore = category_weibull[2].w_score(distance) |
| |
| modified_fc8_score = cha_scores[categoryid] * (1 - wscore * ranked_alpha[categoryid]) |
| openmax_fc8_channel += [modified_fc8_score] |
| openmax_fc8_unknown += [cha_scores[categoryid] - modified_fc8_score] |
| |
| openmax_fc8 = openmax_fc8_channel |
| openmax_score_u = openmax_fc8_unknown |
| openmax_fc8 = sp.asarray(openmax_fc8) |
| openmax_score_u = sp.asarray(openmax_score_u) |
| |
| |
| openmax_prob = computeOpenMaxProbability(openmax_fc8, openmax_score_u, num_labels) |
| softmax_prob = textarr['scores'].ravel() |
| |
| return sp.asarray(openmax_prob), sp.asarray(softmax_prob) |
|
|