mirror of
https://github.com/microsoft/qlib.git
synced 2026-07-10 14:26:56 +08:00
docs and bug fixed
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
Ensemble can merge the objects in an Ensemble. For example, if there are many submodels predictions, we may need to merge them in an ensemble predictions.
|
||||
"""
|
||||
|
||||
from typing import Union
|
||||
import pandas as pd
|
||||
|
||||
|
||||
@@ -24,6 +25,30 @@ class Ensemble:
|
||||
raise NotImplementedError(f"Please implement the `__call__` method.")
|
||||
|
||||
|
||||
class SingleKeyEnsemble(Ensemble):
|
||||
|
||||
"""
|
||||
Extract the object if there is only one key and value in dict. Make result more readable.
|
||||
{Only key: Only value} -> Only value
|
||||
If there are more than 1 key or less than 1 key, then do nothing.
|
||||
Even you can run this recursively to make dict more readable.
|
||||
NOTE: Default run recursively.
|
||||
"""
|
||||
|
||||
def __call__(self, ensemble_dict: Union[dict, object], recursion: bool = True) -> object:
|
||||
if not isinstance(ensemble_dict, dict):
|
||||
return ensemble_dict
|
||||
if recursion:
|
||||
tmp_dict = {}
|
||||
for k, v in ensemble_dict.items():
|
||||
tmp_dict[k] = self(v, recursion)
|
||||
ensemble_dict = tmp_dict
|
||||
keys = list(ensemble_dict.keys())
|
||||
if len(keys) == 1:
|
||||
ensemble_dict = ensemble_dict[keys[0]]
|
||||
return ensemble_dict
|
||||
|
||||
|
||||
class RollingEnsemble(Ensemble):
|
||||
|
||||
"""Merge the rolling objects in an Ensemble"""
|
||||
@@ -47,3 +72,24 @@ class RollingEnsemble(Ensemble):
|
||||
artifact = artifact[~artifact.index.duplicated(keep="last")]
|
||||
artifact = artifact.sort_index()
|
||||
return artifact
|
||||
|
||||
|
||||
class AverageEnsemble(Ensemble):
|
||||
def __call__(self, ensemble_dict: dict):
|
||||
"""
|
||||
Average a dict of same shape dataframe like `prediction` or `IC` into an ensemble.
|
||||
|
||||
NOTE: The values of dict must be pd.DataFrame, and have the index "datetime"
|
||||
|
||||
Args:
|
||||
ensemble_dict (dict): a dict like {"A": pd.DataFrame, "B": pd.DataFrame}.
|
||||
The key of the dict will be ignored.
|
||||
|
||||
Returns:
|
||||
pd.DataFrame: the complete result of averaging.
|
||||
"""
|
||||
values = list(ensemble_dict.values())
|
||||
results = pd.concat(values, axis=1)
|
||||
results = results.mean(axis=1).to_frame("score")
|
||||
results = results.sort_index()
|
||||
return results
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
|
||||
"""
|
||||
Group can group a set of object based on `group_func` and change them to a dict.
|
||||
After group, we provide a method to reduce them.
|
||||
|
||||
For example:
|
||||
|
||||
group: {(A,B,C1): object, (A,B,C2): object} -> {(A,B): {C1: object, C2: object}}
|
||||
reduce: {(A,B): {C1: object, C2: object}} -> {(A,B): object}
|
||||
|
||||
"""
|
||||
|
||||
from qlib.model.ens.ensemble import Ensemble, RollingEnsemble
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
"""
|
||||
The Trainer will train a list of tasks and return a list of model recorder.
|
||||
There are two steps in each Trainer including `train`(make model recorder) and `end_train`(modify model recorder).
|
||||
There are two steps in each Trainer including ``train``(make model recorder) and ``end_train``(modify model recorder).
|
||||
|
||||
This is concept called "DelayTrainer", which can be used in online simulating to parallel training.
|
||||
In "DelayTrainer", the first step is only to save some necessary info to model recorder, and the second step which will be finished in the end can do some concurrent and time-consuming operations such as model fitting.
|
||||
This is concept called ``DelayTrainer``, which can be used in online simulating to parallel training.
|
||||
In ``DelayTrainer``, the first step is only to save some necessary info to model recorder, and the second step which will be finished in the end can do some concurrent and time-consuming operations such as model fitting.
|
||||
|
||||
`Qlib` offer two kind of Trainer, TrainerR is simplest and TrainerRM is based on TaskManager to help manager tasks lifecycle automatically.
|
||||
``Qlib`` offer two kind of Trainer, ``TrainerR`` is the simplest way and ``TrainerRM`` is based on TaskManager to help manager tasks lifecycle automatically.
|
||||
"""
|
||||
|
||||
import socket
|
||||
@@ -36,9 +36,6 @@ def begin_task_train(task_config: dict, experiment_name: str, recorder_name: str
|
||||
Returns:
|
||||
Recorder: the model recorder
|
||||
"""
|
||||
# FIXME: recorder_id
|
||||
if recorder_name is None:
|
||||
recorder_name = str(time.time())
|
||||
with R.start(experiment_name=experiment_name, recorder_name=recorder_name):
|
||||
R.log_params(**flatten_dict(task_config))
|
||||
R.save_objects(**{"task": task_config}) # keep the original format and datatype
|
||||
@@ -58,7 +55,7 @@ def end_task_train(rec: Recorder, experiment_name: str) -> Recorder:
|
||||
Returns:
|
||||
Recorder: the model recorder
|
||||
"""
|
||||
with R.start(experiment_name=experiment_name, recorder_name=rec.info["name"], resume=True):
|
||||
with R.start(experiment_name=experiment_name, recorder_id=rec.info["id"], resume=True):
|
||||
task_config = R.load_object("task")
|
||||
# model & dataset initiation
|
||||
model: Model = init_instance_by_config(task_config["model"])
|
||||
@@ -314,7 +311,8 @@ class TrainerRM(Trainer):
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
NOTE: this method will delete all task in this task_pool!
|
||||
.. note::
|
||||
this method will delete all task in this task_pool!
|
||||
"""
|
||||
tm = TaskManager(task_pool=self.task_pool)
|
||||
tm.remove()
|
||||
|
||||
Reference in New Issue
Block a user