-
Notifications
You must be signed in to change notification settings - Fork 0
/
metric.py
52 lines (44 loc) · 2.5 KB
/
metric.py
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
import typing
import numpy as np
from sklearn.metrics import mean_absolute_percentage_error, r2_score, mean_squared_error
THRESHOLD = 0.15
NEGATIVE_WEIGHT = 1.1
def deviation_metric_one_sample(y_true: typing.Union[float, int], y_pred: typing.Union[float, int]) -> float:
"""
Реализация кастомной метрики для хакатона.
:param y_true: float, реальная цена
:param y_pred: float, предсказанная цена
:return: float, значение метрики
"""
deviation = (y_true-y_pred) / np.maximum(1e-8, y_true)
if np.abs(deviation) <= THRESHOLD:
return 0
elif deviation <= - 4 * THRESHOLD:
return 9 * NEGATIVE_WEIGHT
elif deviation < -THRESHOLD:
return NEGATIVE_WEIGHT * ((deviation / THRESHOLD) + 1) ** 2
elif deviation < 4 * THRESHOLD:
return ((deviation / THRESHOLD) - 1) ** 2
else:
return 9
def deviation_metric(y_true: np.array, y_pred: np.array) -> float:
return np.array([deviation_metric_one_sample(y_true[n], y_pred[n]) for n in range(len(y_true))]).mean()
def median_absolute_percentage_error(y_true: np.array, y_pred: np.array) -> float:
return np.median(np.abs(y_pred-y_true)/y_true)
def metrics_stat(y_true: np.array, y_pred: np.array) -> typing.Dict[str,float]:
mape = mean_absolute_percentage_error(y_true, y_pred)
mdape = median_absolute_percentage_error(y_true, y_pred)
rmse = mean_squared_error(y_true, y_pred, squared=False)
r2 = r2_score(y_true, y_pred)
raif_metric = deviation_metric(y_true, y_pred)
return {'mape':mape, 'mdape':mdape, 'rmse': rmse, 'r2': r2, 'raif_metric':raif_metric}
# EPS = 1e-8
# assert deviation_metric(np.array([1,2,3,4,5]),np.array([1,2,3,4,5])) <= EPS
# assert deviation_metric(np.array([1,2,3,4,5]),np.array([0.9,1.8,2.7,3.6,4.5])) <= EPS
# assert deviation_metric(np.array([1,2,3,4,5]),np.array([1.1,2.2,3.3,4.4,5.5])) <= EPS
# assert deviation_metric(np.array([1,2,3,4,5]),np.array([1.15,2.3,3.45,4.6,5.75])) <= EPS
# assert np.abs(deviation_metric(np.array([1,2,3,4,5]),np.array([1.3,2.6,3.9,5.2,6.5]))-1) <= EPS
# assert np.abs(deviation_metric(np.array([1,2,3,4,5]),np.array([0.7,1.4,2.1,2.8,3.5]))-1*NEGATIVE_WEIGHT) <= EPS
# assert np.abs(deviation_metric(np.array([1,2,3,4,5]),np.array([10,20,30,40,50]))-9) <= EPS
# assert np.abs(deviation_metric(np.array([1,2,3,4,5]),np.array([0,0,0,0,0]))-9*NEGATIVE_WEIGHT) <= EPS
# assert np.abs(deviation_metric(np.array([1,2,3,4,5]),np.array([1,2.2,3.3,5,50])) - 85/45) <= EPS