|
import torch |
|
import numpy as np |
|
import math |
|
|
|
|
|
def f2_score(y_true, y_pred, threshold=0.5): |
|
return fbeta_score(y_true, y_pred, 2, threshold) |
|
|
|
|
|
def dice(logit, truth, threshold=0.5): |
|
batch_size = len(truth) |
|
|
|
with torch.no_grad(): |
|
logit = logit.view(batch_size, -1) |
|
truth = truth.view(batch_size, -1) |
|
assert logit.shape == truth.shape |
|
|
|
probability = logit |
|
p = (probability > threshold).float() |
|
t = (truth > 0.5).float() |
|
|
|
t_sum = t.sum(-1) |
|
p_sum = p.sum(-1) |
|
neg_index = torch.nonzero(t_sum == 0) |
|
pos_index = torch.nonzero(t_sum >= 1) |
|
|
|
|
|
dice_neg = (p_sum == 0).float() |
|
dice_pos = 2 * (p * t).sum(-1) / ((p + t).sum(-1)) |
|
|
|
dice_neg = dice_neg[neg_index] |
|
dice_pos = dice_pos[pos_index] |
|
dice = torch.cat([dice_pos, dice_neg]) |
|
|
|
dice_neg = np.nan_to_num(dice_neg.mean().item(), 0) |
|
dice_pos = np.nan_to_num(dice_pos.mean().item(), 0) |
|
dice = dice.mean().item() |
|
|
|
num_neg = len(neg_index) |
|
num_pos = len(pos_index) |
|
|
|
return dice, dice_neg, dice_pos, num_neg, num_pos |
|
|
|
|
|
def mIoU(results, masks, threshold=0.5, eps=1): |
|
""" |
|
:param results: b w h |
|
:param masks: b w h |
|
:param threshold: 0.5 |
|
:return: |
|
""" |
|
results = (results > threshold).float() |
|
b = len(results) |
|
results = results.view(b, -1).detach().cpu().numpy() |
|
masks = masks.view(b, -1).detach().cpu().numpy() |
|
intersection = (masks * results).sum(1) |
|
union = results.sum(1) + masks.sum(1) - intersection |
|
union = torch.from_numpy(union) |
|
intersection = torch.from_numpy(intersection) |
|
intersection = torch.clamp(intersection, 0, 1e8) |
|
union = torch.clamp(union, 0, 1e8) |
|
ious = ((intersection + eps) / (union + eps)).mean() |
|
return ious |
|
|
|
|
|
def fbeta_score_threshold_matrix(y_true, y_pred, threshold, beta=2, eps=1e-9): |
|
beta2 = beta ** 2 |
|
threshold = torch.from_numpy(threshold) |
|
threshold = threshold.unsqueeze(0).repeat(len(y_pred), 1).float() |
|
y_pred = (y_pred > threshold).float() |
|
y_true = y_true.float() |
|
|
|
true_positive = (y_pred * y_true).sum(dim=1) |
|
precision = true_positive.div(y_pred.sum(dim=1).add(eps)) |
|
recall = true_positive.div(y_true.sum(dim=1).add(eps)) |
|
|
|
return torch.mean( |
|
(precision * recall).div(precision.mul(beta2) + recall + eps).mul(1 + beta2) |
|
).item() |
|
|
|
|
|
def fbeta_score(y_true, y_pred, beta, threshold, eps=1e-9): |
|
beta2 = beta ** 2 |
|
|
|
y_pred = torch.ge(y_pred.float(), threshold).float() |
|
y_true = y_true.float() |
|
|
|
true_positive = (y_pred * y_true).sum(dim=1) |
|
precision = true_positive.div(y_pred.sum(dim=1).add(eps)) |
|
recall = true_positive.div(y_true.sum(dim=1).add(eps)) |
|
|
|
return torch.mean( |
|
(precision * recall).div(precision.mul(beta2) + recall + eps).mul(1 + beta2) |
|
).item() |
|
|
|
|
|
def create_class_weight(labels_dict, mu=0.5): |
|
total = np.sum(np.array(list(labels_dict.values()))) |
|
keys = labels_dict.keys() |
|
class_weight = dict() |
|
class_weight_log = dict() |
|
for key in keys: |
|
score = total / float(labels_dict[key]) |
|
score_log = math.log(mu * total / float(labels_dict[key])) |
|
class_weight[key] = round(score, 2) if score > 1.0 else round(1.0, 2) |
|
class_weight_log[key] = ( |
|
round(score_log, 2) if score_log > 1.0 else round(1.0, 2) |
|
) |
|
|
|
return class_weight, class_weight_log |
|
|
|
|
|
def get_weight(targets): |
|
dict_label = {} |
|
for Target in targets: |
|
labels = Target.split(" ") |
|
labels = [int(l) for l in labels] |
|
for label in labels: |
|
if label in dict_label.keys(): |
|
dict_label[label] += 1 |
|
else: |
|
dict_label[label] = 1 |
|
|
|
Target2 = [sorted([int(i) for i in t.split(" ")]) for t in targets] |
|
class_weight, class_weight_log = create_class_weight(dict_label) |
|
|
|
weights = [] |
|
for t in Target2: |
|
w = 0 |
|
for t_ in t: |
|
w += class_weight_log[t_] |
|
weights.append(w) |
|
return weights |
|
|