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

Refactor update & modification when running NN

This commit is contained in:
Young
2021-04-11 14:39:19 +00:00
parent a366c11d67
commit cca43cf102
8 changed files with 211 additions and 33 deletions

View File

@@ -1,6 +1,7 @@
from qlib.model.ens.ensemble import Ensemble, RollingEnsemble
from typing import Callable, Union
from qlib.utils.serial import Serializable
from joblib import Parallel, delayed
class Group(Serializable):
@@ -18,10 +19,23 @@ class Group(Serializable):
ens (Ensemble, optional): If not None, do ensemble for grouped value after grouping.
"""
self.group = group_func
self.ens = ens
self._group_func = group_func
self._ens_func = ens
def __call__(self, ungrouped_dict: dict, *args, **kwargs):
def group(self, *args, **kwargs):
# TODO: such design is weird when `_group_func` is the only configurable part in the class
if isinstance(getattr(self, "_group_func", None), Callable):
return self._group_func(*args, **kwargs)
else:
raise NotImplementedError(f"Please specify valid `group_func`.")
def reduce(self, *args, **kwargs):
if isinstance(getattr(self, "_ens_func", None), Callable):
return self._ens_func(*args, **kwargs)
else:
raise NotImplementedError(f"Please specify valid `_ens_func`.")
def __call__(self, ungrouped_dict: dict, n_jobs=1, verbose=0, *args, **kwargs):
"""Group the ungrouped_dict into different groups.
Args:
@@ -30,23 +44,24 @@ class Group(Serializable):
Returns:
dict: grouped_dict like {G1: object, G2: object}
"""
if isinstance(getattr(self, "group", None), Callable):
grouped_dict = self.group(ungrouped_dict, *args, **kwargs)
if self.ens is not None:
ens_dict = {}
for key, value in grouped_dict.items():
ens_dict[key] = self.ens(value)
grouped_dict = ens_dict
return grouped_dict
else:
raise NotImplementedError(f"Please specify valid group_func.")
# FIXME: The multiprocessing will raise the following error
# NotImplementedError: Please specify valid `_ens_func`.
# The problem maybe the state of the function is lost
grouped_dict = self.group(ungrouped_dict, *args, **kwargs)
key_l = []
job_l = []
for key, value in grouped_dict.items():
key_l.append(key)
job_l.append(delayed(Group.reduce)(self, value))
return dict(zip(key_l, Parallel(n_jobs=n_jobs, verbose=verbose)(job_l)))
class RollingGroup(Group):
"""group the rolling dict"""
@staticmethod
def rolling_group(rolling_dict: dict):
def group(self, rolling_dict: dict):
"""Given an rolling dict likes {(A,B,R): things}, return the grouped dict likes {(A,B): {R:things}}
NOTE: There is a assumption which is the rolling key is at the end of key tuple, because the rolling results always need to be ensemble firstly.
@@ -63,7 +78,5 @@ class RollingGroup(Group):
grouped_dict.setdefault(key[:-1], {})[key[-1]] = values
return grouped_dict
def __init__(self, group_func=None):
super().__init__(group_func=group_func, ens=RollingEnsemble())
if group_func is None:
self.group = RollingGroup.rolling_group
def __init__(self):
super().__init__(ens=RollingEnsemble())