def border_(p, y, intervals=30, max_dur=None): # True borders = p_labels = utils.segment_labels(p) y_labels = utils.segment_labels(y) p_starts = np.array([s[0] for s in utils.segment_intervals(p)]) y_starts = np.array([s[0] for s in utils.segment_intervals(y)]) dists = [] n_true = len(y_labels) for i in range(n_true): start = y_starts[i] label = y_labels[i] idxs_same_labels = np.nonzero(p_labels==label)[0] if len(idxs_same_labels)>0: closest_correst = np.abs(p_starts[idxs_same_labels] - start).min() else: closest_correst = np.inf dists += [closest_correst] dists = np.array(dists) if max_dur is None: max_dur = np.max(dists) n_bins = int(np.ceil(max_dur / float(intervals))) scores = np.array([np.mean(dists<=i*intervals) for i in range(1, n_bins+1)])*100 return scores
def overlap_(p, y, bg_class): true_intervals = np.array(utils.segment_intervals(y)) true_labels = utils.segment_labels(y) pred_intervals = np.array(utils.segment_intervals(p)) pred_labels = utils.segment_labels(p) if bg_class is not None: true_intervals = np.array([ t for t, l in zip(true_intervals, true_labels) if l != bg_class ]) true_labels = np.array([l for l in true_labels if l != bg_class]) pred_intervals = np.array([ t for t, l in zip(pred_intervals, pred_labels) if l != bg_class ]) pred_labels = np.array([l for l in pred_labels if l != bg_class]) n_true_segs = true_labels.shape[0] n_pred_segs = pred_labels.shape[0] seg_scores = np.zeros(n_true_segs, np.float) for i in range(n_true_segs): for j in range(n_pred_segs): if true_labels[i] == pred_labels[j]: intersection = min( pred_intervals[j][1], true_intervals[i][1]) - max( pred_intervals[j][0], true_intervals[i][0]) union = max(pred_intervals[j][1], true_intervals[i][1]) - min( pred_intervals[j][0], true_intervals[i][0]) score_ = float(intersection) / union seg_scores[i] = max(seg_scores[i], score_) return seg_scores.mean() * 100
def overlap_(p, y, n_classes, bg_class, overlap): true_intervals = np.array(utils.segment_intervals(y)) true_labels = utils.segment_labels(y) pred_intervals = np.array(utils.segment_intervals(p)) pred_labels = utils.segment_labels(p) # Remove background labels if bg_class is not None: true_intervals = true_intervals[true_labels != bg_class] true_labels = true_labels[true_labels != bg_class] pred_intervals = pred_intervals[pred_labels != bg_class] pred_labels = pred_labels[pred_labels != bg_class] n_true = true_labels.shape[0] n_pred = pred_labels.shape[0] # We keep track of the per-class TPs, and FPs. # In the end we just sum over them though. TP = np.zeros(n_classes, np.float) FP = np.zeros(n_classes, np.float) true_used = np.zeros(n_true, np.float) for j in range(n_pred): # Compute IoU against all others intersection = np.minimum( pred_intervals[j, 1], true_intervals[:, 1]) - np.maximum( pred_intervals[j, 0], true_intervals[:, 0]) union = np.maximum(pred_intervals[j, 1], true_intervals[:, 1]) - np.minimum( pred_intervals[j, 0], true_intervals[:, 0]) IoU = (intersection / union) * (pred_labels[j] == true_labels) # Get the best scoring segment idx = IoU.argmax() # If the IoU is high enough and the true segment isn't already used # Then it is a true positive. Otherwise is it a false positive. if IoU[idx] >= overlap and not true_used[idx]: TP[pred_labels[j]] += 1 true_used[idx] = 1 else: FP[pred_labels[j]] += 1 TP = TP.sum() FP = FP.sum() # False negatives are any unused true segment (i.e. "miss") FN = n_true - true_used.sum() precision = TP / (TP + FP) recall = TP / (TP + FN) F1 = 2 * (precision * recall) / (precision + recall) # If the prec+recall=0, it is a NaN. Set these to 0. F1 = np.nan_to_num(F1) return F1 * 100
def edit_score(P, Y, norm=True, bg_class=None, **kwargs): if type(P) == list: tmp = [edit_score(P[i], Y[i], norm, bg_class) for i in range(len(P))] return np.mean(tmp) else: P_ = utils.segment_labels(P) Y_ = utils.segment_labels(Y) if bg_class is not None: P_ = [c for c in P_ if c != bg_class] Y_ = [c for c in Y_ if c != bg_class] return levenstein_(P_, Y_, norm)
def lcs_score(P, Y): if type(P) == list: tmp = [] for i in range(len(P)): P_ = utils.segment_labels(P[i]) Y_ = utils.segment_labels(Y[i]) tmp += [lcs_(P_,Y_)] return np.mean(tmp) else: P_ = utils.segment_labels(P) Y_ = utils.segment_labels(Y) return lcs_(P_, Y_)
def edit_score(P, Y, norm=True): if type(P) == list: tmp = [] for i in range(len(P)): P_ = utils.segment_labels(P[i]) Y_ = utils.segment_labels(Y[i]) tmp += [levenstein_(P_,Y_,norm)] return np.mean(tmp) else: P_ = utils.segment_labels(P) Y_ = utils.segment_labels(Y) return levenstein_(P_, Y_, norm)
def overlap_(p,y): true_intervals = np.array(utils.segment_intervals(y)) true_labels = utils.segment_labels(y) pred_intervals = np.array(utils.segment_intervals(p)) pred_labels = utils.segment_labels(p) n_true_segs = true_labels.shape[0] n_pred_segs = pred_labels.shape[0] seg_scores = np.zeros(n_true_segs, np.float) for i in range(n_true_segs): for j in range(n_pred_segs): if true_labels[i]==pred_labels[j]: intersection = min(pred_intervals[j][1], true_intervals[i][1]) - max(pred_intervals[j][0], true_intervals[i][0]) union = max(pred_intervals[j][1], true_intervals[i][1]) - min(pred_intervals[j][0], true_intervals[i][0]) score_ = float(intersection)/union seg_scores[i] = max(seg_scores[i], score_) return seg_scores.mean()*100
def midpoint_(p,y): """ As suggested in Rohrbach et al (IJCV15) for action detection """ segs_p = utils.segment_intervals(p) segs_y = utils.segment_intervals(y) class_p = utils.segment_labels(p).tolist() class_y = utils.segment_labels(y).tolist() unused = np.ones(len(class_y), np.bool) n_true = len(segs_y) TP, FP, FN = 0, 0, 0 # Go through each segment and check if it's correct. for i in range(len(segs_p)): midpoint = np.mean(segs_p[i]) # Check each corresponding true segment for j in range(n_true): # If the midpoint is in this true segment if segs_y[j][0] <= midpoint <= segs_y[j][1]: # If yes and it's correct if (class_p[i] == class_y[j]): # Only a TP if it's the first occurance. Otherwise FP if unused[j]: TP += 1 unused[j] = 0 else: FP += 1 # FN if it's wrong class else: FN += 1 elif midpoint < segs_y[j][0]: break prec = float(TP) / (TP+FP) * 100 recall = float(TP) / (TP+FN) * 100 return prec, recall
def clf_(p, y, bg_class): sums = 0. n_segs = 0. S_true = utils.segment_labels(y) I_true = np.array(utils.segment_intervals(y)) for i in range(len(S_true)): if S_true[i] == bg_class: continue # If p is 1d, compute the most likely label, otherwise take the max over the score if p.ndim == 1: pred_label = scipy.stats.mode( p[I_true[i][0]:I_true[i][1]])[0][0] else: pred_label = p[I_true[i][0]:I_true[i][1]].mean(1).argmax() sums += pred_label == S_true[i] n_segs += 1 return sums / n_segs * 100
def segmental_pw_cost(Yi, n_classes, skip=1): Yi_ = utils.segment_labels(Yi) return pw_cost(Yi_, n_classes, skip)