Source code for libcity.evaluator.eval_funcs

import numpy as np
import torch


# 均方误差(Mean Square Error)
[docs]def mse(loc_pred, loc_true): assert len(loc_pred) == len(loc_true), 'MSE: 预测数据与真实数据大小不一致' return np.mean(sum(pow(loc_pred - loc_true, 2)))
# 平均绝对误差(Mean Absolute Error)
[docs]def mae(loc_pred, loc_true): assert len(loc_pred) == len(loc_true), 'MAE: 预测数据与真实数据大小不一致' return np.mean(sum(loc_pred - loc_true))
# 均方根误差(Root Mean Square Error)
[docs]def rmse(loc_pred, loc_true): assert len(loc_pred) == len(loc_true), 'RMSE: 预测数据与真实数据大小不一致' return np.sqrt(np.mean(sum(pow(loc_pred - loc_true, 2))))
# 平均绝对百分比误差(Mean Absolute Percentage Error)
[docs]def mape(loc_pred, loc_true): assert len(loc_pred) == len(loc_true), 'MAPE: 预测数据与真实数据大小不一致' assert 0 not in loc_true, "MAPE: 真实数据有0,该公式不适用" return np.mean(abs(loc_pred - loc_true) / loc_true)
# 平均绝对和相对误差(Mean Absolute Relative Error)
[docs]def mare(loc_pred, loc_true): assert len(loc_pred) == len(loc_true), "MARE:预测数据与真实数据大小不一致" assert np.sum(loc_true) != 0, "MARE:真实位置全为0,该公式不适用" return np.sum(np.abs(loc_pred - loc_true)) / np.sum(loc_true)
# 对称平均绝对百分比误差(Symmetric Mean Absolute Percentage Error)
[docs]def smape(loc_pred, loc_true): assert len(loc_pred) == len(loc_true), 'SMAPE: 预测数据与真实数据大小不一致' assert 0 in (loc_pred + loc_true), "SMAPE: 预测数据与真实数据有0,该公式不适用" return 2.0 * np.mean(np.abs(loc_pred - loc_true) / (np.abs(loc_pred) + np.abs(loc_true)))
# 对比真实位置与预测位置获得预测准确率
[docs]def acc(loc_pred, loc_true): assert len(loc_pred) == len(loc_true), "accuracy: 预测数据与真实数据大小不一致" loc_diff = loc_pred - loc_true loc_diff[loc_diff != 0] = 1 return loc_diff, np.mean(loc_diff == 0)
[docs]def top_k(loc_pred, loc_true, topk): """ count the hit numbers of loc_true in topK of loc_pred, used to calculate Precision, Recall and F1-score, calculate the reciprocal rank, used to calcualte MRR, calculate the sum of DCG@K of the batch, used to calculate NDCG Args: loc_pred: (batch_size * output_dim) loc_true: (batch_size * 1) topk: Returns: tuple: tuple contains: hit (int): the hit numbers \n rank (float): the sum of the reciprocal rank of input batch \n dcg (float): dcg """ assert topk > 0, "top-k ACC评估方法:k值应不小于1" loc_pred = torch.FloatTensor(loc_pred) val, index = torch.topk(loc_pred, topk, 1) index = index.numpy() hit = 0 rank = 0.0 dcg = 0.0 for i, p in enumerate(index): target = loc_true[i] if target in p: hit += 1 rank_list = list(p) rank_index = rank_list.index(target) # rank_index is start from 0, so need plus 1 rank += 1.0 / (rank_index + 1) dcg += 1.0 / np.log2(rank_index + 2) return hit, rank, dcg
[docs]def Precision_torch(preds, labels, topk): precision = [] for i in range(preds.shape[0]): label = labels[i] pred = preds[i] accident_grids = label > 0 sorted, _ = torch.sort(pred.flatten(), descending=True) threshold = sorted[topk - 1] pred_grids = pred >= threshold matched = pred_grids & accident_grids precision.append(torch.sum(matched.flatten()).item() / topk) return sum(precision) / len(precision)
[docs]def Recall_torch(preds, labels, topk): recall = [] for i in range(preds.shape[0]): label = labels[i] pred = preds[i] accident_grids = label > 0 sorted, _ = torch.sort(pred.flatten(), descending=True) threshold = sorted[topk - 1] pred_grids = pred >= threshold matched = pred_grids & accident_grids if torch.sum(accident_grids).item() != 0: recall.append(torch.sum(matched.flatten()).item() / torch.sum(accident_grids.flatten()).item()) return sum(recall) / len(recall)
[docs]def F1_Score_torch(preds, labels, topk): precision = Precision_torch(preds, labels, topk) recall = Recall_torch(preds, labels, topk) return 2 * precision * recall / (precision + recall)
[docs]def MAP_torch(preds, labels, topk): ap = [] for i in range(preds.shape[0]): label = labels[i].flatten() pred = preds[i].flatten() accident_grids = label > 0 sorted, rank = torch.sort(pred, descending=True) rank = rank[:topk] if topk != 0: threshold = sorted[topk - 1] else: threshold = 0 label = label != 0 pred = pred >= threshold matched = pred & label match_num = 0 precision_sum = 0 for i in range(rank.shape[0]): if matched[rank[i]]: match_num += 1 precision_sum += match_num / (i + 1) if rank.shape[0] != 0: ap.append(precision_sum / rank.shape[0]) return sum(ap) / len(ap)
[docs]def PCC_torch(preds, labels, topk): pcc = [] for i in range(preds.shape[0]): label = labels[i].flatten() pred = preds[i].flatten() sorted, rank = torch.sort(pred, descending=True) pred = sorted[:topk] rank = rank[:topk] sorted_label = torch.zeros(topk) for i in range(topk): sorted_label[i] = label[rank[i]] label = sorted_label label_average = torch.sum(label) / (label.shape[0]) pred_average = torch.sum(pred) / (pred.shape[0]) if torch.sqrt(torch.sum((label - label_average) * (label - label_average))) * torch.sqrt( torch.sum((pred - pred_average) * (pred - pred_average))) != 0: pcc.append((torch.sum((label - label_average) * (pred - pred_average)) / ( torch.sqrt(torch.sum((label - label_average) * (label - label_average))) * torch.sqrt( torch.sum((pred - pred_average) * (pred - pred_average))))).item()) return sum(pcc) / len(pcc)