1
0
mirror of https://github.com/microsoft/qlib.git synced 2026-07-13 15:56:57 +08:00

Merge pull request #314 from D-X-Y/fshare

(1) Fix /0 bug in double_ensemble, (2) remove _default_uri for R/expm, (3) support model size in pytorch models
This commit is contained in:
you-n-g
2021-03-11 20:51:16 +08:00
committed by GitHub
23 changed files with 185 additions and 70 deletions

View File

@@ -105,7 +105,7 @@ _default_config = {
"redis_port": 6379, "redis_port": 6379,
"redis_task_db": 1, "redis_task_db": 1,
# This value can be reset via qlib.init # This value can be reset via qlib.init
"logging_level": "INFO", "logging_level": logging.INFO,
# Global configuration of qlib log # Global configuration of qlib log
# logging_level can control the logging level more finely # logging_level can control the logging level more finely
"logging_config": { "logging_config": {
@@ -124,12 +124,12 @@ _default_config = {
"handlers": { "handlers": {
"console": { "console": {
"class": "logging.StreamHandler", "class": "logging.StreamHandler",
"level": "DEBUG", "level": logging.DEBUG,
"formatter": "logger_format", "formatter": "logger_format",
"filters": ["field_not_found"], "filters": ["field_not_found"],
} }
}, },
"loggers": {"qlib": {"level": "DEBUG", "handlers": ["console"]}}, "loggers": {"qlib": {"level": logging.DEBUG, "handlers": ["console"]}},
}, },
# Defatult config for experiment manager # Defatult config for experiment manager
"exp_manager": { "exp_manager": {
@@ -185,7 +185,7 @@ MODE_CONF = {
# The nfs should be auto-mounted by qlib on other # The nfs should be auto-mounted by qlib on other
# serversS(such as PAI) [auto_mount:True] # serversS(such as PAI) [auto_mount:True]
"timeout": 100, "timeout": 100,
"logging_level": "INFO", "logging_level": logging.INFO,
"region": REG_CN, "region": REG_CN,
## Custom Operator ## Custom Operator
"custom_ops": [], "custom_ops": [],

View File

@@ -104,10 +104,9 @@ class Account:
# if suspend, no new price to be updated, profit is 0 # if suspend, no new price to be updated, profit is 0
if trader.check_stock_suspended(code, today): if trader.check_stock_suspended(code, today):
continue continue
else: today_close = trader.get_close(code, today)
today_close = trader.get_close(code, today) profit += (today_close - self.current.position[code]["price"]) * self.current.position[code]["amount"]
profit += (today_close - self.current.position[code]["price"]) * self.current.position[code]["amount"] self.current.update_stock_price(stock_id=code, price=today_close)
self.current.update_stock_price(stock_id=code, price=today_close)
self.rtn += profit self.rtn += profit
# update holding day count # update holding day count
self.current.add_count_all() self.current.add_count_all()

View File

@@ -184,7 +184,7 @@ class DEnsembleModel(Model):
/ M / M
) )
loss_feat = self.get_loss(y_train.values.squeeze(), pred.values) loss_feat = self.get_loss(y_train.values.squeeze(), pred.values)
g.loc[i_f, "g_value"] = np.mean(loss_feat - loss_values) / np.std(loss_feat - loss_values) g.loc[i_f, "g_value"] = np.mean(loss_feat - loss_values) / (np.std(loss_feat - loss_values) + 1e-7)
x_train_tmp.loc[:, feat] = x_train.loc[:, feat].copy() x_train_tmp.loc[:, feat] = x_train.loc[:, feat].copy()
# one column in train features is all-nan # if g['g_value'].isna().any() # one column in train features is all-nan # if g['g_value'].isna().any()

View File

@@ -23,6 +23,7 @@ import torch
import torch.nn as nn import torch.nn as nn
import torch.optim as optim import torch.optim as optim
from .pytorch_utils import count_parameters
from ...model.base import Model from ...model.base import Model
from ...data.dataset import DatasetH from ...data.dataset import DatasetH
from ...data.dataset.handler import DataHandlerLP from ...data.dataset.handler import DataHandlerLP
@@ -39,8 +40,8 @@ class ALSTM(Model):
the evaluate metric used in early stop the evaluate metric used in early stop
optimizer : str optimizer : str
optimizer name optimizer name
GPU : str GPU : int
the GPU ID(s) used for training the GPU ID used for training
""" """
def __init__( def __init__(
@@ -76,7 +77,7 @@ class ALSTM(Model):
self.early_stop = early_stop self.early_stop = early_stop
self.optimizer = optimizer.lower() self.optimizer = optimizer.lower()
self.loss = loss self.loss = loss
self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() and GPU >= 0 else "cpu")
self.use_gpu = torch.cuda.is_available() self.use_gpu = torch.cuda.is_available()
self.seed = seed self.seed = seed
@@ -123,6 +124,9 @@ class ALSTM(Model):
num_layers=self.num_layers, num_layers=self.num_layers,
dropout=self.dropout, dropout=self.dropout,
) )
self.logger.info("model:\n{:}".format(self.ALSTM_model))
self.logger.info("model size: {:.4f} MB".format(count_parameters(self.ALSTM_model)))
if optimizer.lower() == "adam": if optimizer.lower() == "adam":
self.train_optimizer = optim.Adam(self.ALSTM_model.parameters(), lr=self.lr) self.train_optimizer = optim.Adam(self.ALSTM_model.parameters(), lr=self.lr)
elif optimizer.lower() == "gd": elif optimizer.lower() == "gd":
@@ -214,7 +218,6 @@ class ALSTM(Model):
self, self,
dataset: DatasetH, dataset: DatasetH,
evals_result=dict(), evals_result=dict(),
verbose=True,
save_path=None, save_path=None,
): ):

View File

@@ -24,6 +24,7 @@ import torch.nn as nn
import torch.optim as optim import torch.optim as optim
from torch.utils.data import DataLoader from torch.utils.data import DataLoader
from .pytorch_utils import count_parameters
from ...model.base import Model from ...model.base import Model
from ...data.dataset import DatasetH, TSDatasetH from ...data.dataset import DatasetH, TSDatasetH
from ...data.dataset.handler import DataHandlerLP from ...data.dataset.handler import DataHandlerLP
@@ -40,8 +41,8 @@ class ALSTM(Model):
the evaluate metric used in early stop the evaluate metric used in early stop
optimizer : str optimizer : str
optimizer name optimizer name
GPU : str GPU : int
the GPU ID(s) used for training the GPU ID used for training
""" """
def __init__( def __init__(
@@ -78,7 +79,7 @@ class ALSTM(Model):
self.early_stop = early_stop self.early_stop = early_stop
self.optimizer = optimizer.lower() self.optimizer = optimizer.lower()
self.loss = loss self.loss = loss
self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() and GPU >= 0 else "cpu")
self.n_jobs = n_jobs self.n_jobs = n_jobs
self.use_gpu = torch.cuda.is_available() self.use_gpu = torch.cuda.is_available()
self.seed = seed self.seed = seed
@@ -127,7 +128,10 @@ class ALSTM(Model):
hidden_size=self.hidden_size, hidden_size=self.hidden_size,
num_layers=self.num_layers, num_layers=self.num_layers,
dropout=self.dropout, dropout=self.dropout,
).to(self.device) )
self.logger.info("model:\n{:}".format(self.ALSTM_model))
self.logger.info("model size: {:.4f} MB".format(count_parameters(self.ALSTM_model)))
if optimizer.lower() == "adam": if optimizer.lower() == "adam":
self.train_optimizer = optim.Adam(self.ALSTM_model.parameters(), lr=self.lr) self.train_optimizer = optim.Adam(self.ALSTM_model.parameters(), lr=self.lr)
elif optimizer.lower() == "gd": elif optimizer.lower() == "gd":
@@ -201,7 +205,6 @@ class ALSTM(Model):
self, self,
dataset, dataset,
evals_result=dict(), evals_result=dict(),
verbose=True,
save_path=None, save_path=None,
): ):
dl_train = dataset.prepare("train", col_set=["feature", "label"], data_key=DataHandlerLP.DK_L) dl_train = dataset.prepare("train", col_set=["feature", "label"], data_key=DataHandlerLP.DK_L)

View File

@@ -22,6 +22,7 @@ import torch
import torch.nn as nn import torch.nn as nn
import torch.optim as optim import torch.optim as optim
from .pytorch_utils import count_parameters
from ...model.base import Model from ...model.base import Model
from ...data.dataset import DatasetH from ...data.dataset import DatasetH
from ...data.dataset.handler import DataHandlerLP from ...data.dataset.handler import DataHandlerLP
@@ -42,8 +43,8 @@ class GATs(Model):
the evaluate metric used in early stop the evaluate metric used in early stop
optimizer : str optimizer : str
optimizer name optimizer name
GPU : str GPU : int
the GPU ID(s) used for training the GPU ID used for training
""" """
def __init__( def __init__(
@@ -83,7 +84,7 @@ class GATs(Model):
self.base_model = base_model self.base_model = base_model
self.with_pretrain = with_pretrain self.with_pretrain = with_pretrain
self.model_path = model_path self.model_path = model_path
self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() and GPU >= 0 else "cpu")
self.use_gpu = torch.cuda.is_available() self.use_gpu = torch.cuda.is_available()
self.seed = seed self.seed = seed
@@ -135,6 +136,9 @@ class GATs(Model):
dropout=self.dropout, dropout=self.dropout,
base_model=self.base_model, base_model=self.base_model,
) )
self.logger.info("model:\n{:}".format(self.GAT_model))
self.logger.info("model size: {:.4f} MB".format(count_parameters(self.GAT_model)))
if optimizer.lower() == "adam": if optimizer.lower() == "adam":
self.train_optimizer = optim.Adam(self.GAT_model.parameters(), lr=self.lr) self.train_optimizer = optim.Adam(self.GAT_model.parameters(), lr=self.lr)
elif optimizer.lower() == "gd": elif optimizer.lower() == "gd":
@@ -232,7 +236,6 @@ class GATs(Model):
self, self,
dataset: DatasetH, dataset: DatasetH,
evals_result=dict(), evals_result=dict(),
verbose=True,
save_path=None, save_path=None,
): ):

View File

@@ -24,6 +24,7 @@ import torch.optim as optim
from torch.utils.data import DataLoader from torch.utils.data import DataLoader
from torch.utils.data import Sampler from torch.utils.data import Sampler
from .pytorch_utils import count_parameters
from ...model.base import Model from ...model.base import Model
from ...data.dataset import DatasetH from ...data.dataset import DatasetH
from ...data.dataset.handler import DataHandlerLP from ...data.dataset.handler import DataHandlerLP
@@ -62,8 +63,8 @@ class GATs(Model):
the evaluate metric used in early stop the evaluate metric used in early stop
optimizer : str optimizer : str
optimizer name optimizer name
GPU : str GPU : int
the GPU ID(s) used for training the GPU ID used for training
""" """
def __init__( def __init__(
@@ -104,7 +105,7 @@ class GATs(Model):
self.base_model = base_model self.base_model = base_model
self.with_pretrain = with_pretrain self.with_pretrain = with_pretrain
self.model_path = model_path self.model_path = model_path
self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() and GPU >= 0 else "cpu")
self.n_jobs = n_jobs self.n_jobs = n_jobs
self.use_gpu = torch.cuda.is_available() self.use_gpu = torch.cuda.is_available()
self.seed = seed self.seed = seed
@@ -157,6 +158,9 @@ class GATs(Model):
dropout=self.dropout, dropout=self.dropout,
base_model=self.base_model, base_model=self.base_model,
) )
self.logger.info("model:\n{:}".format(self.GAT_model))
self.logger.info("model size: {:.4f} MB".format(count_parameters(self.GAT_model)))
if optimizer.lower() == "adam": if optimizer.lower() == "adam":
self.train_optimizer = optim.Adam(self.GAT_model.parameters(), lr=self.lr) self.train_optimizer = optim.Adam(self.GAT_model.parameters(), lr=self.lr)
elif optimizer.lower() == "gd": elif optimizer.lower() == "gd":
@@ -245,7 +249,6 @@ class GATs(Model):
self, self,
dataset, dataset,
evals_result=dict(), evals_result=dict(),
verbose=True,
save_path=None, save_path=None,
): ):

View File

@@ -23,6 +23,7 @@ import torch
import torch.nn as nn import torch.nn as nn
import torch.optim as optim import torch.optim as optim
from .pytorch_utils import count_parameters
from ...model.base import Model from ...model.base import Model
from ...data.dataset import DatasetH from ...data.dataset import DatasetH
from ...data.dataset.handler import DataHandlerLP from ...data.dataset.handler import DataHandlerLP
@@ -76,7 +77,7 @@ class GRU(Model):
self.early_stop = early_stop self.early_stop = early_stop
self.optimizer = optimizer.lower() self.optimizer = optimizer.lower()
self.loss = loss self.loss = loss
self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() and GPU >= 0 else "cpu")
self.use_gpu = torch.cuda.is_available() self.use_gpu = torch.cuda.is_available()
self.seed = seed self.seed = seed
@@ -123,6 +124,9 @@ class GRU(Model):
num_layers=self.num_layers, num_layers=self.num_layers,
dropout=self.dropout, dropout=self.dropout,
) )
self.logger.info("model:\n{:}".format(self.gru_model))
self.logger.info("model size: {:.4f} MB".format(count_parameters(self.gru_model)))
if optimizer.lower() == "adam": if optimizer.lower() == "adam":
self.train_optimizer = optim.Adam(self.gru_model.parameters(), lr=self.lr) self.train_optimizer = optim.Adam(self.gru_model.parameters(), lr=self.lr)
elif optimizer.lower() == "gd": elif optimizer.lower() == "gd":
@@ -214,7 +218,6 @@ class GRU(Model):
self, self,
dataset: DatasetH, dataset: DatasetH,
evals_result=dict(), evals_result=dict(),
verbose=True,
save_path=None, save_path=None,
): ):

View File

@@ -24,6 +24,7 @@ import torch.nn as nn
import torch.optim as optim import torch.optim as optim
from torch.utils.data import DataLoader from torch.utils.data import DataLoader
from .pytorch_utils import count_parameters
from ...model.base import Model from ...model.base import Model
from ...data.dataset import DatasetH, TSDatasetH from ...data.dataset import DatasetH, TSDatasetH
from ...data.dataset.handler import DataHandlerLP from ...data.dataset.handler import DataHandlerLP
@@ -78,7 +79,7 @@ class GRU(Model):
self.early_stop = early_stop self.early_stop = early_stop
self.optimizer = optimizer.lower() self.optimizer = optimizer.lower()
self.loss = loss self.loss = loss
self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() and GPU >= 0 else "cpu")
self.n_jobs = n_jobs self.n_jobs = n_jobs
self.use_gpu = torch.cuda.is_available() self.use_gpu = torch.cuda.is_available()
self.seed = seed self.seed = seed
@@ -127,7 +128,10 @@ class GRU(Model):
hidden_size=self.hidden_size, hidden_size=self.hidden_size,
num_layers=self.num_layers, num_layers=self.num_layers,
dropout=self.dropout, dropout=self.dropout,
).to(self.device) )
self.logger.info("model:\n{:}".format(self.gru_model))
self.logger.info("model size: {:.4f} MB".format(count_parameters(self.gru_model)))
if optimizer.lower() == "adam": if optimizer.lower() == "adam":
self.train_optimizer = optim.Adam(self.GRU_model.parameters(), lr=self.lr) self.train_optimizer = optim.Adam(self.GRU_model.parameters(), lr=self.lr)
elif optimizer.lower() == "gd": elif optimizer.lower() == "gd":
@@ -201,7 +205,6 @@ class GRU(Model):
self, self,
dataset, dataset,
evals_result=dict(), evals_result=dict(),
verbose=True,
save_path=None, save_path=None,
): ):
dl_train = dataset.prepare("train", col_set=["feature", "label"], data_key=DataHandlerLP.DK_L) dl_train = dataset.prepare("train", col_set=["feature", "label"], data_key=DataHandlerLP.DK_L)

View File

@@ -76,7 +76,7 @@ class LSTM(Model):
self.early_stop = early_stop self.early_stop = early_stop
self.optimizer = optimizer.lower() self.optimizer = optimizer.lower()
self.loss = loss self.loss = loss
self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() and GPU >= 0 else "cpu")
self.use_gpu = torch.cuda.is_available() self.use_gpu = torch.cuda.is_available()
self.seed = seed self.seed = seed
@@ -214,7 +214,6 @@ class LSTM(Model):
self, self,
dataset: DatasetH, dataset: DatasetH,
evals_result=dict(), evals_result=dict(),
verbose=True,
save_path=None, save_path=None,
): ):

View File

@@ -78,7 +78,7 @@ class LSTM(Model):
self.early_stop = early_stop self.early_stop = early_stop
self.optimizer = optimizer.lower() self.optimizer = optimizer.lower()
self.loss = loss self.loss = loss
self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() and GPU >= 0 else "cpu")
self.n_jobs = n_jobs self.n_jobs = n_jobs
self.use_gpu = torch.cuda.is_available() self.use_gpu = torch.cuda.is_available()
self.seed = seed self.seed = seed
@@ -201,7 +201,6 @@ class LSTM(Model):
self, self,
dataset, dataset,
evals_result=dict(), evals_result=dict(),
verbose=True,
save_path=None, save_path=None,
): ):
dl_train = dataset.prepare("train", col_set=["feature", "label"], data_key=DataHandlerLP.DK_L) dl_train = dataset.prepare("train", col_set=["feature", "label"], data_key=DataHandlerLP.DK_L)

View File

@@ -15,6 +15,7 @@ import torch
import torch.nn as nn import torch.nn as nn
import torch.optim as optim import torch.optim as optim
from .pytorch_utils import count_parameters
from ...model.base import Model from ...model.base import Model
from ...data.dataset import DatasetH from ...data.dataset import DatasetH
from ...data.dataset.handler import DataHandlerLP from ...data.dataset.handler import DataHandlerLP
@@ -42,8 +43,8 @@ class DNNModelPytorch(Model):
learning rate decay steps learning rate decay steps
optimizer : str optimizer : str
optimizer name optimizer name
GPU : str GPU : int
the GPU ID(s) used for training the GPU ID used for training
""" """
def __init__( def __init__(
@@ -80,7 +81,7 @@ class DNNModelPytorch(Model):
self.lr_decay_steps = lr_decay_steps self.lr_decay_steps = lr_decay_steps
self.optimizer = optimizer.lower() self.optimizer = optimizer.lower()
self.loss_type = loss self.loss_type = loss
self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() and GPU >= 0 else "cpu")
self.use_GPU = torch.cuda.is_available() self.use_GPU = torch.cuda.is_available()
self.seed = seed self.seed = seed
self.weight_decay = weight_decay self.weight_decay = weight_decay
@@ -129,6 +130,9 @@ class DNNModelPytorch(Model):
self._scorer = mean_squared_error if loss == "mse" else roc_auc_score self._scorer = mean_squared_error if loss == "mse" else roc_auc_score
self.dnn_model = Net(input_dim, output_dim, layers, loss=self.loss_type) self.dnn_model = Net(input_dim, output_dim, layers, loss=self.loss_type)
self.logger.info("model:\n{:}".format(self.dnn_model))
self.logger.info("model size: {:.4f} MB".format(count_parameters(self.dnn_model)))
if optimizer.lower() == "adam": if optimizer.lower() == "adam":
self.train_optimizer = optim.Adam(self.dnn_model.parameters(), lr=self.lr, weight_decay=self.weight_decay) self.train_optimizer = optim.Adam(self.dnn_model.parameters(), lr=self.lr, weight_decay=self.weight_decay)
elif optimizer.lower() == "gd": elif optimizer.lower() == "gd":

View File

@@ -23,6 +23,7 @@ import torch.nn as nn
import torch.nn.init as init import torch.nn.init as init
import torch.optim as optim import torch.optim as optim
from .pytorch_utils import count_parameters
from ...model.base import Model from ...model.base import Model
from ...data.dataset import DatasetH from ...data.dataset import DatasetH
from ...data.dataset.handler import DataHandlerLP from ...data.dataset.handler import DataHandlerLP
@@ -196,8 +197,8 @@ class SFM(Model):
learning rate learning rate
optimizer : str optimizer : str
optimizer name optimizer name
GPU : str GPU : int
the GPU ID(s) used for training the GPU ID used for training
""" """
def __init__( def __init__(
@@ -216,7 +217,7 @@ class SFM(Model):
eval_steps=5, eval_steps=5,
loss="mse", loss="mse",
optimizer="gd", optimizer="gd",
GPU="0", GPU=0,
seed=None, seed=None,
**kwargs **kwargs
): ):
@@ -239,7 +240,7 @@ class SFM(Model):
self.eval_steps = eval_steps self.eval_steps = eval_steps
self.optimizer = optimizer.lower() self.optimizer = optimizer.lower()
self.loss = loss self.loss = loss
self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu") self.device = torch.device("cuda:%d" % (GPU) if torch.cuda.is_available() and GPU >= 0 else "cpu")
self.use_gpu = torch.cuda.is_available() self.use_gpu = torch.cuda.is_available()
self.seed = seed self.seed = seed
@@ -295,6 +296,9 @@ class SFM(Model):
dropout_U=self.dropout_U, dropout_U=self.dropout_U,
device=self.device, device=self.device,
) )
self.logger.info("model:\n{:}".format(self.sfm_model))
self.logger.info("model size: {:.4f} MB".format(count_parameters(self.sfm_model)))
if optimizer.lower() == "adam": if optimizer.lower() == "adam":
self.train_optimizer = optim.Adam(self.sfm_model.parameters(), lr=self.lr) self.train_optimizer = optim.Adam(self.sfm_model.parameters(), lr=self.lr)
elif optimizer.lower() == "gd": elif optimizer.lower() == "gd":
@@ -365,7 +369,6 @@ class SFM(Model):
self, self,
dataset: DatasetH, dataset: DatasetH,
evals_result=dict(), evals_result=dict(),
verbose=True,
save_path=None, save_path=None,
): ):

View File

@@ -23,6 +23,7 @@ import torch.optim as optim
import torch.nn.functional as F import torch.nn.functional as F
from torch.autograd import Function from torch.autograd import Function
from .pytorch_utils import count_parameters
from ...model.base import Model from ...model.base import Model
from ...data.dataset import DatasetH from ...data.dataset import DatasetH
from ...data.dataset.handler import DataHandlerLP from ...data.dataset.handler import DataHandlerLP
@@ -49,7 +50,7 @@ class TabnetModel(Model):
loss="mse", loss="mse",
metric="", metric="",
early_stop=20, early_stop=20,
GPU="1", GPU=0,
pretrain_loss="custom", pretrain_loss="custom",
ps=0.3, ps=0.3,
lr=0.01, lr=0.01,
@@ -75,7 +76,7 @@ class TabnetModel(Model):
self.n_epochs = n_epochs self.n_epochs = n_epochs
self.logger = get_module_logger("TabNet") self.logger = get_module_logger("TabNet")
self.pretrain_n_epochs = pretrain_n_epochs self.pretrain_n_epochs = pretrain_n_epochs
self.device = "cuda:%s" % (GPU) if torch.cuda.is_available() else "cpu" self.device = "cuda:%s" % (GPU) if torch.cuda.is_available() and GPU >= 0 else "cpu"
self.loss = loss self.loss = loss
self.metric = metric self.metric = metric
self.early_stop = early_stop self.early_stop = early_stop
@@ -98,6 +99,8 @@ class TabnetModel(Model):
self.tabnet_decoder = TabNet_Decoder(self.out_dim, self.d_feat, n_shared, n_ind, vbs, n_steps, self.device).to( self.tabnet_decoder = TabNet_Decoder(self.out_dim, self.d_feat, n_shared, n_ind, vbs, n_steps, self.device).to(
self.device self.device
) )
self.logger.info("model:\n{:}\n{:}".format(self.tabnet_model, self.tabnet_decoder))
self.logger.info("model size: {:.4f} MB".format(count_parameters([self.tabnet_model, self.tabnet_decoder])))
if optimizer.lower() == "adam": if optimizer.lower() == "adam":
self.pretrain_optimizer = optim.Adam( self.pretrain_optimizer = optim.Adam(
@@ -159,7 +162,6 @@ class TabnetModel(Model):
self, self,
dataset: DatasetH, dataset: DatasetH,
evals_result=dict(), evals_result=dict(),
verbose=True,
save_path=None, save_path=None,
): ):
if self.pretrain: if self.pretrain:

View File

@@ -0,0 +1,37 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
import torch.nn as nn
def count_parameters(models_or_parameters, unit="m"):
"""
This function is to obtain the storage size unit of a (or multiple) models.
Parameters
----------
models_or_parameters : PyTorch model(s) or a list of parameters.
unit : the storage size unit.
Returns
-------
The number of parameters of the given model(s) or parameters.
"""
if isinstance(models_or_parameters, nn.Module):
counts = sum(v.numel() for v in models_or_parameters.parameters())
elif isinstance(models_or_parameters, nn.Parameter):
counts = models_or_parameters.numel()
elif isinstance(models_or_parameters, (list, tuple)):
return sum(count_parameters(x, unit) for x in models_or_parameters)
else:
counts = sum(v.numel() for v in models_or_parameters)
unit = unit.lower()
if unit == "kb" or unit == "k":
counts /= 2 ** 10
elif unit == "mb" or unit == "m":
counts /= 2 ** 20
elif unit == "gb" or unit == "g":
counts /= 2 ** 30
elif unit is not None:
raise ValueError("Unknow unit: {:}".format(unit))
return counts

View File

@@ -148,7 +148,7 @@ class Operator:
for user_id, user in um.users.items(): for user_id, user in um.users.items():
dates, trade_exchange = prepare(um, trade_date, user_id, exchange_config) dates, trade_exchange = prepare(um, trade_date, user_id, exchange_config)
executor = SimulatorExecutor(trade_exchange=trade_exchange) executor = SimulatorExecutor(trade_exchange=trade_exchange)
if not str(dates[0].date()) == str(pred_date.date()): if str(dates[0].date()) != str(pred_date.date()):
raise ValueError( raise ValueError(
"The account data is not newest! last trading date {}, today {}".format( "The account data is not newest! last trading date {}, today {}".format(
dates[0].date(), trade_date.date() dates[0].date(), trade_date.date()

View File

@@ -3,8 +3,7 @@
import logging import logging
import logging.handlers from typing import Optional, Text, Dict, Any
import os
import re import re
from logging import config as logging_config from logging import config as logging_config
from time import time from time import time
@@ -13,16 +12,13 @@ from contextlib import contextmanager
from .config import C from .config import C
def get_module_logger(module_name, level=None): def get_module_logger(module_name, level: Optional[int] = None):
""" """
Get a logger for a specific module. Get a logger for a specific module.
:param module_name: str :param module_name: str
Logic module name. Logic module name.
:param level: int :param level: int
:param sh_level: int
Stream handler log level.
:param log_format: str
:return: Logger :return: Logger
Logger object. Logger object.
""" """
@@ -103,7 +99,7 @@ class TimeInspector:
cls.log_cost_time(info=f"{name} Done") cls.log_cost_time(info=f"{name} Done")
def set_log_with_config(log_config: dict): def set_log_with_config(log_config: Dict[Text, Any]):
"""set log with config """set log with config
:param log_config: :param log_config:

View File

@@ -2,6 +2,7 @@
# Licensed under the MIT License. # Licensed under the MIT License.
from contextlib import contextmanager from contextlib import contextmanager
from typing import Text, Optional
from .expm import MLflowExpManager from .expm import MLflowExpManager
from .exp import Experiment from .exp import Experiment
from .recorder import Recorder from .recorder import Recorder
@@ -20,7 +21,9 @@ class QlibRecorder:
return "{name}(manager={manager})".format(name=self.__class__.__name__, manager=self.exp_manager) return "{name}(manager={manager})".format(name=self.__class__.__name__, manager=self.exp_manager)
@contextmanager @contextmanager
def start(self, experiment_name=None, recorder_name=None, uri=None): def start(
self, experiment_name: Optional[Text] = None, recorder_name: Optional[Text] = None, uri: Optional[Text] = None
):
""" """
Method to start an experiment. This method can only be called within a Python's `with` statement. Here is the example code: Method to start an experiment. This method can only be called within a Python's `with` statement. Here is the example code:
@@ -282,6 +285,12 @@ class QlibRecorder:
""" """
return self.exp_manager.uri return self.exp_manager.uri
def set_uri(self, uri: Optional[Text]):
"""
Method to reset the current uri of current experiment manager.
"""
self.exp_manager.set_uri(uri)
def get_recorder(self, recorder_id=None, recorder_name=None, experiment_name=None): def get_recorder(self, recorder_id=None, recorder_name=None, experiment_name=None):
""" """
Method for retrieving a recorder. Method for retrieving a recorder.

View File

@@ -16,7 +16,7 @@ def get_path_list(path):
if isinstance(path, str): if isinstance(path, str):
return [path] return [path]
else: else:
return [p for p in path] return list(path)
def sys_config(config, config_path): def sys_config(config, config_path):

View File

@@ -23,7 +23,7 @@ class Experiment:
self.active_recorder = None # only one recorder can running each time self.active_recorder = None # only one recorder can running each time
def __repr__(self): def __repr__(self):
return "{name}(info={info})".format(name=self.__class__.__name__, info=self.info) return "{name}(id={id}, info={info})".format(name=self.__class__.__name__, id=self.id, info=self.info)
def __str__(self): def __str__(self):
return str(self.info) return str(self.info)
@@ -175,6 +175,9 @@ class MLflowExperiment(Experiment):
self._default_rec_name = "mlflow_recorder" self._default_rec_name = "mlflow_recorder"
self._client = mlflow.tracking.MlflowClient(tracking_uri=self._uri) self._client = mlflow.tracking.MlflowClient(tracking_uri=self._uri)
def __repr__(self):
return "{name}(id={id}, info={info})".format(name=self.__class__.__name__, id=self.id, info=self.info)
def start(self, recorder_name=None): def start(self, recorder_name=None):
logger.info(f"Experiment {self.id} starts running ...") logger.info(f"Experiment {self.id} starts running ...")
# set up recorder # set up recorder

View File

@@ -10,6 +10,7 @@ from contextlib import contextmanager
from typing import Optional, Text from typing import Optional, Text
from .exp import MLflowExperiment, Experiment from .exp import MLflowExperiment, Experiment
from ..config import C
from .recorder import Recorder from .recorder import Recorder
from ..log import get_module_logger from ..log import get_module_logger
@@ -23,15 +24,12 @@ class ExpManager:
""" """
def __init__(self, uri: Text, default_exp_name: Optional[Text]): def __init__(self, uri: Text, default_exp_name: Optional[Text]):
self._default_uri = uri self._current_uri = uri
self._current_uri = None
self.default_exp_name = default_exp_name self.default_exp_name = default_exp_name
self.active_experiment = None # only one experiment can active each time self.active_experiment = None # only one experiment can active each time
def __repr__(self): def __repr__(self):
return "{name}(default_uri={duri}, current_uri={curi})".format( return "{name}(current_uri={curi})".format(name=self.__class__.__name__, curi=self._current_uri)
name=self.__class__.__name__, duri=self._default_uri, curi=self._current_uri
)
def start_exp( def start_exp(
self, self,
@@ -217,6 +215,15 @@ class ExpManager:
""" """
raise NotImplementedError(f"Please implement the `delete_exp` method.") raise NotImplementedError(f"Please implement the `delete_exp` method.")
@property
def default_uri(self):
"""
Get the default tracking URI from qlib.config.C
"""
if "kwargs" not in C.exp_manager or "uri" not in C.exp_manager["kwargs"]:
raise ValueError("The default URI is not set in qlib.config.C")
return C.exp_manager["kwargs"]["uri"]
@property @property
def uri(self): def uri(self):
""" """
@@ -226,7 +233,7 @@ class ExpManager:
------- -------
The tracking URI string. The tracking URI string.
""" """
return self._current_uri or self._default_uri return self._current_uri or self.default_uri
def set_uri(self, uri: Optional[Text] = None): def set_uri(self, uri: Optional[Text] = None):
""" """
@@ -239,7 +246,7 @@ class ExpManager:
""" """
if uri is None: if uri is None:
logger.info("No tracking URI is provided. Use the default tracking URI.") logger.info("No tracking URI is provided. Use the default tracking URI.")
self._current_uri = self._default_uri self._current_uri = self.default_uri
else: else:
# Temporarily re-set the current uri as the uri argument. # Temporarily re-set the current uri as the uri argument.
self._current_uri = uri self._current_uri = uri

View File

@@ -201,7 +201,7 @@ class MLflowRecorder(Recorder):
def __init__(self, experiment_id, uri, name=None, mlflow_run=None): def __init__(self, experiment_id, uri, name=None, mlflow_run=None):
super(MLflowRecorder, self).__init__(experiment_id, name) super(MLflowRecorder, self).__init__(experiment_id, name)
self._uri = uri self._uri = uri
self.artifact_uri = None self._artifact_uri = None
self.client = mlflow.tracking.MlflowClient(tracking_uri=self._uri) self.client = mlflow.tracking.MlflowClient(tracking_uri=self._uri)
# construct from mlflow run # construct from mlflow run
if mlflow_run is not None: if mlflow_run is not None:
@@ -220,14 +220,51 @@ class MLflowRecorder(Recorder):
else None else None
) )
def __repr__(self):
name = self.__class__.__name__
space_length = len(name) + 1
return "{name}(info={info},\n{space}uri={uri},\n{space}artifact_uri={artifact_uri},\n{space}client={client})".format(
name=name,
space=" " * space_length,
info=self.info,
uri=self.uri,
artifact_uri=self.artifact_uri,
client=self.client,
)
@property
def uri(self):
return self._uri
@property
def artifact_uri(self):
return self._artifact_uri
def get_local_dir(self):
"""
This function will return the directory path of this recorder.
"""
if self.artifact_uri is not None:
local_dir_path = Path(self.artifact_uri.lstrip("file:")) / ".."
local_dir_path = str(local_dir_path.resolve())
if os.path.isdir(local_dir_path):
return local_dir_path
else:
raise RuntimeError("This recorder is not saved in the local file system.")
else:
raise Exception(
"Please make sure the recorder has been created and started properly before getting artifact uri."
)
def start_run(self): def start_run(self):
# set the tracking uri # set the tracking uri
mlflow.set_tracking_uri(self._uri) mlflow.set_tracking_uri(self.uri)
# start the run # start the run
run = mlflow.start_run(self.id, self.experiment_id, self.name) run = mlflow.start_run(self.id, self.experiment_id, self.name)
# save the run id and artifact_uri # save the run id and artifact_uri
self.id = run.info.run_id self.id = run.info.run_id
self.artifact_uri = run.info.artifact_uri self._artifact_uri = run.info.artifact_uri
self.start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.status = Recorder.STATUS_R self.status = Recorder.STATUS_R
logger.info(f"Recorder {self.id} starts running under Experiment {self.experiment_id} ...") logger.info(f"Recorder {self.id} starts running under Experiment {self.experiment_id} ...")
@@ -247,7 +284,7 @@ class MLflowRecorder(Recorder):
self.status = status self.status = status
def save_objects(self, local_path=None, artifact_path=None, **kwargs): def save_objects(self, local_path=None, artifact_path=None, **kwargs):
assert self._uri is not None, "Please start the experiment and recorder first before using recorder directly." assert self.uri is not None, "Please start the experiment and recorder first before using recorder directly."
if local_path is not None: if local_path is not None:
self.client.log_artifacts(self.id, local_path, artifact_path) self.client.log_artifacts(self.id, local_path, artifact_path)
else: else:
@@ -259,7 +296,7 @@ class MLflowRecorder(Recorder):
shutil.rmtree(temp_dir) shutil.rmtree(temp_dir)
def load_object(self, name): def load_object(self, name):
assert self._uri is not None, "Please start the experiment and recorder first before using recorder directly." assert self.uri is not None, "Please start the experiment and recorder first before using recorder directly."
path = self.client.download_artifacts(self.id, name) path = self.client.download_artifacts(self.id, name)
with Path(path).open("rb") as f: with Path(path).open("rb") as f:
return pickle.load(f) return pickle.load(f)
@@ -289,7 +326,7 @@ class MLflowRecorder(Recorder):
) )
def list_artifacts(self, artifact_path=None): def list_artifacts(self, artifact_path=None):
assert self._uri is not None, "Please start the experiment and recorder first before using recorder directly." assert self.uri is not None, "Please start the experiment and recorder first before using recorder directly."
artifacts = self.client.list_artifacts(self.id, artifact_path) artifacts = self.client.list_artifacts(self.id, artifact_path)
return [art.path for art in artifacts] return [art.path for art in artifacts]

View File

@@ -123,6 +123,8 @@ def train():
recorder = R.get_recorder() recorder = R.get_recorder()
# To test __repr__ # To test __repr__
print(recorder) print(recorder)
# To test get_local_dir
print(recorder.get_local_dir())
rid = recorder.id rid = recorder.id
sr = SignalRecord(model, dataset, recorder) sr = SignalRecord(model, dataset, recorder)
sr.generate() sr.generate()