|
|
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) |
|
|
|