Word2Vec

Word2Vec是一个非常简单的模型,其实只有一个隐层,所以都不能算是“深度”学习。但是由于网上的教程都特别侧重于数学描述而对实现方案一带而过,加上Google的C语言版本的Word2Vec可读性好差(不知是可读性差还是我代码阅读力太差),好几次想研究研究这玩意儿都放弃了。最近痛定思痛下定决心,终于把论文和源码读下来了。

Word2Vec基本上有两个模型:Skip-gram和CBOW。Skip-gram是用一个单词的上下文(一个单词左右两边的单词)去猜测这个单词本身;CBOW是用一个单词去猜测它的上下文。可以想象,这么一个猜测任务的表现一定是非常差的——一个单词能组成的句子那么多,只看一个单词我怎么知道它左右有哪些单词。幸运的是,这个预测模型本身并不重要,我们需要的是这个学习任务中得到的副产品:词向量——其实就是模型的权重,从事后的角度来看,每个词所对应的权重似乎蕴含了词本身表达的信息。比如说good这个单词,在It is a good weather中,把good换成great整句话也不会有任何违和感,也就是说goodgreat往往具有相似的上下文,那么用good去猜测上下文的结果和用great猜测上下文的结果应该是相似的。那么网络学习到的greatgood的权重也应该相似。这就是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