利用word2vec对关键词进行聚类

2017 年 8 月 28 日 数据挖掘入门与实战 要学习更多点这→



大数据挖掘DT数据分析  公众号: datadw


按照一般的思路,可以用新闻ID向量来表示某个关键词,这就像广告推荐系统里面用用户访问类别向量来表示用户一样,然后就可以用kmeans的方法进行聚类了。不过对于新闻来说存在一个问题,那就量太大,如果给你十万篇新闻,那每一个关键词将需要十万维的向量表示,随着新闻数迅速增加,那维度就更大了,这计算起来难度太大。于是,这个方法思路简单但是不可行。


好在我们有word2vec这个工具,这是google的一个开源工具,能够仅仅根据输入的词的集合计算出词与词直接的距离,既然距离知道了自然也就能聚类了,而且这个工具本身就自带了聚类功能,很是强大。下面正式介绍如何使用该工具进行词的分析,关键词分析和聚类自然也就包含其中了。word2vec官网地址看这里:https://code.google.com/p/word2vec/


1、寻找语料

要分析,第一步肯定是收集数据,这里不可能一下子就得到所有词的集合,最常见的方法是自己写个爬虫去收集网页上的数据。不过,如果不需要实时性,我们可以使用别人提供好的网页数据,例如搜狗2012年6月到7月的新闻数据:http://www.sogou.com/labs/dl/ca.html 直接下载完整版,注册一个帐号,然后用ftp下载,ubuntu下推荐用filezilla






下载得到的数据有1.5G



2、分词

我们得到的1.5的数据是包含一些html标签的,我们只需要新闻内容,也就是content其中的值。首先可以通过简单的命令把非content的标签干掉



  1. cat news_tensite_xml.dat | iconv -f gbk -t utf-8 -c | grep "<content>"  > corpus.txt  


得到了corpus.txt文件只含有content标签之间的内容,再对内容进行分词即可,这里推荐使用之前提到过的ANSJ,没听过的看这


里:http://blog.csdn.net/zhaoxinfan/article/details/10403917


下面是调用ANSJ进行分词的程序:


  1. import java.util.HashSet;  

  2. import java.util.List;  

  3. import java.util.Set;  

  4. import java.io.BufferedReader;  

  5. import java.io.BufferedWriter;  

  6. import java.io.File;  

  7. import java.io.FileInputStream;  

  8. import java.io.FileReader;  

  9. import java.io.FileWriter;  

  10. import java.io.IOException;  

  11. import java.io.InputStreamReader;  

  12. import java.io.PrintWriter;  

  13. import java.io.StringReader;  

  14. import java.util.Iterator;  

  15.   

  16. import love.cq.util.IOUtil;  

  17.   

  18. import org.ansj.app.newWord.LearnTool;  

  19. import org.ansj.domain.Term;  

  20. import org.ansj.recognition.NatureRecognition;  

  21. import org.ansj.splitWord.Analysis;  

  22. import org.ansj.splitWord.analysis.NlpAnalysis;  

  23. import org.ansj.splitWord.analysis.ToAnalysis;  

  24. import org.ansj.util.*;  

  25. import org.ansj.recognition.*;  

  26.   

  27.   

  28. public class test {  

  29.     public static final String TAG_START_CONTENT = "<content>";  

  30.     public static final String TAG_END_CONTENT = "</content>";  

  31.       

  32.     public static void main(String[] args) {  

  33.         String temp = null ;  

  34.           

  35.         BufferedReader reader = null;  

  36.         PrintWriter pw = null;  

  37.         try {  

  38.             reader = IOUtil.getReader("corpus.txt""UTF-8") ;  

  39.             ToAnalysis.parse("test 123 孙") ;  

  40.             pw = new PrintWriter("resultbig.txt");  

  41.             long start = System.currentTimeMillis()  ;  

  42.             int allCount =0 ;  

  43.             int termcnt = 0;  

  44.             Set<String> set = new HashSet<String>();  

  45.             while((temp=reader.readLine())!=null){  

  46.                 temp = temp.trim();  

  47.                 if (temp.startsWith(TAG_START_CONTENT)) {  

  48.                     int end = temp.indexOf(TAG_END_CONTENT);  

  49.                     String content = temp.substring(TAG_START_CONTENT.length(), end);  

  50.                     //System.out.println(content);  

  51.                     if (content.length() > 0) {  

  52.                         allCount += content.length() ;  

  53.                         List<Term> result = ToAnalysis.parse(content);  

  54.                         for (Term term: result) {  

  55.                             String item = term.getName().trim();  

  56.                             if (item.length() > 0) {  

  57.                                 termcnt++;  

  58.                                 pw.print(item.trim() + " ");  

  59.                                 set.add(item);  

  60.                             }  

  61.                         }  

  62.                         pw.println();  

  63.                     }  

  64.                 }  

  65.             }  

  66.             long end = System.currentTimeMillis() ;  

  67.             System.out.println("共" + termcnt + "个term," + set.size() + "个不同的词,共 "  

  68.                     +allCount+" 个字符,每秒处理了:"+(allCount*1000.0/(end-start)));  

  69.         } catch (IOException e) {   

  70.             e.printStackTrace();  

  71.         } finally {  

  72.             if (null != reader) {  

  73.                 try {  

  74.                     reader.close();  

  75.                 } catch (IOException e) {  

  76.                     e.printStackTrace();  

  77.                 }  

  78.             }  

  79.             if (null != pw) {  

  80.                 pw.close();  

  81.             }  

  82.         }  

  83.     }  

  84. }  


经过对新闻内容分词之后,得到的输出文件resultbig.txt有2.2G,其中的格式如下:



这个文件就是word2vec工具的输入文件


3、本地运行word2vec进行分析

首先要做的肯定是从官网上下载word2vec的源码:http://word2vec.googlecode.com/svn/trunk/ ,然后把其中makefile文件的.txt后缀去掉,在终端下执行make操作,这时能发现word2vec文件夹下多了好几个东西。接下来就是输入resultbig.txt进行分析了:


  1. ./word2vec -train resultbig.txt -output vectors.bin -cbow 0 -size 200 -window 5 -negative 0 -hs 1 -sample 1e-3 -threads 12 -binary 1  


这里我们指定输出为vectors.bin文件,显然输出到文件便于以后重复利用,省得每次都要计算一遍,要知道处理这2.2G的词集合需要接近半个小时的时间:





下面再输入计算距离的命令即可计算与每个词最接近的词了:


[plain] view plain copy print?

  1. ./distance vectors.bin  


这里列出一些有意思的输出:






怎么样,是不是觉得还挺靠谱的?补充一点,由于word2vec计算的是余弦值,距离范围为0-1之间,值越大代表这两个词关联度越高,所以越排在上面的词与输入的词越紧密。

至于聚类,只需要另一个命令即可:



  1. ./word2vec -train resultbig.txt -output classes.txt -cbow 0 -size 200 -window 5 -negative 0 -hs 1 -sample 1e-3 -threads 12 -classes 500  


按类别排序:



  1. sort classes.txt -k 2 -n > classes.sorted.txt  



后记:如果想要了解word2vec的实现原理,应该读一读官网后面的三篇参考文献。显然,最主要的应该是这篇: Distributed Representations of Words and Phrases and their Compositionality  

https://arxiv.org/pdf/1310.4546.pdf


这篇文章的基础是 Natural Language Processing (almost) from 

Scratch 

http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en//pubs/archive/35671.pdf


其中第四部分提到了把deep learning用在NLP上。

最后感谢晓阳童鞋向我提到这个工具,不愧是立志要成为NLP专家的人。


附:一个在线测试的网站,貌似是一位清华教授做的:http://cikuapi.com/index.php



人工智能大数据与深度学习

搜索添加微信公众号:weic2c


长按图片,识别二维码,点关注



大数据挖掘DT数据分析

搜索添加微信公众号:datadw


教你机器学习,教你数据挖掘


长按图片,识别二维码,点关注


登录查看更多
4

相关内容

分散式表示即将语言表示为稠密、低维、连续的向量。 研究者最早发现学习得到词嵌入之间存在类比关系。比如apple−apples ≈ car−cars, man−woman ≈ king – queen 等。这些方法都可以直接在大规模无标注语料上进行训练。词嵌入的质量也非常依赖于上下文窗口大小的选择。通常大的上下文窗口学到的词嵌入更反映主题信息,而小的上下文窗口学到的词嵌入更反映词的功能和上下文语义信息。
【实用书】学习用Python编写代码进行数据分析,103页pdf
专知会员服务
194+阅读 · 2020年6月29日
深度学习自然语言处理概述,216页ppt,Jindřich Helcl
专知会员服务
212+阅读 · 2020年4月26日
【Amazon】使用预先训练的Transformer模型进行数据增强
专知会员服务
56+阅读 · 2020年3月6日
【干货】用BRET进行多标签文本分类(附代码)
专知会员服务
84+阅读 · 2019年12月27日
ExBert — 可视化分析Transformer学到的表示
专知会员服务
31+阅读 · 2019年10月16日
几种句子表示方法的比较
AINLP
15+阅读 · 2019年9月21日
在Python中使用SpaCy进行文本分类
专知
24+阅读 · 2018年5月8日
实践 | 使用fasttext进行文档分类
黑龙江大学自然语言处理实验室
7+阅读 · 2018年4月29日
word2vec在工业界的应用场景
全球人工智能
5+阅读 · 2018年1月7日
情感分析的新方法,使用word2vec对微博文本进行情感分析和分类
数据挖掘入门与实战
22+阅读 · 2018年1月6日
【干货】--基于Python的文本情感分类
R语言中文社区
5+阅读 · 2018年1月5日
基于典型相关分析的词向量
AI研习社
7+阅读 · 2017年12月24日
情感分析:数据采集与词向量构造方法
北京思腾合力科技有限公司
29+阅读 · 2017年12月20日
京东商品评论情感分析:数据采集与词向量构造方法
数据挖掘入门与实战
5+阅读 · 2017年12月19日
Arxiv
3+阅读 · 2018年11月14日
Arxiv
3+阅读 · 2018年2月22日
VIP会员
相关资讯
几种句子表示方法的比较
AINLP
15+阅读 · 2019年9月21日
在Python中使用SpaCy进行文本分类
专知
24+阅读 · 2018年5月8日
实践 | 使用fasttext进行文档分类
黑龙江大学自然语言处理实验室
7+阅读 · 2018年4月29日
word2vec在工业界的应用场景
全球人工智能
5+阅读 · 2018年1月7日
情感分析的新方法,使用word2vec对微博文本进行情感分析和分类
数据挖掘入门与实战
22+阅读 · 2018年1月6日
【干货】--基于Python的文本情感分类
R语言中文社区
5+阅读 · 2018年1月5日
基于典型相关分析的词向量
AI研习社
7+阅读 · 2017年12月24日
情感分析:数据采集与词向量构造方法
北京思腾合力科技有限公司
29+阅读 · 2017年12月20日
京东商品评论情感分析:数据采集与词向量构造方法
数据挖掘入门与实战
5+阅读 · 2017年12月19日
Top
微信扫码咨询专知VIP会员