Word2Vec及Stock2Vec
Word2Vec
Word2Vec是一个非常简单的模型,其实只有一个隐层,所以都不能算是“深度”学习。但是由于网上的教程都特别侧重于数学描述而对实现方案一带而过,加上Google的C语言版本的Word2Vec可读性好差(不知是可读性差还是我代码阅读力太差),好几次想研究研究这玩意儿都放弃了。最近痛定思痛下定决心,终于把论文和源码读下来了。
Word2Vec基本上有两个模型:Skip-gram和CBOW。Skip-gram是用一个单词的上下文(一个单词左右两边的单词)去猜测这个单词本身;CBOW是用一个单词去猜测它的上下文。可以想象,这么一个猜测任务的表现一定是非常差的——一个单词能组成的句子那么多,只看一个单词我怎么知道它左右有哪些单词。幸运的是,这个预测模型本身并不重要,我们需要的是这个学习任务中得到的副产品:词向量——其实就是模型的权重,从事后的角度来看,每个词所对应的权重似乎蕴含了词本身表达的信息。比如说good
这个单词,在It is a good weather
中,把good
换成great
整句话也不会有任何违和感,也就是说good
和great
往往具有相似的上下文,那么用good
去猜测上下文的结果和用great
猜测上下文的结果应该是相似的。那么网络学习到的great
和good
的权重也应该相似。这就是word2vec的基本思想。
令单词 $i$ 的词嵌入向量为 $u_i$ ,这个词的上下文单词的集合为$J$, CBOW模型就是一个多分类任务的逻辑回归:$\sigma(v_j\cdot u_i)\rightarrow P(j\in J | i)$ |
至于Negative Sampling和Hierarchical Softmax则是为了提升模型的训练速度。一般一个nlp任务的单词库至少也有上万个单词吧,每次运行模型都要对这上万甚至更多的单词一一做逻辑回归,任务量就太大了。Negative Sampling的做法是每次只对正样本(目标单词上下文的单词, 这些单词的标签为1)和一定比例的负样本(随机抽样一些单词,这些单词的标签为0)。这样每次训练都只做了几十次逻辑回归,计算量大大下降。一般来说改变负样本的采样频率会改变预测的表现,但是由于我们只关心词向量,因此问题不大。Hierarchical Softmax的做法我没认真看,就不说了。
Stock2Vec
在Word2Vec的基础上,我们不妨开一下脑洞,能不能用类似的方法获取每只股票的嵌入向量,来表达每只股票的特征呢?
令$u_i$和$r_i^t$为股票$i$的嵌入向量和t期的超额收益,我们用$\hat{y}=\sigma(sign(r_i^t)v_j\cdot u_i)$来建模其他股票超额收益为正的概率$y=P(r_j^t>0 | r_i^t)$,损失函数就用交叉熵$Loss=-[log(\hat{y})y+log(1-\hat{y})(1-y)]$。 |
由于同一个行业内的股票往往走势相关性很大,而且也有类似的基本面信息,因此可以想象同行业股票的嵌入向量往往很接近;另外,大盘股和小盘股也有各自的特征,因此股票嵌入向量也有可能会包含股票的市值大小等因素。
以贵州茅台
为例,以下是一些与之嵌入向量接近的股票,可以看到酒类、药类占了很大的比重,说明模型学习到了行业内部以及跨行业的相似性。
股票 | 相似度 |
---|---|
贵州茅台 | 1.000000 |
张裕A | 0.913261 |
山西汾酒 | 0.853480 |
泸州老窖 | 0.850967 |
苏泊尔 | 0.835780 |
欧亚集团 | 0.818946 |
中国国旅 | 0.817974 |
富安娜 | 0.811406 |
青岛海尔 | 0.800692 |
华北制药 | 0.797927 |
苏宁云商 | 0.797915 |
宇通客车 | 0.795434 |
越秀金控 | 0.792793 |
比亚迪 | 0.791884 |
上海家化 | 0.790853 |
酒鬼酒 | 0.788556 |
海宁皮城 | 0.784683 |
青青稞酒 | 0.778546 |
恒瑞医药 | 0.774118 |
搜于特 | 0.773303 |
洋河股份 | 0.767991 |
*ST中绒 | 0.766714 |
五粮液 | 0.763699 |
永辉超市 | 0.758078 |
康缘药业 | 0.757571 |
金种子酒 | 0.754999 |
康美药业 | 0.740614 |
天地科技 | 0.738492 |
江铃汽车 | 0.736122 |
启迪桑德 | 0.734836 |