1、简介
Word2Vec是 Google 在 2013 年年中开源的一款将词表征为实数值向量的高效工具, 其利用深度学习的思想,可以通过训练,把对文本内容的处理简化为 K 维向量空间中的向量运算,而向量空间上的相似度可以用来表示文本语义上的相似度。
Word2vec输出的词向量一般为50维或100维,这种向量被表示成这个样子[0.11212,0.116545,0.878789,0.5644659,……]。这种词向量可以被用来做很多 NLP 相关的工作,比如聚类、找同义词、词性分析、计算文档相似度计算等等。
word2vec官网地址看这里:https://code.google.com/p/word2vec/
word2vec java版本的一个实现:GitHub - NLPchina/Word2VEC_java: word2vec java版本的一个实现
2、训练
2.1 寻找语料
要做NLP,第一步肯定是根据自己情况准备语料库。笔者准备的是关于交通相关的,通过爬虫爬取的公开语料,大约17W+条(938MB):
2.2 语料预处理
第一步:分词
笔者采用的是ANSJ分词,相关调用见开源中文分词Ansj的简单使用-CSDN博客
第二步:过滤
过滤掉一些常用的停用词、标点符号等。
第三步:保存
词语间用空格隔开,一篇语料占据一行。
预处理代码:
public static void executeWord2VecTxt(String trainPath,String resultPath) {
try {
BufferedReader br = IOUtil.getReader(trainPath, IOUtil.UTF8);
FileOutputStream fos = new FileOutputStream(resultPath);
String line;
int j = 0;
while ((line = br.readLine()) != null) {
System.out.println("文章ID:" + j);
JSONObject json = JSONObject.parseObject(line);
String text = json.getString("text");
List<Term> terms= ToAnalysis.parse(title) ;
//分词过滤,自己实现
StopWord.cleanerPAS(listWods);
StopWord.filter(listWods);
StringBuilder sb = new StringBuilder() ;
for (Term term : terms) {
sb.append(term.getName()) ;
sb.append(" ");
}
fos.write(sb.toString().getBytes()); ;
fos.write("\n".getBytes());
j++;
}
} catch (Exception e) {
e.printStackTrace();
}
}
2.3 训练模型
可以直接选择默认设置进行训练,也可以自己进行参数调整,常见参数如下:
- layerSize表示词向量维数:默认200,一般取100-300左右,经验是不超过1000
- window 上下文窗口大小,cbow一般都是5,如果是Skip-Gram的话,最好是10
- sample 表示采样参数,是一个经验忽视掉频率过高的词的参数,一般为1e-3,最小一般为1e-5
- alpha设置学习速率,默认的为0.025
- cbow false表示不使用cbow模型,默认为Skip-Gram模型
训练代码:
Learn learn = new Learn();
learn.learnFile(new File("E:\\home\\data\\word2VecTrainTxt.txt"));
learn.saveModel(new File("E:\\home\\data\\javaModel.vec"));
训练过程日志输出:
alpha:0.025 Progress: 0%
alpha:0.024997122711267163 Progress: 0%....
alpha:7.495035335541856E-6 Progress: 99%
alpha:4.677829846444493E-6 Progress: 99%
Vocab size: 636198
Words in train file: 89459217
sucess train over!
4224675Process finished with exit code 0
2.4 word2vec调用
初始化:
Word2VEC vec = new Word2VEC();
vec.loadJavaModel("E:\\home\\data\\javaModel.vec");
找近义词:
System.out.println(vec.distance("地铁"));
结果日志输出:
[1号线 0.8300631,
2号线 0.8268978,
5号线 0.7992573,
11号线 0.79095393,
6号线 0.7803578,
10号线 0.77783144,
4号线 0.77761006,
8号线 0.7738936,
7号线 0.75981987,
3号线 0.7417199,
12号线 0.73901767,
260座 0.7323471,
13号线 0.72736794,
14号线 0.72281486,
18号线 0.7186287,
北延| 0.71449405,
9号线 0.71415234,
三叉街 0.71413624,
潘水站 0.71285397,
水澄桥 0.70943874,
候潮门 0.70908654,
龙阳路 0.7077574,
口出 0.6974327,
金吉路站 0.6950388,
换乘 0.69367176,
方湾街 0.6933061,
惠昌路 0.6904804,
广兰路站 0.69042003,
红霞方 0.68959075,
金小郢 0.68952847,
莲花北 0.68823016,
唐宫西 0.68511003,
虹桥火车站 0.6848812,
地铁站 0.6843677,
陶然桥 0.68419755,
狮子坪 0.683676,
达静安 0.6815519,
15号线 0.6787948,
昌岗 0.6781647]
计算余弦相似度:
System.out.println("7号线:地铁" + "\t" + Distance.cosin(vec.getWordVector("7号线"), vec.getWordVector("地铁")));
System.out.println("7号线:公寓" + "\t" + Distance.cosin(vec.getWordVector("7号线"), vec.getWordVector("公寓")));
System.out.println("地铁:公寓" + "\t" + Distance.cosin(vec.getWordVector("地铁"), vec.getWordVector("公寓")));
结果日志输出:
7号线:地铁 0.75982
7号线:公寓 0.17022026
地铁:公寓 0.083744526
3、应用
Word2vec 有很多应用场景,可以用它来生成特征,输入到各种算法模型中,例如:自动摘要、语音识别、自动问答、音乐视频推荐系统等。