halo 的技术博客

返回

先说结论:情感词典只认得你手工列进去的词,而市场天天造新词——词典外的表达它一律算 0,直接漏掉。词嵌入把每个词学成一个向量,语义相近的词自动挨在一起,于是词典没收录的新词也能被『情绪方向』投影出来。 本文合成实验:4000 条公告、三类语义(利好/利空/中性),纯 numpy 训练 skip-gram 后同类词余弦相似度 0.981 远高于异类 0.896。关键对比在留出集上:面对全部由词典外新词组成的公告,词典计数法 IC 直接归零(0.000),而嵌入因子仍有 0.602——这就是向量空间的泛化能力。

词嵌入把语义相近的公告用词聚成簇(PCA 二维投影)

一、问题:词典是死的,语言是活的#

量化里处理文本情绪,最朴素的办法是情感词典:维护一张表,“增长、超预期、回购”记 +1,“亏损、减持、诉讼”记 −1,一篇公告的情绪分就是正词数减负词数。简单、可解释、算得快。

但它有个绕不过去的死穴:它对没收录的词完全失明。 你词典里有”超预期”,某天研报写”业绩大幅扩产、新签订单饱满”——“扩产""订单”你没收录,这篇明明强烈利好的公告,词典给它打 0 分。语言在演化、行业黑话在更新、同一个意思有几十种说法,而手工词典永远追不上。你以为你在做情绪分析,其实只在数几个固定关键词出现了几次。

词嵌入换了个根本思路:不靠人工列词表,而是让模型从海量文本里自己学出『哪些词意思相近』。 学出来的不是标签,是每个词的一个稠密向量。语义相近的词,向量也相近。这样一来,哪怕”扩产”从没被你标注过,只要它在语料里和”增长""超预期”经常出现在相似的上下文,它的向量就会落在利好词一堆里,自然被情绪轴投影成正向。

二、原理:用上下文定义词义#

词嵌入的哲学根基是分布假说(Firth 1957):“一个词的意义,由它周围经常出现的词决定。” “增长”和”扩产”如果总是出现在相似的邻居中间(同样跟着”订单""业绩""超预期”),那它们语义就相近,向量就该接近。

word2vec 的 skip-gram 把这句话变成一个可优化目标:用中心词去预测它窗口内的上下文词。 训练完成后,那个”用来预测”的中心词向量矩阵,就是我们要的词嵌入。

直接对整个词表做 softmax 太贵(每步要归一化几万个词),实践用负采样近似:对每个真实的 (中心词, 上下文词) 正样本,随机抽几个不相关的词当负样本,目标变成”让正样本点积大、负样本点积小”:

L=logσ(vcvo)k=1Klogσ(vcvnk)\mathcal{L} = -\log \sigma(v_c \cdot v_o) - \sum_{k=1}^{K} \log \sigma(-v_c \cdot v_{n_k})

其中 vcv_c 是中心词向量,vov_o 是真实上下文词,vnkv_{n_k} 是负采样词,σ\sigma 是 sigmoid。负样本按词频的 0.75 次方抽样——这个指数是 word2vec 原论文的经验值,作用是既不让高频词(“的""公告”)霸占负样本,也不让极低频词几乎不被抽到。

三、纯 numpy 实现#

三个部件:负采样表、前向的 sigmoid 打分、反向的梯度更新。核心就是对每个训练对,更新中心词向量和它对应的正/负上下文词向量。

训练完对 Win 做行归一化,就得到可以直接算余弦相似度的词嵌入。构造语料时用了三个语义主题,每个主题一套高共现词汇,主题间只有 8% 的词汇泄漏——这模拟了真实公告里”利好用词扎堆、利空用词扎堆”的结构。

四、结果一:语义相近的词自动聚成簇#

训练后把 16 维嵌入做 PCA 投到二维(就是封面图),利好、利空、中性三类词各自聚成一团,泾渭分明——模型从没见过这些标签,纯粹靠”谁和谁在相似上下文里出现”就把它们分了开。

量化上更严格的检验是同类词对 vs 异类词对的余弦相似度分布:

余弦相似度:同语义类词对显著高于跨类词对

同类词对平均余弦 0.981,异类词对 0.896,两个分布明显分离。这个”同类高、异类低”的间隔,就是后面能把词典外新词投影出方向的物理基础——新词只要落在某类词堆里,它跟这类的余弦就高。

五、结果二:词典外新词,才是嵌入真正的战场#

这是全文最值钱的实验。我把每类词汇拆成两半:

  • 词典内词(前 5 个):分析师手工收录进情感词典的;
  • 词典外新词(后 5 个):模型学过(在语料里出现过),但从没被写进词典的新表达。

情绪轴只用词典内词构造(利好词均值利空词均值\text{利好词均值} - \text{利空词均值}),模拟”分析师只能给自己认识的词打标签”。然后分两种公告检验预测力(IC,因子与公告后收益的相关):

信息系数 IC:嵌入因子 vs 词典计数,在纯新词公告上分野

  • 混合用词公告(含词典内词):嵌入因子 IC 0.607,词典计数 0.574——基本打平。当词典能覆盖到词时,两种方法差不多,词典甚至因为规则硬、无噪声还略稳。
  • 纯新词公告(全是词典外新词):词典计数 IC 暴跌到 0.000——它一个词都不认识,全篇打 0,因子成了常数,彻底失去区分度;而嵌入因子 IC 仍有 0.602,几乎没掉。

右图直观展示:即便这些公告用的全是词典没有的新词,嵌入情绪投影值越高,公告后收益的分组均值仍单调上升。原因就是那 0.981 vs 0.896 的间隔——新词”扩产”在向量空间里紧挨着词典内的”增长""超预期”,情绪轴投影自然把它识别成利好。词典法的天花板是它的词表大小,嵌入法的天花板是语料的覆盖广度,后者高一个量级。

六、维度怎么选#

嵌入维度 DD 是要调的超参。用”同类均值余弦 − 异类均值余弦”这个分离间隔来衡量质量:

嵌入维度敏感性:同类-异类相似度差随维度先升后平

D=2D=2 时间隔只有 0.055——维度太低,向量塞不下三类的区分信息,被迫挤在一起。DD 升到 816 间隔涨到约 0.10 并趋于平台,再往上(32、64)不再改善甚至略降。结论:维度不是越大越好,够用即止。 真实语料词表几万、语义关系复杂,工业界常用 100300 维;但盲目堆到上千维只会增加过拟合和计算成本,不会带来成比例的语义质量提升。

七、五类真实陷阱#

陷阱一:把余弦相似度当因果或情感强度。 嵌入学的是”共现相似”,不是”情感极性”。“利好”和”利空”这对反义词,因为经常出现在同类公告的相似位置(都在讲业绩),余弦可能不低。要提取情感方向必须像本文那样显式构造情绪轴(正词均值减负词均值),不能直接拿两个词的余弦当情绪。

陷阱二:语义相近不等于会同向变动。 嵌入告诉你”扩产”和”增长”语义近,不告诉你它们对应的股票会同涨同跌。从词向量到收益预测,中间隔着一整套”语义→事件→基本面→价格”的传导,每一步都会衰减和引入噪声。本文 IC 0.6 是合成数据的理想值,真实公告文本的情绪因子 IC 通常在 0.02~0.05 量级。

陷阱三:训练语料的时间泄漏。 这是文本因子最容易翻车的地方:用全样本语料训练嵌入,再回测早期时段,等于让早期的模型偷看了未来的语言分布(新词、新说法)。严谨做法是嵌入训练窗口严格早于回测窗口,滚动更新,绝不能一次训练用到底。

陷阱四:文档向量用简单平均会丢结构。 本文把公告向量取词向量均值——简单但会抹掉词序和否定。“不及预期”里的”预期”是正词,“不及”是负词,平均下来可能互相抵消甚至判成中性。真实系统需要处理否定词、程度副词,或改用能建模词序的模型。

陷阱五:中文分词是隐藏的前置误差源。 英文空格分词,中文得先分词。“超预期”被错分成”超”+“预期”,或”业绩预亏”被分成”业绩”+“预亏”还是”业绩预”+“亏”,直接决定了词表和共现统计。分词错了,后面再好的嵌入都是建在沙子上。本文用的是预定义词表规避了这个问题,实盘里它往往是最大的误差来源。

小结#

词嵌入相对情感词典的核心优势,不是”更准”,而是泛化——它把离散的、封闭的词表,换成了连续的、开放的语义空间。词典法的能力边界是你列了多少词,嵌入法的能力边界是语料覆盖了多少语言现象。当市场用词稳定、词典覆盖充分时,两者差不多;但一旦遇到新词、黑话、同义变体(这在真实公告里是常态),词典法会系统性失明,而嵌入法凭借”新词自动落进语义邻域”继续工作。代价是它需要足够语料、需要防时间泄漏、且从语义相似到收益预测中间还有很长的、会大幅衰减的传导链——它是一个强大的特征工程工具,不是印钞机。

词嵌入金融文本:用向量空间把公告语义变成可计算因子
https://blog.halo26812.eu.org/blog/word-embedding-finance
Author halo
Published at 2026年7月24日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨