From 056951605b6395c3765624a8ea82a4993e20c023 Mon Sep 17 00:00:00 2001 From: Jactus Date: Thu, 26 Nov 2020 15:50:42 +0800 Subject: [PATCH] Format --- docs/component/data.rst | 1 + examples/workflow_by_code_gats.py | 1 - examples/workflow_by_code_hats.py | 1 - examples/workflow_by_code_sfm.py | 2 +- qlib/contrib/model/catboost_model.py | 20 ++++---- qlib/contrib/model/pytorch_gats.py | 2 +- qlib/contrib/model/pytorch_hats.py | 6 ++- qlib/contrib/model/pytorch_sfm.py | 73 +++++++++++++++------------- qlib/contrib/model/xgboost.py | 30 ++++++------ 9 files changed, 72 insertions(+), 64 deletions(-) diff --git a/docs/component/data.rst b/docs/component/data.rst index efcd81ffd..fda3e0db0 100644 --- a/docs/component/data.rst +++ b/docs/component/data.rst @@ -292,6 +292,7 @@ The ``Processor`` module in ``Qlib`` is designed to be learnable and it is respo - ``Fillna``: `processor` that handles N/A values, which will fill the N/A value by 0 or other given number. - ``MinMaxNorm``: `processor` that applies min-max normalization. - ``ZscoreNorm``: `processor` that applies z-score normalization. +- ``RobustZScoreNorm``: `processor` that applies robust z-score normalization. - ``CSZScoreNorm``: `processor` that applies cross sectional z-score normalization. - ``CSRankNorm``: `processor` that applies cross sectional rank normalization. diff --git a/examples/workflow_by_code_gats.py b/examples/workflow_by_code_gats.py index b5bad31ec..ac413932b 100644 --- a/examples/workflow_by_code_gats.py +++ b/examples/workflow_by_code_gats.py @@ -17,7 +17,6 @@ from qlib.utils import exists_qlib_data from qlib.utils import init_instance_by_config - if __name__ == "__main__": # use default data diff --git a/examples/workflow_by_code_hats.py b/examples/workflow_by_code_hats.py index 67b917f17..15e5ae130 100644 --- a/examples/workflow_by_code_hats.py +++ b/examples/workflow_by_code_hats.py @@ -90,7 +90,6 @@ if __name__ == "__main__": # "record": ['SignalRecord', 'SigAnaRecord', 'PortAnaRecord'], } - model = init_instance_by_config(task["model"]) dataset = init_instance_by_config(task["dataset"]) model.fit(dataset, save_path="benchmarks/HATS/model_hat.pkl") diff --git a/examples/workflow_by_code_sfm.py b/examples/workflow_by_code_sfm.py index e9a72883a..5bd91ded8 100644 --- a/examples/workflow_by_code_sfm.py +++ b/examples/workflow_by_code_sfm.py @@ -78,7 +78,7 @@ if __name__ == "__main__": "dropout_U": 0.5, "n_epochs": 15, "lr": 1e-3, - "metric": "", + "metric": "", "batch_size": 1600, "early_stop": 20, "eval_steps": 5, diff --git a/qlib/contrib/model/catboost_model.py b/qlib/contrib/model/catboost_model.py index eb97fc75b..bba006c35 100644 --- a/qlib/contrib/model/catboost_model.py +++ b/qlib/contrib/model/catboost_model.py @@ -34,14 +34,14 @@ class CatBoostModel(Model): def fit( self, dataset: DatasetH, - num_boost_round = 1000, - early_stopping_rounds = 50, - verbose_eval = 20, - evals_result = dict(), + num_boost_round=1000, + early_stopping_rounds=50, + verbose_eval=20, + evals_result=dict(), **kwargs ): df_train, df_valid = dataset.prepare( - ["train", "valid"], col_set = ["feature", "label"], data_key = DataHandlerLP.DK_L + ["train", "valid"], col_set=["feature", "label"], data_key=DataHandlerLP.DK_L ) x_train, y_train = df_train["feature"], df_train["label"] x_valid, y_valid = df_valid["feature"], df_valid["label"] @@ -52,8 +52,8 @@ class CatBoostModel(Model): else: raise ValueError("CatBoost doesn't support multi-label training") - train_pool = Pool(data = x_train, label = y_train_1d) - valid_pool = Pool(data = x_valid, label = y_valid_1d) + train_pool = Pool(data=x_train, label=y_train_1d) + valid_pool = Pool(data=x_valid, label=y_valid_1d) # Initialize the catboost model self._params["iterations"] = num_boost_round @@ -63,7 +63,7 @@ class CatBoostModel(Model): self.model = CatBoost(self._params, **kwargs) # train the model - self.model.fit(train_pool, eval_set = valid_pool, use_best_model = True, **kwargs) + self.model.fit(train_pool, eval_set=valid_pool, use_best_model=True, **kwargs) evals_result = self.model.get_evals_result() evals_result["train"] = list(evals_result["learn"].values())[0] @@ -72,8 +72,8 @@ class CatBoostModel(Model): def predict(self, dataset): if self.model is None: raise ValueError("model is not fitted yet!") - x_test = dataset.prepare("test", col_set = "feature") - return pd.Series(self.model.predict(x_test.values), index = x_test.index) + x_test = dataset.prepare("test", col_set="feature") + return pd.Series(self.model.predict(x_test.values), index=x_test.index) if __name__ == "__main__": diff --git a/qlib/contrib/model/pytorch_gats.py b/qlib/contrib/model/pytorch_gats.py index 7cdfb571a..72cd5c36f 100755 --- a/qlib/contrib/model/pytorch_gats.py +++ b/qlib/contrib/model/pytorch_gats.py @@ -117,7 +117,7 @@ class GAT(Model): seed, ) ) - + self.GAT_model = GATModel( d_feat=self.d_feat, hidden_size=self.hidden_size, diff --git a/qlib/contrib/model/pytorch_hats.py b/qlib/contrib/model/pytorch_hats.py index cdfae0284..05f89ced0 100644 --- a/qlib/contrib/model/pytorch_hats.py +++ b/qlib/contrib/model/pytorch_hats.py @@ -261,10 +261,12 @@ class HATS(Model): self.logger.info("Loading pretrained model...") if self.base_model == "LSTM": from ...contrib.model.pytorch_lstm import LSTMModel + pretrained_model = LSTMModel() pretrained_model.load_state_dict(torch.load("benchmarks/LSTM/model_lstm_csi300.pkl")) elif self.base_model == "GRU": from ...contrib.model.pytorch_gru import GRUModel + pretrained_model = GRUModel() pretrained_model.load_state_dict(torch.load("benchmarks/GRU/model_gru_csi300.pkl")) model_dict = self.HATS_model.state_dict() @@ -461,7 +463,9 @@ class GraphAttention(nn.Module): h = self.fcs[k](features) nbr_h = torch.cat(tuple([h[row] for row in rows]), dim=0) - self_h = torch.cat(tuple([h[mappings[nodes[i]]].repeat(len(row), 1) for (i, row) in enumerate(rows)]), dim=0) + self_h = torch.cat( + tuple([h[mappings[nodes[i]]].repeat(len(row), 1) for (i, row) in enumerate(rows)]), dim=0 + ) cat_h = torch.cat((self_h, nbr_h), dim=1) e = self.leakyrelu(self.a[k](cat_h)) diff --git a/qlib/contrib/model/pytorch_sfm.py b/qlib/contrib/model/pytorch_sfm.py index 4ec61430e..7fbbd7c6e 100644 --- a/qlib/contrib/model/pytorch_sfm.py +++ b/qlib/contrib/model/pytorch_sfm.py @@ -31,6 +31,7 @@ from ...model.base import Model from ...data.dataset import DatasetH from ...data.dataset.handler import DataHandlerLP + class SFM_Model(nn.Module): def __init__(self, d_feat=6, output_dim=1, freq_dim=10, hidden_size=64, dropout_W=0.0, dropout_U=0.0, device="cpu"): super().__init__() @@ -75,13 +76,13 @@ class SFM_Model(nn.Module): self.states = [] def forward(self, input): - input = input.reshape(len(input), self.input_dim, -1) # [N, F, T] - input = input.permute(0, 2, 1) # [N, T, F] + input = input.reshape(len(input), self.input_dim, -1) # [N, F, T] + input = input.permute(0, 2, 1) # [N, T, F] time_step = input.shape[1] - + for ts in range(time_step): - x = input[:, ts,:] - if len(self.states)==0: #hasn't initialized yet + x = input[:, ts, :] + if len(self.states) == 0: # hasn't initialized yet self.init_states(x) self.get_constants(x) p_tm1 = self.states[0] @@ -98,64 +99,65 @@ class SFM_Model(nn.Module): x_fre = torch.matmul(x * B_W[0], self.W_fre) + self.b_fre x_c = torch.matmul(x * B_W[0], self.W_c) + self.b_c x_o = torch.matmul(x * B_W[0], self.W_o) + self.b_o - - i = self.inner_activation(x_i + torch.matmul(h_tm1 * B_U[0], self.U_i)) # not sure whether I am doing in the right unsquuze - + + i = self.inner_activation( + x_i + torch.matmul(h_tm1 * B_U[0], self.U_i) + ) # not sure whether I am doing in the right unsquuze ste = self.inner_activation(x_ste + torch.matmul(h_tm1 * B_U[0], self.U_ste)) fre = self.inner_activation(x_fre + torch.matmul(h_tm1 * B_U[0], self.U_fre)) ste = torch.reshape(ste, (-1, self.hidden_dim, 1)) fre = torch.reshape(fre, (-1, 1, self.freq_dim)) - + f = ste * fre - + c = i * self.activation(x_c + torch.matmul(h_tm1 * B_U[0], self.U_c)) time = time_tm1 + 1 omega = torch.tensor(2 * np.pi) * time * frequency - re = torch.cos(omega) + re = torch.cos(omega) im = torch.sin(omega) - + c = torch.reshape(c, (-1, self.hidden_dim, 1)) S_re = f * S_re_tm1 + c * re S_im = f * S_im_tm1 + c * im - + A = torch.square(S_re) + torch.square(S_im) A = torch.reshape(A, (-1, self.freq_dim)).float() A_a = torch.matmul(A * B_U[0], self.U_a) A_a = torch.reshape(A_a, (-1, self.hidden_dim)) a = self.activation(A_a + self.b_a) - + o = self.inner_activation(x_o + torch.matmul(h_tm1 * B_U[0], self.U_o)) h = o * a p = torch.matmul(h, self.W_p) + self.b_p self.states = [p, h, S_re, S_im, time, None, None, None] - self.states = [] + self.states = [] return self.fc_out(p).squeeze() def init_states(self, x): reducer_f = torch.zeros((self.hidden_dim, self.freq_dim)).to(self.device) reducer_p = torch.zeros((self.hidden_dim, self.output_dim)).to(self.device) - + init_state_h = torch.zeros(self.hidden_dim).to(self.device) init_state_p = torch.matmul(init_state_h, reducer_p) - + init_state = torch.zeros_like(init_state_h).to(self.device) init_freq = torch.matmul(init_state_h, reducer_f) init_state = torch.reshape(init_state, (-1, self.hidden_dim, 1)) init_freq = torch.reshape(init_freq, (-1, 1, self.freq_dim)) - + init_state_S_re = init_state * init_freq init_state_S_im = init_state * init_freq - + init_state_time = torch.tensor(0).to(self.device) self.states = [init_state_p, init_state_h, init_state_S_re, init_state_S_im, init_state_time, None, None, None] @@ -201,7 +203,7 @@ class SFM(Model): dropout_U=0.0, n_epochs=200, lr=0.001, - metric = "", + metric="", batch_size=2000, early_stop=20, eval_steps=5, @@ -234,7 +236,7 @@ class SFM(Model): self.lr_decay_steps = lr_decay_steps self.optimizer = optimizer.lower() self.loss = loss - self.device = "cuda:%d"%(GPU) if torch.cuda.is_available() else "cpu" + self.device = "cuda:%d" % (GPU) if torch.cuda.is_available() else "cpu" self.use_gpu = torch.cuda.is_available() self.seed = seed @@ -243,7 +245,7 @@ class SFM(Model): "\nd_feat : {}" "\nhidden_size : {}" "\noutput_size : {}" - "\nfrequency_dimension : {}" + "\nfrequency_dimension : {}" "\ndropout_W: {}" "\ndropout_U: {}" "\nn_epochs : {}" @@ -286,14 +288,14 @@ class SFM(Model): self._scorer = mean_squared_error if loss == "mse" else roc_auc_score self.sfm_model = SFM_Model( - d_feat=self.d_feat, + d_feat=self.d_feat, output_dim=self.output_dim, - hidden_size=self.hidden_size, - freq_dim=self.freq_dim, - dropout_W=self.dropout_W, - dropout_U=self.dropout_U, - device=self.device - ) + hidden_size=self.hidden_size, + freq_dim=self.freq_dim, + dropout_W=self.dropout_W, + dropout_U=self.dropout_U, + device=self.device, + ) if optimizer.lower() == "adam": self.train_optimizer = optim.Adam(self.sfm_model.parameters(), lr=self.lr) elif optimizer.lower() == "gd": @@ -414,7 +416,7 @@ class SFM(Model): def mse(self, pred, label): loss = (pred - label) ** 2 return torch.mean(loss) - + def loss_fn(self, pred, label): mask = ~torch.isnan(label) @@ -422,7 +424,7 @@ class SFM(Model): return self.mse(pred[mask], label[mask]) raise ValueError("unknown loss `%s`" % self.loss) - + def metric_fn(self, pred, label): mask = torch.isfinite(label) @@ -436,6 +438,7 @@ class SFM(Model): def cal_ic(self, pred, label): return torch.mean(pred * label) + def predict(self, dataset): if not self._fitted: raise ValueError("model is not fitted yet!") @@ -447,7 +450,7 @@ class SFM(Model): sample_num = x_values.shape[0] preds = [] - for begin in range(sample_num)[::self.batch_size]: + for begin in range(sample_num)[:: self.batch_size]: if sample_num - begin < self.batch_size: end = sample_num else: @@ -457,16 +460,18 @@ class SFM(Model): if self.device != "cpu": x_batch = x_batch.to(self.device) - + with torch.no_grad(): pred = self.sfm_model(x_batch).detach().cpu().numpy() preds.append(pred) - + return pd.Series(np.concatenate(preds), index=index) + class AverageMeter(object): """Computes and stores the average and current value""" + def __init__(self): self.reset() diff --git a/qlib/contrib/model/xgboost.py b/qlib/contrib/model/xgboost.py index 203e71b9a..039fd2c80 100755 --- a/qlib/contrib/model/xgboost.py +++ b/qlib/contrib/model/xgboost.py @@ -30,15 +30,15 @@ class XGBModel(Model): def fit( self, dataset: DatasetH, - num_boost_round = 1000, - early_stopping_rounds = 50, - verbose_eval = 20, - evals_result = dict(), + num_boost_round=1000, + early_stopping_rounds=50, + verbose_eval=20, + evals_result=dict(), **kwargs ): df_train, df_valid = dataset.prepare( - ["train", "valid"], col_set = ["feature", "label"], data_key = DataHandlerLP.DK_L + ["train", "valid"], col_set=["feature", "label"], data_key=DataHandlerLP.DK_L ) x_train, y_train = df_train["feature"], df_train["label"] x_valid, y_valid = df_valid["feature"], df_valid["label"] @@ -49,16 +49,16 @@ class XGBModel(Model): else: raise ValueError("XGBoost doesn't support multi-label training") - dtrain = xgb.DMatrix(x_train.values, label = y_train_1d) - dvalid = xgb.DMatrix(x_valid.values, label = y_valid_1d) + dtrain = xgb.DMatrix(x_train.values, label=y_train_1d) + dvalid = xgb.DMatrix(x_valid.values, label=y_valid_1d) self.model = xgb.train( self._params, - dtrain = dtrain, - num_boost_round = num_boost_round, - evals = [(dtrain, "train"), (dvalid, "valid")], - early_stopping_rounds = early_stopping_rounds, - verbose_eval = verbose_eval, - evals_result = evals_result, + dtrain=dtrain, + num_boost_round=num_boost_round, + evals=[(dtrain, "train"), (dvalid, "valid")], + early_stopping_rounds=early_stopping_rounds, + verbose_eval=verbose_eval, + evals_result=evals_result, **kwargs ) evals_result["train"] = list(evals_result["train"].values())[0] @@ -67,5 +67,5 @@ class XGBModel(Model): def predict(self, dataset): if self.model is None: raise ValueError("model is not fitted yet!") - x_test = dataset.prepare("test", col_set = "feature") - return pd.Series(self.model.predict(xgb.DMatrix(x_test.values)), index = x_test.index) + x_test = dataset.prepare("test", col_set="feature") + return pd.Series(self.model.predict(xgb.DMatrix(x_test.values)), index=x_test.index)