1
0
mirror of https://github.com/microsoft/qlib.git synced 2026-07-11 14:56:55 +08:00

online_serving V3

This commit is contained in:
lzh222333
2021-03-18 09:30:01 +00:00
parent d33041dc24
commit 8abdd63869
9 changed files with 333 additions and 273 deletions

View File

@@ -8,7 +8,7 @@ from qlib import get_module_logger
class TaskCollector:
"""
Collect the record results of the finished tasks with key and filter
Collect the record (or its results) of the tasks
"""
def __init__(self, experiment_name: str) -> None:
@@ -17,7 +17,7 @@ class TaskCollector:
self.logger = get_module_logger("TaskCollector")
def list_recorders(self, rec_filter_func=None):
""""""
recs = self.exp.list_recorders()
recs_flt = {}
for rid, rec in recs.items():
@@ -26,57 +26,77 @@ class TaskCollector:
return recs_flt
def list_recorders_by_task(self, task_filter_func=None):
def rec_filter(recorder):
return task_filter_func(self.get_task(recorder))
return self.list_recorders(rec_filter)
def list_latest_recorders(self, rec_filter_func=None):
recs_flt = self.list_recorders(rec_filter_func)
max_test = self.latest_time(recs_flt)
latest_rec = {}
for rid, rec in recs_flt.items():
if self.get_task(rec)["dataset"]["kwargs"]["segments"]["test"] == max_test:
latest_rec[rid] = rec
return latest_rec
def get_recorder_by_id(self, recorder_id):
return self.exp.get_recorder(recorder_id, create=False)
def list_recorders_by_task(self, task_filter_func):
"""[summary]
def get_task(self, recorder):
if isinstance(recorder, str):
recorder = self.get_recorder_by_id(recorder_id=recorder)
try:
task = recorder.load_object("task")
except OSError:
raise OSError(f"Can't find task in {recorder.info['id']}, have you trained with model.trainer.task_train?")
return task
Parameters
----------
task_filter_func : [type], optional
[description], by default None
"""
def latest_time(self, recorders):
if len(recorders) == 0:
raise Exception(f"Can't find any recorder in {self.exp_name}")
max_test = max(self.get_task(rec)["dataset"]["kwargs"]["segments"]["test"] for rec in recorders.values())
return max_test
def rec_filter_func(recorder):
try:
task = recorder.load_object("task")
except OSError:
raise OSError(
f"Can't find task in {recorder.info['id']}, have you trained with model.trainer.task_train?"
)
return task_filter_func(task)
return self.list_recorders(rec_filter_func)
class RollingCollector(TaskCollector):
"""
Collect the record results of the rolling tasks
"""
def collect_predictions(
def __init__(
self,
get_key_func,
task_filter_func=None,
):
"""
Collect predictions using a filter and a key function.
experiment_name: str,
) -> None:
super().__init__(experiment_name)
self.logger = get_module_logger("RollingCollector")
def collect_rolling_predictions(self, get_key_func, rec_filter_func=None):
"""For rolling tasks, the predictions will be in the diffierent recorder.
To collect and concat the predictions of one rolling task, get_key_func will help this method see which group a recorder will be.
Parameters
----------
experiment_name : str
get_key_func : Callable[[dict], bool] -> Union[Number, str, tuple]
get the key of a task when collect it
filter_func : Callable[[dict], bool] -> bool
to judge a task will be collected or not
get_key_func : Callable[dict,str]
a function that get task config and return its group str
rec_filter_func : Callable[Recorder,bool], optional
a function that decide whether filter a recorder, by default None
Returns
-------
dict
the dict of predictions
a dict of {group: predictions}
"""
recs_flt = self.list_recorders(task_filter_func=task_filter_func, only_have_task=True)
# filter records
recs_flt = self.list_recorders(rec_filter_func)
# group
recs_group = {}
for _, rec in recs_flt.items():
params = rec.task
group_key = get_key_func(params)
task = self.get_task(rec)
group_key = get_key_func(task)
recs_group.setdefault(group_key, []).append(rec)
# reduce group
@@ -85,39 +105,12 @@ class TaskCollector:
pred_l = []
for rec in rec_l:
pred_l.append(rec.load_object("pred.pkl").iloc[:, 0])
pred = pd.concat(pred_l).sort_index()
# Make sure the pred are sorted according to the rolling start time
pred_l.sort(key=lambda pred: pred.index.get_level_values("datetime").min())
pred = pd.concat(pred_l)
# If there are duplicated predition, we use the latest perdiction
pred = pred[~pred.index.duplicated(keep="last")]
pred = pred.sort_index()
reduce_group[k] = pred
self.logger.info(f"Collect {len(reduce_group)} predictions in {self.exp_name}")
return reduce_group
def collect_latest_records(
self,
task_filter_func=None,
):
"""Collect latest recorders using a filter.
Parameters
----------
task_filter_func : Callable[[dict], bool], optional
to judge a task will be collected or not, by default None
Returns
-------
dict, tuple
a dict of recorders and a tuple of test segments
"""
recs_flt = self.list_recorders(task_filter_func=task_filter_func, only_have_task=True)
if len(recs_flt) == 0:
self.logger.warning("Can not collect any recorders...")
return None, None
max_test = max(rec.task["dataset"]["kwargs"]["segments"]["test"] for rec in recs_flt.values())
latest_record = {}
for rid, rec in recs_flt.items():
if rec.task["dataset"]["kwargs"]["segments"]["test"] == max_test:
latest_record[rid] = rec
self.logger.info(f"Collect {len(latest_record)} latest records in {self.exp_name}")
return latest_record, max_test
return reduce_group