基础 - 模型
Published on
简介
模型用于计算股票的预测分数。Qlib提供了基类Model
,所有模型都必须继承它;另外还提供了基类ModelFT
,包含了用于微调的方法。
例子
Qlib的模型库中包含了LightGBM
、MLP
、LSTM
等模型,它们被视为基线模型。下面的例子展示了如何将LightGBM
作为独立模块使用:
from qlib.contrib.model.gbdt import LGBModel
from qlib.contrib.data.handler import Alpha158
from qlib.utils import init_instance_by_config, flatten_dict
from qlib.workflow import R
from qlib.workflow.record_temp import SignalRecord, PortAnaRecord
market = "csi300"
benchmark = "SH000300"
data_handler_config = {
"start_time": "2008-01-01",
"end_time": "2020-08-01",
"fit_start_time": "2008-01-01",
"fit_end_time": "2014-12-31",
"instruments": market,
}
task = {
"model": {
"class": "LGBModel",
"module_path": "qlib.contrib.model.gbdt",
"kwargs": {
"loss": "mse",
"colsample_bytree": 0.8879,
"learning_rate": 0.0421,
"subsample": 0.8789,
"lambda_l1": 205.6999,
"lambda_l2": 580.9768,
"max_depth": 8,
"num_leaves": 210,
"num_threads": 20,
},
},
"dataset": {
"class": "DatasetH",
"module_path": "qlib.data.dataset",
"kwargs": {
"handler": {
"class": "Alpha158",
"module_path": "qlib.contrib.data.handler",
"kwargs": data_handler_config,
},
"segments": {
"train": ("2008-01-01", "2014-12-31"),
"valid": ("2015-01-01", "2016-12-31"),
"test": ("2017-01-01", "2020-08-01"),
},
},
},
}
# 初始化模型
model = init_instance_by_config(task["model"])
dataset = init_instance_by_config(task["dataset"])
# 开始实验
with R.start(experiment_name="workflow"):
# 训练
R.log_params(**flatten_dict(task))
model.fit(dataset)
# 预测
recorder = R.get_recorder()
sr = SignalRecord(model, dataset, recorder)
sr.generate()
严格来说,模型的预测分数的意义依赖于用户对标签的设计。在默认情况下,通常是模型对股票的排序,分数越高的股票收益越高。
自定义模型
通过以下步骤,用户可以编写自定义模型:
- 编写一个自定义模型类,它应该继承
Model
类 - 编写一个配置文件描述该模型的路径与参数
- 测试自定义模型
编写模型类
自定义模型类需要继承Model
并重写它的方法:
- 重写
__init__
方法- Qlib将初始化参数传给
__init__
方法 - 配置文件中的参数必须与
__init__
方法中定义的参数一致
- Qlib将初始化参数传给
例子如下,对应的配置文件中需要包含loss
等参数:
def __init__(self, loss='mse', **kwargs):
if loss not in {'mse', 'binary'}:
raise NotImplementedError
self._scorer = mean_squared_error if loss == 'mse' else roc_auc_score
self._params.update(objective=loss, **kwargs)
self._model = None
- 重写
fit
方法- Qlib调用
fit
方法训练模型 - 参数必须包含训练数据集
dataset
- 可以包含一些带有默认值的可选参数
- Qlib调用
例子如下,其中num_boost_round = 1000
是可选参数:
def fit(self, dataset: DatasetH, num_boost_round = 1000, **kwargs):
# 为lgb训练与评估准备数据
df_train, df_valid = dataset.prepare(
["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"]
# Lightgbm需要1D数组作为标签
if y_train.values.ndim == 2 and y_train.values.shape[1] == 1:
y_train, y_valid = np.squeeze(y_train.values), np.squeeze(y_valid.values)
else:
raise ValueError("LightGBM doesn't support multi-label training")
dtrain = lgb.Dataset(x_train.values, label=y_train)
dvalid = lgb.Dataset(x_valid.values, label=y_valid)
# 训练模型
self.model = lgb.train(
self.params,
dtrain,
num_boost_round=num_boost_round,
valid_sets=[dtrain, dvalid],
valid_names=["train", "valid"],
early_stopping_rounds=early_stopping_rounds,
verbose_eval=verbose_eval,
evals_result=evals_result,
**kwargs
)
- 重写
predict
方法- 参数必须包含测试数据集
dataset
- 返回预测分数
- 参数必须包含测试数据集
例子如下:
def predict(self, dataset: DatasetH, **kwargs)-> pandas.Series:
if self.model is None:
raise ValueError("model is not fitted yet!")
x_test = dataset.prepare("test", col_set="feature", data_key=DataHandlerLP.DK_I)
return pd.Series(self.model.predict(x_test.values), index=x_test.index)
- 重写
finetune
方法(可选)- 需要使用此方法时,应当继承
ModelFT
类 - 参数必须包含数据集
dataset
- 需要使用此方法时,应当继承
例子如下:
def finetune(self, dataset: DatasetH, num_boost_round=10, verbose_eval=20):
# 基于现有模型,通过训练更多轮次来进行微调
dtrain, _ = self._prepare_data(dataset)
self.model = lgb.train(
self.params,
dtrain,
num_boost_round=num_boost_round,
init_model=self.model,
valid_sets=[dtrain],
valid_names=["train"],
verbose_eval=verbose_eval,
)
编写配置文件
为了在自动工作流中使用自定义模型,用户需要修改配置文件中的模型部分。对于上面的自定义模型,配置文件如下:
model:
class: LGBModel
module_path: qlib.contrib.model.gbdt
args:
loss: mse
colsample_bytree: 0.8879
learning_rate: 0.0421
subsample: 0.8789
lambda_l1: 205.6999
lambda_l2: 580.9768
max_depth: 8
num_leaves: 210
num_threads: 20
用户可以在examples/benchmarks
目录下找到所有基线模型的配置文件。
测试
可以使用如下命令测试一个模型:
cd examples
qrun benchmarks/LightGBM/workflow_config_lightgbm.yaml
也可以将模型作为一个独立模块进行测试,一个例子在examples/workflow_by_code.ipynb
中。