Word2VEC_java 是孙健(ansj)编写的一个谷歌 word2vec 的 java 实现版本,同时支持读取由谷歌 c 语言版 word2vec 训练产生的模型。Word2Vec 则是对其的进一步包装,同时实现了常用的词语相似度和句子相似度计算。
Word2Vec 同时支持加载谷歌模型和 Java 模型,分别使用 loadGoogleModel()
和 loadJavaModel()
函数读取。关于如何训练模型,请见训练 word2vec 模型。
Word2Vec vec = new Word2Vec();
try {
vec.loadGoogleModel("data/wiki_chinese_word2vec(Google).model");
} catch (IOException e) {
e.printStackTrace();
}
Word2Vec 提供了简单的词语相似度计算方法,可以直接调用 wordSimilarity()
函数计算两个词语的相似度,也可以通过 getSimilarWords()
函数获取与指定词语相似的词语。
//计算词语相似度
System.out.println("狗|猫: " + vec.wordSimilarity("狗", "猫"));
System.out.println("计算机|电脑: " + vec.wordSimilarity("计算机", "电脑"));
System.out.println("计算机|人: " + vec.wordSimilarity("计算机", "人"));
//获取相似的词语
Set<WordEntry> similarWords = vec.getSimilarWords("漂亮", 10);
for(WordEntry word : similarWords) {
System.out.println(word.name + " : " + word.score);
}
狗|猫: 0.71021223
计算机|电脑: 0.64130974
计算机|人: 0.060623944
//与"漂亮"语义相似的前10个词语:
可爱 : 0.7255844
时髦 : 0.68324685
脸蛋 : 0.6748609
打扮 : 0.6430359
乖巧 : 0.6370341
迷人 : 0.63440853
甜美 : 0.6340918
温柔 : 0.63337386
爽朗 : 0.63315964
聪明 : 0.6319053
Word2Vec 还提供了计算句子相似度的方法 fastSentenceSimilarity()
和 sentenceSimilarity()
,输入是两个分好词的句子(即两个词语列表),还支持自定义每个词语在相似度计算中的权值(默认所有词语权值为1)。
为了方便测试,Word2Vec 对 Ansj中文分词 进行了包装,提供了一个简易的分词工具类 Segment
,用来获取分词后的词语列表和词性列表。在实际使用中,也可以使用自己的分词工具(比如 Ansj中文分词、斯坦福NLP、哈工大语言技术平台、中科院分词系统、HanLP 等)。
String s1 = "苏州有多条公路正在施工,造成局部地区汽车行驶非常缓慢。";
String s2 = "苏州最近有多条公路在施工,导致部分地区交通拥堵,汽车难以通行。";
String s3 = "苏州是一座美丽的城市,四季分明,雨量充沛。";
//分词,获取词语列表
List<String> wordList1 = Segment.getWords(s1);
List<String> wordList2 = Segment.getWords(s2);
List<String> wordList3 = Segment.getWords(s3);
//快速句子相似度
System.out.println("快速句子相似度:");
System.out.println("s1|s1: " + vec.fastSentenceSimilarity(wordList1, wordList1));
System.out.println("s1|s2: " + vec.fastSentenceSimilarity(wordList1, wordList2));
System.out.println("s1|s3: " + vec.fastSentenceSimilarity(wordList1, wordList3));
//句子相似度(所有词语权值设为1)
System.out.println("s1|s1: " + vec.sentenceSimilarity(wordList1, wordList1));
System.out.println("s1|s2: " + vec.sentenceSimilarity(wordList1, wordList2));
System.out.println("s1|s3: " + vec.sentenceSimilarity(wordList1, wordList3));
//句子相似度(名词、动词权值设为1,其他设为0.8)
float[] weightArray1 = Segment.getPOSWeightArray(Segment.getPOS(s1));
float[] weightArray2 = Segment.getPOSWeightArray(Segment.getPOS(s2));
float[] weightArray3 = Segment.getPOSWeightArray(Segment.getPOS(s3));
System.out.println("s1|s1: " + vec.sentenceSimilarity(wordList1, wordList1, weightArray1, weightArray1));
System.out.println("s1|s2: " + vec.sentenceSimilarity(wordList1, wordList2, weightArray1, weightArray2));
System.out.println("s1|s3: " + vec.sentenceSimilarity(wordList1, wordList3, weightArray1, weightArray3));
//快速句子相似度
s1|s1: 1.0000006
s1|s2: 0.9144124
s1|s3: 0.6289892
//句子相似度:
s1|s1: 1.0
s1|s2: 0.7888574
s1|s3: 0.4520114
//句子相似度(名词、动词权值设为1,其他设为0.8):
s1|s1: 1.0
s1|s2: 0.7922064
s1|s3: 0.45209178
注意: 加载不同的 word2vec 模型,计算相似度的结果也不同。
Word2VEC_java 实现了 java 下的 word2vec 模型训练,Word2Vec 对其封装,也提供了相应的调用接口:
void trainJavaModel(String trainFilePath, String modelFilePath)
- trainFilePath: 训练文件路径
- modelFilePath: 模型文件路径
trainJavaModel 为静态函数,可以直接调用:
try {
Word2Vec.trainJavaModel("data/train.txt", "data/test.model");
} catch (IOException e) {
e.printStackTrace();
}
Google 实现的 C 语言版的 word2vec 是目前公认的准确率最高的 word2vec 版本,因而训练更推荐直接使用 google 的原版。ansj 实现的 java 版也支持训练模型,但是准确率未和 Google 版做过比较。
下面提供两个 GitHub 上克隆的 Google word2vec 项目:
下载后使用 make
命令编译,之后使用编译出的 word2vec 来训练模型:
./word2vec -train $TEXT_DATA -output $VECTOR_DATA -cbow 0 -size 200 -window 5 -negative 0 -hs 1 -sample 1e-3 -threads 12 -binary 1
简单说明一下:
TEXT_DATA
为训练文本文件路径,词之间使用空格分隔;VECTOR_DATA
为输出的模型文件;不使用 cbow 模型,默认为 Skip-Gram 模型;每个单词的向量维度是 200;训练的窗口大小为 5;不使用 NEG 方法,使用 HS 方法;-sampe
指的是采样的阈值,如果一个词语在训练样本中出现的频率越大,那么就越会被采样;-binary
为 1 指的是结果二进制存储,为 0 是普通存储。
详情请见 Word2Vector 模型,可以下载训练好的 Google 版模型及对应的训练语料。
如果想对最新的维基百科中文语料进行处理,可以参考《维基百科中文语料库词向量的训练:处理维基百科中文语料》。
Word2Vec 也提供了 Python 的实现版本(需要安装 gensim 依赖包),只需下载 Word2Vec.py,然后 from Word2Vec import Word2Vec
引入项目即可:
from Word2Vec import Word2Vec
w2v = Word2Vec('/Users/jim/Desktop/wiki_chinese_word2vec.model', kind='bin')
print('狗|猫: ', w2v.word_similarity('狗', '猫'))
print('计算机|电脑: ', w2v.word_similarity('计算机', '电脑'))
print('计算机|人: ', w2v.word_similarity('计算机', '人'))
详细示例可以参见 test.py。