2022年股票分析专题 BERT模型介绍与数据实证

  • 来源:华泰证券
  • 发布时间:2022/11/03
  • 浏览次数:2135
  • 举报

BERT、FinBERT 和 Adapter-BERT

BERT 模型介绍

BERT 网络结构及输入

关于 BERT 模型更详细的原理及背景介绍可以参考华泰金工研究《人工智能 62:NLP 综述, 勾勒 AI 语义理解的轨迹》,本文只对 BERT 模型进行基础概念的相关介绍,我们默认读者 对 NLP 相关概念已经有一定基础。BERT 的全称为 Bidirectional Encoder Representation from Transformers,其中有两个关键词,一个是 Bidirectional,一个是 Transformers。

1. 关于 Bidirectional(双向)的理解: 对于某一个句子,例如“介绍本文采用的[Mask]语言模型”,我们遮住其中的“预训练”一 词,想让模型预测出来。如果仅采用前文(即“介绍/本文/采用/的”)来预测[Mask],或者 仅采用后文(即“语言/模型”)来预测[Mask],均称为单向预测,不能完整地理解整个语句 的含义。BERT 的作者提出采用完整的上下文(即“介绍/本文/采用/的/…/语言/模型”)来 进行双向的预测,具体采用 Transformers 模型来实现。

2. Transformer: Transformer 是 Google 在 2017 年提出的用于机器翻译的模型,近年来被推广到了各个领 域,取得了较大的成功。Transformers 抛弃传统的 CNN、RNN 结构,采用编码器-解码器 (encoder-decoder)的结构,其核心是自注意力机制。

BERT采用了Transformer的编码器,其中最重要的是Multi-Head Attention(多头注意力)模块。所谓多头注意力,就是考虑多次自注意力机制,目的是提 取多重语意的含义,而自注意力机制本质上就是相关性的计算。通过自注意力机制,模型 得到了语句中每个词语与其他词语之间的相关性,从而把注意力放在相关性较大的词语上。 例如,我们想翻译“The cat stuck out its tongue and licked its owner”这句话。在这个语 句中,与“licked”最相关的词语是“cat”和“owner”,于是模型会重点联 系“cat”和“owner”的语意来翻译“licked”这个词语。

将 Transformer 的编码器进行多层堆叠后,形成 BERT 的主体结构。由于 BERT 是一个预 训练模型,因此需要适应各种各样的自然语言任务,模型的输入需要包含一句话(如文本 情感分类、序列标注任务)或者两句话以上(文本摘要、自然语言推断、问答任务等)。

BERT 的输入为每一个 token 对应的表征(token 的直观理解即为单词或字符),除了 token 以外还在输入的每一个序列开头插入特定的分类 token([CLS]),该分类 token 对应的最后 一个 Transformer 层输出可以表征整个序列的信息。 模型如何分辨输入句子属于句子 A 还是句子 B?BERT 采用两种办法来解决: 1. 在序列 tokens 中把分割 token(标记为[SEP])插入到每个句子之后,代表句子结束; 2. 为每一个 token 表征都添加一个可学习的分割 embedding 来指示其属于句子 A 还是句 子 B。

BERT 预训练任务

预训练在计算机视觉领域(CV,Computer Vision)是较为成熟的概念,CV 中所采用的预 训练任务一般是 ImageNet 图像分类任务,完成图像分类任务的前提是必须能抽取出良好的 图像特征,而 ImageNet 数据集具有规模大、质量高的优点,能获得较好的效果。NLP 中 没有像 ImageNet 这样的高质量人工标注数据,因此 BERT 利用大规模文本数据的自监督 性质来构建预训练任务,包括两项:Masked Language Model(MLM)和 Next Sentence Prediction(NSP)。

1. Masked Language Model(MLM)

在每条训练样本中以 15%的概率随机地选中某个 token 位置用于预测,且被选中的 token 会按概率替换成以下三个 token 之一: 1)80%的概率替换成[MASK],如 The stock price rises —> The stock price [MASK] 2)10%的概率替换为其他 token,如 The stock price rises —> The stock price dives 3)10%的概率还是原来的 token,如 The stock price rises —> The stock price rises 再用该位置的输出向量去预测替换后的 token(输出向量接全连接层,再用 softmax 输出为 每个 token 的概率,再和该位置的真实 token 向量求交叉熵损失函数)。

2. Next Sentence Prediction(NSP)

BERT 使用 NSP 预训练来使模型有能力理解句子之间的关系,即预测两个句子是否是上下 文关系。具体做法为对于每一个训练样例,在语料库中挑选出句子 A 和句子 B 来组成: 1)50%的概率句子 B 是句子 A 的下一句,此时标记为 IsNext; 2)50%的概率句子 B 是语料中随机选取的句子(不一定是 A 的下一句),此时标记为 NotNext; 把训练样例输入给 BERT,用[CLS]的输出向量进行二分类预测。 最后的预训练输入样本可能如下所示,每条样本在训练时 MLM任务和 NSP任务同时进行, 两部分损失函数相加作为总体预训练损失函数。 样本 1:[CLS] CSI500 rose [MASK] today [SEP] trading volume [MASK] significantly [SEP] 标签 1:IsNext 样本 2:[CLS] CSI500 [MASK] sharply today [SEP] penguin [MASK] are flight [SEP] 标签 2:NotNext 预训练完成的 BERT 模型在下游应用时会进行 Fine-Tuning 操作,本文后续在应用 FinBERT 对研报文本进行编码时,也是考虑到经过微调的 CLS 向量可以更好地表征文本语义信息, 所以在新闻舆情样本上进行了微调。

FinBERT 模型介绍

我们没有采用 Google 发布的原版 BERT,而是采用了熵简科技在 2020 年末发布的 FinBE RT:一款在大规模金融领域语料上预训练的中文 BERT 模型(https://github.com/valuesi mplex/FinBERT)。FinBERT 采用与原版 BERT 相同的模型架构,但预训练方法略有不同, 这里我们简要介绍 FinBERT 的预训练方法。

FinBERT 采用的预训练语料主要包括金融财经类新闻、研报或上市公司公告、金融类百科 词条,经预处理之后得到约 30 亿 Tokens,这一数量超过了原生中文 BERT 的训练规模: 1) 金融财经类新闻:从公开渠道采集的最近十年的金融财经类新闻资讯,约 100 万篇; 2) 研报/上市公司公告:从公开渠道收集的各类研报和公司公告,来自 500 多家境内外研 究机构,涉及 9000 家上市公司,包含 150 多种不同类型的研报,共约 200 万篇; 3) 金融类百科词条:从 Wiki 等渠道收集的金融类中文百科词条,约 100 万条。

基于上述数据集,熵简科技的 FinBERT 进行了两类预训练任务: 1. 字词级别的预训练: 1) Financial Whole Word Mask:该任务即前面提到的,随机遮住部分字词,让模型预 测。这里进一步采用了全词 Mask 的方法,即对组成同一个词语的汉字全部进行 Mask, 从而使模型学习到领域内的先验知识,例如金融学概念之间的相关性等。 2) Next Sentence Prediction:引入预测下一句的任务,使模型理解句子间的关系。 2. 任务级别的预训练: 1) 研报行业分类:利用公司点评、行业点评类的研报自动生成了大量带有行业标签的语料, 并构建了行业分类的文档级有监督任务。每个行业拥有 5k~20k 条语料,共计约 40 万 条文档级语料。 2) 财经新闻的金融实体识别:利用已有的企业工商信息库和公开可查的上市公司董监高信 息,基于金融财经新闻构建了命名实体识别类的有监督任务语料,共计约 50 万条。

Adapter-BERT

上文所述的 FinBERT 模型参数量超过一亿,直接使用常规的微调方法对所有参数都进行微 调,配置要求较高,很难实现。本文采用了 2019 年发表于机器学习顶级会议 ICML 的 ada pter-BERT(http://proceedings.mlr.press/v97/houlsby19a.html),在几乎不影响模型性能 的情况下,将需要微调的参数减少到约三百万。 具体而言,在 BERT 的每个 Transformer 层内添加了两个 Adapter 模块,位于全连接层之 后。Adapter 模块的主要结构为一个下采样全连接层和一个上采样全连接层,并且包括一个 残差连接。Adapter 模块内的全连接层的参数要远少于 Transformer 内的多头 注意力层和全连接层的参数。

数据处理与模型训练

FinBERT 模型微调

新闻舆情数据展示

一般来说如果预训练好的 BERT 不进行特定场景的微调操作,其 CLS 层难以对整段文本进 行向量编码,这是因为 BERT 在训练时的两个任务 MLM 和 NSP 都不是为了对句子进行编 码而设计的,CLS 蕴含的信息不一定是充分的文本上下文信息,常规做法是会对 BERT 进 行微调。我们使用带情感标注的万得新闻舆情数据对 FinBERT 进行微调,使得 CLS 层能 更好地表征文本上下文信息。 Wind 新闻舆情数据库提供的舆情数据从 2015 年开始,为了尽可能少地使用到未来信息, 同时保证可用于模型微调的训练样本数量足够,我们仅使用 2015-2017 三年的全部万得新 闻舆情数据,并进行以下操作生成最终的待训练样本。

最终我们得到 14.8 万条金融新闻舆情情感分类样本。其中步骤 8)所使用的 tokens 长度 N 将决定后续对研报进行情感编码时每次可以输入的文本长度,我们将在后文进行讨论。下 表展示了万得新闻舆情数据库中的数据结构。

FinBERT 微调

在微调 FinBERT 时我们需要搭建结构完整的网络层,在 FinBERT 前面我们添加了一个输 入层;在 FinBERT 输出特征向量之后,首先截取[CLS]标识符对应的 768 维特征向量,然 后通过两个 Dropout 层和两个全连接层的组合,映射到 2 维的情感分类概率。

超参数的选择不一定完全按照下表所示,FinBERT 微调受随机数种子点影响较小,因此可以根据实际显卡配置对参数进行调整。实际上总训 练轮数也可以降低,可以看到损失函数及分类准确率基本在 10 轮以后就明显收敛。

FinBERT 编码与二次训练

FinBERT 研报编码

在微调完 FinBERT 以后,我们对每篇分析师研报进行编码。过去我们的做法是将每篇文本 处理成词频向量,本质是认为拆解出的词频可以表征整段文本的语义信息;现在我们使用 FinBERT 来对研报文本进行向量编码。首先,我们采用与生成微调样本类似的预处理方法, 将研报文本预处理成 FinBERT 能读入的形式,具体而言:

处理长文本的两种方式:截长补短和切割为多段,截长 补短即常规的 Truncate 和 Pad 操作;切割为多段指的是按固定字符数将长文本切分为多条 样本,我们会在后文进行讨论。此处 tokens 的长度 N 实际取决于 FinBERT 在数据预处理 与训练时采用的 tokens 长度,关于这个参数我们也会在下文进行讨论。 上述预处理完成后,我们将研报文本输入给 FinBERT,然后去掉微调 FinBERT 网络结构中 的 4~7 层,仅保留 1~3 层,输出 FinBERT 的 CLS 层作为研报文本的向量编码,CLS 层的 维度为 768 维。接下来我们将上述隐藏层向量作为 XGBoost 的输入来进 行第二次训练。

XGBoost 模型训练

相比于词频向量的版本,第二步训练我们唯一修改的地方仅在于输入给 XGBoost 模型的特 征有所改变,其他细节基本相同。具体来说,XGBoost 的训练标签为研报发布前后两天, 个股相对于中证 500 的超额收益(不进行中性化处理),我们按以下方式将其分为三类后作 为训练标签 Y: 1. 上涨(y=1):较大的正向超额收益,即样本的超额收益位于整体的前 30%; 2. 震荡(y=0):较低的正向或负向超额收益,即样本的超额收益位于整体的前 30%~70%; 3. 下跌(y=-1):较大的负向超额收益,即样本的超额收益位于整体的后 30%。词频向量的优势在于可解释性较强, 可以很直观地看出每一维特征的含义,但是会损失较多语义信息;BERT 编码的优势在于对 语义信息的利用更充分,但是可解释性较差,每一维特征的含义不明显。

我们采用滚动的方式对 XGBoost 模型进行训练,每次滚动样本内为过去 6 个月,样本外为 未来 12 个月。例如对于某轮样本外的首月 T 月来说,我们将 T-6 至 T-1 月的数据作为样本 内,T 月至 T+11 月的数据作为样本外;下一迭代期则以 T+6 月至 T+11 月的数据作为样本 内,T+12 至 T+23 月的数据作为样本外;以此类推。

数据实证:从更充分的语义理解到更显著的 Alpha 提升

基础模型实证

在进行更多参数讨论之前,同样的我们首先给出基准参数模型下的文本因子表现。主要讨 论部分我们仍以盈利预测调整场景下的研报文本挖掘为主,后面我们同样展示业绩发布、 评级调整场景下的文本因子升级效果。

词频向量版的十分层回测结果、与 FinBERT 编码版本的 forecast_adj_txt_bert 因子多头第一 层对比。相比于词频向量版本,FinBERT 编码的版本多 头收益提升显著,从原始 22.87%提升至 27.50%,多头收益提升接近 5Pct。FinBERT 编码 版因子多头相对中证 500 超额收益在 2016、2017 年也获得明显正向超额,而词频向量版 因子多头在这两年超额走平。从选定参数的基础模型来看,除多头以外,其余分层的提升 不明显。

扩展测试一:文本截断和分段的比较

在 NLP 任务中需要根据实际应用场景来对文本进行一定的预处理,例如在某些场景下,可 以尝试对原始文本进行过滤,降低有效文本的长度,从而提升模型性能。

在前文所述的基础模型中,我们采用的是前截断的方法来保证文本不超过指定字符数,从 逻辑上来说我们将标题与摘要拼接,且大多数研报首段会总结最核心的观点,因此前截断 保留关键信息是合乎逻辑的。这里我们再尝试一种预处理方法,即对长文本进行分段:如 果一条文本字符数超过 N,那么我们以长度 N 为限将长文本分成多条样本。 切分以后的每条样本都将作为一条单独的样本参与下一步 XGBoost 模型训练与预测。

在样本外预测时,每条研报样本的得分将由分段子样本的得分求均值得到。这里我们比较 字符数为 500 或 200、分段或截断四种组合的测试结果。从对比结果 来看,有以下两点结论: 1. 引入 BERT 编码以后的各组测试因子收益均优于词频向量版本,绝对收益的提升都在 1.5Pct 以上,说明 BERT 编码的提升是稳健的,方法论的改进不是偶然导致的过拟合; 2. 样本分段的测试组多头超额更稳健,最近一年超额波动更小,可能是因为在合成因子时 所使用的样本量更多,选股效果更稳定。

扩展测试二:是否有必要对 FinBERT 进行微调?

前文我们提到过,如果不对 BERT 模型进行微调,BERT 的 CLS 或不能很好地表征语义信 息,因为 BERT 预训练时 MLM 及 NSP 两个任务都不是为了表征语义信息而提出的,因此 任务目标不同。微调实际上是为了使得 BERT 能更好地表征语义信息。我们发现如果不对 FinBERT 进行微调,在带标注的新闻舆情语料上的分类准确率约为 80%,微调以后分类准 确率超过 96%。 本小节我们测试微调对文本因子的影响。对于不做微调的测试组,我们直接将研报文本预 处理好以后输入给 FinBERT 并提取出 CLS 层作为后续 XGBoost 模型训练的输入,其他流 程相同。从结果来看,如果不对 FinBERT 进行微调,虽然 forecast_adj_txt_bert 因子也有比较明显的多头收益,但是相比于词频向量的版本没有明显 提升。因此我们认为有必要对 FinBERT 进行微调。

扩展测试三:CLS 编码与全连接层编码对比

在对 FinBERT 进行微调时,CLS 层后连接的是全连接层,该隐藏层也可以视为是对研报文 本的编码。本小节我们尝试比较使用该全连接层进行编码与使用 CLS 层进行编码的效果有 何不同。 从结果来看全连接层也可以用于文本编码,构建出的文本因子相比于词频向量版本仍有一 定提升,且近两年多头超额较为稳健,波动相对更小。此外全连接层编码得到的 forecast_adj_txt_bert 因子分层更为明显,第二层表现也较好。

扩展测试四:CLS 编码与词频特征结合

我们继续尝试将 CLS 编码与词频向量结合一起作为特征输入给 XGBoost 模型进行训练。 当然从逻辑上来说 CLS 编码基本已经包含文本的绝大部分信息,再纳入词频向量或有冗余, 这里我们仅作为测试实验进行展示。

从上述结果来看,额外加入词频向量作为特征以后效果并未有进一步提升,说明 CLS 编码 确实已经能涵盖绝大部分文本信息,但加入词频特征以后,forecast_adj_txt_bert 因子的分 层效果有所提升。

扩展测试五:仅使用 FinBERT 微调

除了前文 FinBERT 编码与 XGBoost 模型训练的改进思路以外,直接使用 FinBERT 在每一 轮进行微调也是一种思路,微调时不再使用带标签的万得新闻舆情,而是直接使用研报, 预测标签使用 XGBoost 模型训练时的标签。其余流程不变。

从上述结果来看,如果仅使用 FinBERT 微调而不引入第二步骤的 XGBoost 模型训练,构建 出的文本因子效果明显削弱。我们认为有两种可能的解释:1)BERT 模型的优势在于对语义 本身的理解,如果直接引入个股超额收益这一标签进行学习,反而增加了模型学习的负担, 模型既要学习语义理解,又要学习市场的反馈,导致效果不佳;2)FinBERT 参数量较大, 可能是由于测试规模仍然不足所以导致没有得到潜在的更优解,而并非方案本身缺陷。

Forecast_adj_txt_bert 因子讨论

我们继续对 forecast_adj_txt_bert 因子进行一些其他讨论。我们计算该文本因子与 Barra 风 格因子及传统因子的皮尔森相关系数。文本因子与动量因子正相关性相对较高,历史均值大约在 0.3 左右; 与 BP 因子负相关性相对较高,历史均值大约在-0.3 左右;与其余风格因子整体相关性偏低。 文本因子与传统因子相关性也较低,历史每个截面期的相关系数均值都不超过 0.5。

不同场景下的文本因子升级

业绩发布

在业绩发布场景下我们也可以对 SUE_txt 因子进行升级,SUE_txt 在计算时样本匹配流程,业绩公告的类型包括业绩预告、业绩快报及正式财报。

三类公告在合并时,按以下流程计算: 1. 模型训练:模型滚动训练时,所有类型的公告样本放在一起训练;同时进行样本预剔除, 即对每个季度单独判断,如果该季度已经发布过业绩预告或快报,则不使用财报样本。 2. 因子构建: 1) 在 4 月末追溯 2/3/4 月所有类型公告并计算因子值;在 8 月末,追溯 7/8 月所有类 型公告并计算因子值;在 10 月末,追溯 10 月所有类型公告样本并计算因子值; 2) 在其余月末,首先延续上月末的因子值,然后对当月已经发布了新的业绩公告的股 票,更新该公告对应的 SUE_txt 因子值。

文本因子的应用案例

案例一:主动量化选股组合

等权增强组合

在前期两篇相关报告中我们都曾将文本因子应用于构建主动量化选股组合,这里我们也不 例外,继续展示主动量化选股组合的构建案例。以 forecast_adj_txt_bert 因子分十层的多头 第一层为基础股票池,使用以下表格中的因子,每月将下述因子进行等权合成,合成之前 会对因子进行行业市值中性化处理,同时对因子方向进行调整。相比于上篇报告(人工智 能 57)所使用的 4 个基本面+4 个技术面因子,这里我们纳入了更多因子进行合成,提高合 成得分的稳定性。

不等权增强组合

我们进一步考虑从等权组合到不等权组合。我们从技术面角度出发对文本 FADT 选股组合 的权重进行调整,如果个股处于较为明显的上行趋势,则个股权重可以适当增加;反之若 个股处于较为明显的下行趋势,则个股权重可以适当降低。具体来说,我们使用个股的多 空头排列状态来对个股权重进行调整。

权重调整流程如下所示: 1. 在调仓截面日判断组合内个股的多空头状态:如果过去 20 个交易日有超过 15 个交易 日多头排列,则个股处于多头状态;如果过去 20 个交易日有超过 10 个交易日空头排 列,则个股处于空头状态(空头给予的满足条件更宽松,给下行趋势的股票更大惩罚); 2. 若个股为多头状态,则将原始的持仓权重乘以 2;若个股为空头状态,则将原始的持仓 权重乘以 0.5; 3. 按 100%总仓位将调整后的持仓权重归一化; 4. 考虑到个股持仓权重不能过高,如果调整后个股权重超过 20%,则截断为 20%。

加入市值限制的主动量化选股

考虑到部分投资者对股票市值有限制,不能投资池外市值过小的股票,因此我们考虑对股 票组合的市值进行限制。首先在 forecast_adj_txt_bert 中对应截面期总市值低于 100 亿元 的股票因子值置为 nan,对剩余个股在截面上进行十分层,仍以第一层为基础池,使用上文 所述因子进行增强构建等权选股组合。

案例二:沪深 300 内选股

第二组案例我们测试直接在沪深 300 股票池内进行选股的效果。与传统的指数增强不同, 这里我们不控制行业市值中性,不控制风格中性,仅根据 forecast_adj_txt_bert 因子在沪深 300 股票池内的打分选择靠前的 30 只股票,按前文所述多空头排列权重调整方式对个股仓 位进行调整,得到沪深 300 内不等权精选组合。


(本文仅供参考,不代表我们的任何投资建议。如需使用相关信息,请参阅报告原文。)

相关报告
评论
  • 相关文档
  • 相关文章
  • 全部热门
  • 本年热门
  • 本季热门
分享至