File size: 5,163 Bytes
2d06dcc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
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)
|