8.4 使用大数据——在线算法与外存学习
如果你执行上一节中的示例代码,就会发现:在网格搜索阶段为包含50000个电影评论的数据集构建特征向量的计算成本很高。在许多真实应用中,经常会用到更大的数据集,数据集大小甚至会超出计算机内存的容量。并不是每个人都有机会使用超级计算设备,因此我们将通过一种称为外存学习的技术来处理超大数据集。
回顾一下第2章中我们曾经介绍过的随机梯度下降(stochastic gradient descent)的概念,此优化算法每次使用一个样本更新模型的权重信息。在本节,我们将使用scikit-learn中SGDClassifier的partial_fit函数来读取本地存储设备,并且使用小型子批次(minibatches)文档来训练一个逻辑斯谛回归模型。
在本章开始时,我们构建了movie_data.csv数据文件,且在移除停用词阶段对此单词做了token处理。首先,我们定义一个tokenizer函数来清理movie_data.csv文件中未经处理的文本数据:
接下来我们定义一个生成器函数:stream_docs,它每次读取且返回一个文档的内容:
为了验证stream_docs函数是否能正常工作,我们来读取一下movie_data.csv文件的第一个文档,它应返回一个包含评论信息和对应类标的元组:
定义一个get_minibatch函数,它以stream_doc函数得到的文档数据流作为输入,并通过参数size返回指定数量的文档内容:
不幸的是,由于需要将所有的词汇加载到内存中,我们无法通过CountVectorizer来使用外存学习方法。另外,TfidfVectorizer需要将所有训练数据集中的特征向量加载到内存以计算逆文档频率。不过,scikit-learn提供了另外一个处理文本信息的向量处理器:HashingVectorizer。HashingVectorizer是独立于数据的,其哈希算法使用了Austin Appleby提出的32位MurmurHash3算法(https://sites.google.com/site/murmurhash/)。
在上述代码中,我们使用tokenizer函数初始化HashingVectorizer,并且将特征的数量设定为221。此外,我们通过将SGDClassifier中loss参数的值设定为log来重新初始化逻辑斯谛回归分类器。请注意:通过为HashingVectorizer设定一个大的特征数量,降低了哈希碰撞的概率,不过同时也增加了逻辑斯谛回归模型中系数的数量。
现在到了真正有趣的部分。设置好所有的辅助函数后,我们可以通过下述代码使用外存学习:
为了估计学习算法的进度,我们再一次使用PyPrind包。将进度条对象设定为45次迭代,在接下来的for循环中,我们在45个文档的子:批次上进行迭代,每个子:批次包含1000个文档。
完成了增量学习后,我们将使用剩余的5000个文档来评估模型的性能:
可以看到,模型的准确率约为87%,略微低于我们在上一节使用网格搜索进行超参调优得到的模型。不过外存学习的存储效率很高,只用了不到一分钟的时间就完成了计算。最后,我们可以通过剩下的5000个文档来升级模型:
如果读者希望直接进入第9章,建议不要关闭当前的Python会话窗口。在下一章中,我们学习如何将刚刚训练得到的模型存储到硬盘以供后续使用,以及如何将其嵌入到Web应用中。
虽然词袋模型仍旧是文本分类领域最为流行的模型,但是它没有考虑句子的结构和语法。一种流行的词袋模型扩展就是潜狄利克雷分配(Latent Dirichlet Allocation),这是一种考虑句子潜在语义的主题模型(D.M.Blei,A.Y.Ng,and M.I.Jordan.Latent Dirichlet allocation.The Journal of machine Learning research,3:993-1022,2003)。
word2vec是最近提出的一种词袋模型的替代算法,它由谷歌公司在2013年提出(T.Mikolov,K.Chen,G.Corrado,and J.Dean.Efficient Estimation of Word Represen-tations in Vector Space.arXiv preprint arXiv:1301.3781,2013)。word2vec算法是基于神经网络的一种无监督算法,它会自动尝试学习单词之间的关系。word2vec背后的理念就是将词义相近的单词划分到相同的簇中;通过巧妙的向量间隔,此模型可以通过简单的向量计算来得到合适的单词,例如:king–man+woman=queen。
读者可以通过链接https://code.google.com/p/word2vec/找到word2vec模型原始的C语言实现、相关的论文及其替代实现代码。