Customize Metrics¶
Here we present how to develop a new metric, and apply it into RecBole. Users can implement their customized metrics and combine the metrics with others for personal evaluation.
Here, it only takes three steps to incorporate a new metric and we introduce them step by step.
Create a New Metric Class¶
Then, we create a new class in the file ~recbole.evaluator.metrics
and define the parameter in __init__()
:
from recbole.evaluator.base_metric import AbstractMetric
class MyMetric(AbstractMetric):
def __init__(self, config):
Set properties of the metric¶
After that, we set the properties of metrics:
Set metric_need
¶
It is a list that contains one or multiple string that corresponding to needed input of metrics. For now, we support 9 inputs for metrics including both recommendation results and information of dataset which are listed below.
Notation |
Explanation |
---|---|
rec.items |
K recommended items for each user |
rec.topk |
Boolean matrix indicating the existence of a recommended item in the test set and number of positive items for each user |
rec.meanrank |
Mean ranking of positive items for each user |
rec.score |
Pure output score |
data.num_items |
Number of item in dataset |
data.num_users |
Number of user in dataset |
data.count_items |
Interaction number of each item in training data |
data.count_users |
Interaction number of each user in training data |
data.label |
Pure label field of input data (Usually used with rec.score together) |
Set metric_type
¶
It indicates whether the scores required by metric are grouped by user,
range in EvaluatorType.RANKING
(for grouped ones) and EvaluatorType.VALUE
(for non-grouped ones).
In current RecBole, all the “grouped” metrics are ranking-based and all the “non-grouped”
metrics are value-based. To keep with our paper, we adopted the more formal terms: RANKING
and VALUE
.
Set smaller
¶
It indicates whether the smaller metric value represents better performance, range in
True
and False
, default to False
.
Example¶
If we want to add a ranking-based metric named YourMetric
which needs the recommended items and the
total item number, and the smaller YourMetric
indicates better model performance, the code is shown below:
from recbole.evaluator.base_metric import AbstractMetric
from recbole.utils import EvaluatorType
class MyMetric(AbstractMetric):
metric_type = EvaluatorType.RANKING
metric_need = ['rec.items', 'data.num_items']
smaller = True
def __init__(self, config):
Implement calculate_metric(self, dataobject)¶
All the computational process is defined in this function. The args is a packaged data object that
contains all the result above. We can treat it as a dict and get data from it by
rec_items = dataobject.get('rec.items')
. The returned value should be a dict with key of metric name
and value of final result. Note that the metric name should be lowercase.
Example code:
def calculate_metric(self, dataobject):
"""Get the dictionary of a metric.
Args:
dataobject(DataStruct): it contains all the information needed to calculate metrics.
Returns:
dict: such as ``{'mymetric@10': 3153, 'mymetric@20': 0.3824}``
"""
rec_items = dataobject.get('rec.items')
# Add the logic of your metric here.
return result_dict