-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathevaluation_metric.py
executable file
·58 lines (47 loc) · 2.43 KB
/
evaluation_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
53
54
55
56
57
58
import numpy as np
import pandas as pd
import pandas.api.types
import scipy.stats
class ParticipantVisibleError(Exception):
pass
def score(
solution: pd.DataFrame,
submission: pd.DataFrame,
row_id_column_name: str,
naive_mean: float,
naive_sigma: float,
sigma_true: float
) -> float:
'''
This is a Gaussian Log Likelihood based metric. For a submission, which contains the predicted mean (x_hat) and variance (x_hat_std),
we calculate the Gaussian Log-likelihood (GLL) value to the provided ground truth (x). We treat each pair of x_hat,
x_hat_std as a 1D gaussian, meaning there will be 283 1D gaussian distributions, hence 283 values for each test spectrum,
the GLL value for one spectrum is the sum of all of them.
Inputs:
- solution: Ground Truth spectra (from test set)
- shape: (nsamples, n_wavelengths)
- submission: Predicted spectra and errors (from participants)
- shape: (nsamples, n_wavelengths*2)
naive_mean: (float) mean from the train set.
naive_sigma: (float) standard deviation from the train set.
sigma_true: (float) essentially sets the scale of the outputs.
'''
del solution[row_id_column_name]
del submission[row_id_column_name]
if submission.min().min() < 0:
raise ParticipantVisibleError('Negative values in the submission')
for col in submission.columns:
if not pandas.api.types.is_numeric_dtype(submission[col]):
raise ParticipantVisibleError(f'Submission column {col} must be a number')
n_wavelengths = len(solution.columns)
if len(submission.columns) != n_wavelengths*2:
raise ParticipantVisibleError('Wrong number of columns in the submission')
y_pred = submission.iloc[:, :n_wavelengths].values
# Set a non-zero minimum sigma pred to prevent division by zero errors.
sigma_pred = np.clip(submission.iloc[:, n_wavelengths:].values, a_min=10**-15, a_max=None)
y_true = solution.values
GLL_pred = np.sum(scipy.stats.norm.logpdf(y_true, loc=y_pred, scale=sigma_pred))
GLL_true = np.sum(scipy.stats.norm.logpdf(y_true, loc=y_true, scale=sigma_true * np.ones_like(y_true)))
GLL_mean = np.sum(scipy.stats.norm.logpdf(y_true, loc=naive_mean * np.ones_like(y_true), scale=naive_sigma * np.ones_like(y_true)))
submit_score = (GLL_pred - GLL_mean)/(GLL_true - GLL_mean)
return float(np.clip(submit_score, 0.0, 1.0))