THU-IAR's picture
Upload 198 files
2d06dcc verified
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 each category, read meanfile, distance file, and perform weibull fitting
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]
# Now recalibrate each fc8 score for each channel and for each class
# to include probability of unknown
openmax_fc8, openmax_score_u = [], []
cha_scores = txtlayer
openmax_fc8_channel = []
openmax_fc8_unknown = []
for categoryid in range(num_labels):
# get distance between current channel and mean vector
category_weibull = query_weibull(categoryid, weibull_model)
distance = compute_distance(txtlayer, category_weibull[0], distance_type)
# obtain w_score for the distance and compute probability of the distance
# being unknown wrt to mean training vector and channel distances for
# category and channel under consideration
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)
# Pass the recalibrated fc8 scores for the image into openmax
openmax_prob = computeOpenMaxProbability(openmax_fc8, openmax_score_u, num_labels)
softmax_prob = textarr['scores'].ravel()
return sp.asarray(openmax_prob), sp.asarray(softmax_prob)