diff --git a/examples/benchmarks/DoubleEnsemble/workflow_config_doubleensemble_Alpha158.yaml b/examples/benchmarks/DoubleEnsemble/workflow_config_doubleensemble_Alpha158.yaml index 12da23171..85cc0a270 100644 --- a/examples/benchmarks/DoubleEnsemble/workflow_config_doubleensemble_Alpha158.yaml +++ b/examples/benchmarks/DoubleEnsemble/workflow_config_doubleensemble_Alpha158.yaml @@ -37,7 +37,7 @@ task: kwargs: base_model: "gbm" loss: mse - num_models: 6 + num_models: 3 enable_sr: True enable_fs: True alpha1: 1 @@ -53,11 +53,8 @@ task: - 0.4 sub_weights: - 1 - - 0.2 - - 0.2 - - 0.2 - - 0.2 - - 0.2 + - 1 + - 1 epochs: 28 colsample_bytree: 0.8879 learning_rate: 0.2 diff --git a/examples/benchmarks/DoubleEnsemble/workflow_config_doubleensemble_Alpha360.yaml b/examples/benchmarks/DoubleEnsemble/workflow_config_doubleensemble_Alpha360.yaml index d9481f12d..74db1f362 100644 --- a/examples/benchmarks/DoubleEnsemble/workflow_config_doubleensemble_Alpha360.yaml +++ b/examples/benchmarks/DoubleEnsemble/workflow_config_doubleensemble_Alpha360.yaml @@ -44,7 +44,7 @@ task: kwargs: base_model: "gbm" loss: mse - num_models: 6 + num_models: 3 enable_sr: True enable_fs: True alpha1: 1 @@ -60,11 +60,8 @@ task: - 0.4 sub_weights: - 1 - - 0.2 - - 0.2 - - 0.2 - - 0.2 - - 0.2 + - 1 + - 1 epochs: 136 colsample_bytree: 0.8879 learning_rate: 0.0421 diff --git a/examples/benchmarks/README.md b/examples/benchmarks/README.md index 623172676..fb5602e9e 100644 --- a/examples/benchmarks/README.md +++ b/examples/benchmarks/README.md @@ -43,8 +43,7 @@ The numbers shown below demonstrate the performance of the entire `workflow` of | TFT (Bryan Lim, et al.) | Alpha158(with selected 20 features) | 0.0358±0.00 | 0.2160±0.03 | 0.0116±0.01 | 0.0720±0.03 | 0.0847±0.02 | 0.8131±0.19 | -0.1824±0.03 | | MLP | Alpha158 | 0.0376±0.00 | 0.2846±0.02 | 0.0429±0.00 | 0.3220±0.01 | 0.0895±0.02 | 1.1408±0.23 | -0.1103±0.02 | | LightGBM(Guolin Ke, et al.) | Alpha158 | 0.0448±0.00 | 0.3660±0.00 | 0.0469±0.00 | 0.3877±0.00 | 0.0901±0.00 | 1.0164±0.00 | -0.1038±0.00 | -| DoubleEnsemble(Chuheng Zhang, et al.) | Alpha158 | 0.0544±0.00 | 0.4340±0.00 | 0.0523±0.00 | 0.4284±0.01 | 0.1168±0.01 | 1.3384±0.12 | -0.1036±0.01 | - +| DoubleEnsemble(Chuheng Zhang, et al.) | Alpha158 | 0.0521±0.00 | 0.4223±0.01 | 0.0502±0.00 | 0.4117±0.01 | 0.1158±0.01 | 1.3432±0.11 | -0.0920±0.01 | ### Alpha360 dataset @@ -56,7 +55,7 @@ The numbers shown below demonstrate the performance of the entire `workflow` of | Localformer(Juyong Jiang, et al.) | Alpha360 | 0.0404±0.00 | 0.2932±0.04 | 0.0542±0.00 | 0.4110±0.03 | 0.0246±0.02 | 0.3211±0.21 | -0.1095±0.02 | | CatBoost((Liudmila Prokhorenkova, et al.) | Alpha360 | 0.0378±0.00 | 0.2714±0.00 | 0.0467±0.00 | 0.3659±0.00 | 0.0292±0.00 | 0.3781±0.00 | -0.0862±0.00 | | XGBoost(Tianqi Chen, et al.) | Alpha360 | 0.0394±0.00 | 0.2909±0.00 | 0.0448±0.00 | 0.3679±0.00 | 0.0344±0.00 | 0.4527±0.02 | -0.1004±0.00 | -| DoubleEnsemble(Chuheng Zhang, et al.) | Alpha360 | 0.0404±0.00 | 0.3023±0.00 | 0.0495±0.00 | 0.3898±0.00 | 0.0468±0.01 | 0.6302±0.20 | -0.0860±0.01 | +| DoubleEnsemble(Chuheng Zhang, et al.) | Alpha360 | 0.0390±0.00 | 0.2946±0.01 | 0.0486±0.00 | 0.3836±0.01 | 0.0462±0.01 | 0.6151±0.18 | -0.0915±0.01 | | LightGBM(Guolin Ke, et al.) | Alpha360 | 0.0400±0.00 | 0.3037±0.00 | 0.0499±0.00 | 0.4042±0.00 | 0.0558±0.00 | 0.7632±0.00 | -0.0659±0.00 | | TCN(Shaojie Bai, et al.) | Alpha360 | 0.0441±0.00 | 0.3301±0.02 | 0.0519±0.00 | 0.4130±0.01 | 0.0604±0.02 | 0.8295±0.34 | -0.1018±0.03 | | ALSTM (Yao Qin, et al.) | Alpha360 | 0.0497±0.00 | 0.3829±0.04 | 0.0599±0.00 | 0.4736±0.03 | 0.0626±0.02 | 0.8651±0.31 | -0.0994±0.03 | diff --git a/qlib/contrib/model/double_ensemble.py b/qlib/contrib/model/double_ensemble.py index ccdd88af7..50c3d22b4 100644 --- a/qlib/contrib/model/double_ensemble.py +++ b/qlib/contrib/model/double_ensemble.py @@ -44,7 +44,7 @@ class DEnsembleModel(Model, FeatureInt): if sample_ratios is None: # the default values for sample_ratios sample_ratios = [0.8, 0.7, 0.6, 0.5, 0.4] if sub_weights is None: # the default values for sub_weights - sub_weights = [1.0, 0.2, 0.2, 0.2, 0.2, 0.2] + sub_weights = [1] * self.num_models if not len(sample_ratios) == bins_fs: raise ValueError("The length of sample_ratios should be equal to bins_fs.") self.sample_ratios = sample_ratios @@ -87,7 +87,9 @@ class DEnsembleModel(Model, FeatureInt): loss_curve = self.retrieve_loss_curve(model_k, df_train, features) pred_k = self.predict_sub(model_k, df_train, features) pred_sub.iloc[:, k] = pred_k - pred_ensemble = pred_sub.iloc[:, : k + 1].mean(axis=1) + pred_ensemble = (pred_sub.iloc[:, : k + 1] * self.sub_weights[0 : k + 1]).sum(axis=1) / np.sum( + self.sub_weights[0 : k + 1] + ) loss_values = pd.Series(self.get_loss(y_train.values.squeeze(), pred_ensemble.values)) if self.enable_sr: @@ -159,8 +161,8 @@ class DEnsembleModel(Model, FeatureInt): h["bins"] = pd.cut(h["h_value"], self.bins_sr) h_avg = h.groupby("bins")["h_value"].mean() weights = pd.Series(np.zeros(N, dtype=float)) - for i_b, b in enumerate(h_avg.index): - weights[h["bins"] == b] = 1.0 / (self.decay**k_th * h_avg[i_b] + 0.1) + for b in h_avg.index: + weights[h["bins"] == b] = 1.0 / (self.decay**k_th * h_avg[b] + 0.1) return weights def feature_selection(self, df_train, loss_values): @@ -246,6 +248,7 @@ class DEnsembleModel(Model, FeatureInt): pd.Series(submodel.predict(x_test.loc[:, feat_sub].values), index=x_test.index) * self.sub_weights[i_sub] ) + pred = pred / np.sum(self.sub_weights) return pred def predict_sub(self, submodel, df_data, features):