使用DL4J读取词向量并计算语义相似度
2018-01-16 13:46
3531 查看
使用DL4J读取词向量并计算单词语义相似度
By 龙前尘
实验环境:WINDOWS 8、Java-1.8.0_25、DL4J-0.9.1、ND4J-0.9.1
转载请注明地址:
http://blog.csdn.net/svenhuayuncheng/article/details/79073883
笔者按
在将词向量用于语义相似度计算时,如笔者前文所述:Windows系统下使用维基百科中文语料训练Word2Vec词向量,笔者已经利用Gensim训练好了词向量。由于笔者的项目工程是基于Java编写的,故需要找到相关的Java类库来读取词向量。经过一番查询,笔者锁定了DL4J(Deeplearning for Java)这个库,下文即使用DL4J来读取词向量的方法,以及笔者踩到的坑。
DeepLearning4J(DL4J)是一套基于Java语言的神经网络工具包,可以构建、定型和部署神经网络。DL4J与Hadoop和Spark集成,支持分布式CPU和GPU,为商业环境(而非研究工具目的)所设计。Skymind是DL4J的商业支持机构。
Deeplearning4j拥有先进的技术,以即插即用为目标,通过更多预设的使用,避免多余的配置,让非企业也能够进行快速的原型制作。DL4J同时可以规模化定制。DL4J遵循Apache 2.0许可协议,一切以其为基础的衍生作品均属于衍生作品的作者。
Deeplearning4j包括了分布式、多线程的深度学习框架,以及普通的单线程深度学习框架。定型过程以集群进行,也就是说,Deeplearning4j可以快速处理大量数据。神经网络可通过[迭代化简]平行定型,与 Java、 Scala 和 Clojure 均兼容。
DL4J使用了ND4J来做矩阵计算,在配置时,也必须要配置ND4J,否则会报错。
ND4J配置如下:
本文主要针对于第二种词向量文件的读取与操作。
首先为读取词向量文件,代码如下:
读取文件后,可以将Word2vec作为查询表使用:
如果遇到未登录词,Word2vec返回一个全零向量。
试一试效果:
报错如下图所示:
该错误是堆外内存溢出导致。
这是由于DL4J使用了ND4J,该模块使用off-heap(堆外内存)来存储NDArray,并且对于原生代码(如BLAS、CUDA库)可以提供更好的性能2.
off-heap堆外内存指不由JVM维护的内存空间,故JVM的垃圾回收机制也不会管理对堆外内存。在JVM中,ND4J会维护指向堆外内存的指针,可以通过JNI将这些指针传递到ND4J底层的C++代码中,来完成ND4J操作。
为了维护内存空间的分配,ND4J使用了两种方法:
第一是通过JVM与弱引用追踪方法(WeakReference tracking);
第二是通过内存工作空间管理(MemoryWorkspaces)。
这两种方法的核心思想是一样的:即当一个INDArray数组被垃圾回收后,其对应的堆外内存应该被释放,并重新分配该内存空间。GC与MemoryWorkspaces不同之处在于何时、如何释放内存。
对于JVM,当INDArray数组被作为垃圾回收时,其对应的堆外内存被释放;
对于MemoryWorkspaces,当一个INDArray数组离开工作空间的范围时,比如,当神经网络中的一层已经完成了前馈传递,其内存可能会被重用,故不进行内存释放或重分配。这样对于循环神经网络来说性能更佳。
所以,无论用什么方法,在DL4J/ND4J中,有两种类型的内存限制都需要显示配置。堆内(on-heap)JVM内存,以及NDArray数组所在的堆外(off-heap)内存,都需要设置内存限制。
设置如下:
-Xms
-Xmx
-Dorg.bytedeco.javacpp.maxbytes
-Dorg.bytedeco.javacpp.maxphysicalbytes
例如,设置堆内内存初始大小为1G,最大堆内内存为2G,最大堆外内存为8G,则有:
在IntelliJ IDEA中,需要在Run->Edit Configurations中设置VM参数。
设置如下图所示:
如此设置后,问题解决。
该问题是由于操作系统无法加载某些必要的类库导致。这里可以使用Dependency Walker来解决问题。
1、 首先下载类库:Dependency Walker 2.2 for x64,并解压。
2、 引入类包:
3、在main()方法之前,或者在初始化对象之前,插入以下代码。
由此,解决了使用main方法运行程序出错的问题。
以上,完成了使用DL4J读取词向量的全过程。
本文旨在做一个实验记录,也是抛砖引玉,欢迎大家共同探讨!
https://deeplearning4j.org/cn/index。 ↩
https://deeplearning4j.org/memory。 ↩
By 龙前尘
实验环境:WINDOWS 8、Java-1.8.0_25、DL4J-0.9.1、ND4J-0.9.1
转载请注明地址:
http://blog.csdn.net/svenhuayuncheng/article/details/79073883
笔者按
在将词向量用于语义相似度计算时,如笔者前文所述:Windows系统下使用维基百科中文语料训练Word2Vec词向量,笔者已经利用Gensim训练好了词向量。由于笔者的项目工程是基于Java编写的,故需要找到相关的Java类库来读取词向量。经过一番查询,笔者锁定了DL4J(Deeplearning for Java)这个库,下文即使用DL4J来读取词向量的方法,以及笔者踩到的坑。
1. 何为DL4J
本文节选自DL4J官网1。DeepLearning4J(DL4J)是一套基于Java语言的神经网络工具包,可以构建、定型和部署神经网络。DL4J与Hadoop和Spark集成,支持分布式CPU和GPU,为商业环境(而非研究工具目的)所设计。Skymind是DL4J的商业支持机构。
Deeplearning4j拥有先进的技术,以即插即用为目标,通过更多预设的使用,避免多余的配置,让非企业也能够进行快速的原型制作。DL4J同时可以规模化定制。DL4J遵循Apache 2.0许可协议,一切以其为基础的衍生作品均属于衍生作品的作者。
Deeplearning4j包括了分布式、多线程的深度学习框架,以及普通的单线程深度学习框架。定型过程以集群进行,也就是说,Deeplearning4j可以快速处理大量数据。神经网络可通过[迭代化简]平行定型,与 Java、 Scala 和 Clojure 均兼容。
2. 配置POM文件
DL4J配置如下:<!-- https://mvnrepository.com/artifact/org.deeplearning4j/deeplearning4j-core --> <dependency> <groupId>org.deeplearning4j</groupId> <artifactId>deeplearning4j-core</artifactId> <version>0.9.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.deeplearning4j/deeplearning4j-nlp --> <dependency> <groupId>org.deeplearning4j</groupId> <artifactId>deeplearning4j-nlp</artifactId> <version>0.9.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.nd4j/nd4j-native-platform -->
DL4J使用了ND4J来做矩阵计算,在配置时,也必须要配置ND4J,否则会报错。
ND4J配置如下:
<!-- https://mvnrepository.com/artifact/org.nd4j/nd4j-native-platform --> <dependency> <groupId>org.nd4j</groupId> <artifactId>nd4j-native-platform</artifactId> <version>0.9.1</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.nd4j/nd4j-native --> <dependency> <groupId>org.nd4j</groupId> <artifactId>nd4j-native</artifactId> <version>0.9.1</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.nd4j/nd4j-api --> <dependency> <groupId>org.nd4j</groupId> <artifactId>nd4j-api</artifactId> <version>0.9.1</version> </dependency>
3. 使用DL4J读取词向量
DL4J可以读取使用DL4J训练出的词向量,也可以读取使用Gensim训练出的词向量vector文件,此外,对于谷歌训练好的谷歌新闻语料模型GoogleNews-vectors-negative300.bin,也可以读取。本文主要针对于第二种词向量文件的读取与操作。
首先为读取词向量文件,代码如下:
Word2Vec word2Vec = WordVectorSerializer.readWord2VecModel("wiki.zh.text.vector");
读取文件后,可以将Word2vec作为查询表使用:
WeightLookupTable weightLookupTable = word2Vec.lookupTable(); Iterator<INDArray> vectors = weightLookupTable.vectors(); INDArray wordVectorMatrix = word2Vec.getWordVectorMatrix("农业"); double[] wordVector = word2Vec.getWordVector("农业");
如果遇到未登录词,Word2vec返回一个全零向量。
试一试效果:
Collection<String> lst = vec.wordsNearest("计算机", 10); System.out.println(lst); double cosSim = vec.similarity("农业", "计算机"); System.out.println(cosSim); for(Double d : wordVector) System.out.println(d);
4. 踩过的坑
4.1 堆外内存溢出问题
读取词向量的代码很简单,但是仍然遇到问题。报错如下图所示:
该错误是堆外内存溢出导致。
这是由于DL4J使用了ND4J,该模块使用off-heap(堆外内存)来存储NDArray,并且对于原生代码(如BLAS、CUDA库)可以提供更好的性能2.
off-heap堆外内存指不由JVM维护的内存空间,故JVM的垃圾回收机制也不会管理对堆外内存。在JVM中,ND4J会维护指向堆外内存的指针,可以通过JNI将这些指针传递到ND4J底层的C++代码中,来完成ND4J操作。
为了维护内存空间的分配,ND4J使用了两种方法:
第一是通过JVM与弱引用追踪方法(WeakReference tracking);
第二是通过内存工作空间管理(MemoryWorkspaces)。
这两种方法的核心思想是一样的:即当一个INDArray数组被垃圾回收后,其对应的堆外内存应该被释放,并重新分配该内存空间。GC与MemoryWorkspaces不同之处在于何时、如何释放内存。
对于JVM,当INDArray数组被作为垃圾回收时,其对应的堆外内存被释放;
对于MemoryWorkspaces,当一个INDArray数组离开工作空间的范围时,比如,当神经网络中的一层已经完成了前馈传递,其内存可能会被重用,故不进行内存释放或重分配。这样对于循环神经网络来说性能更佳。
所以,无论用什么方法,在DL4J/ND4J中,有两种类型的内存限制都需要显示配置。堆内(on-heap)JVM内存,以及NDArray数组所在的堆外(off-heap)内存,都需要设置内存限制。
设置如下:
-Xms
当应用开始时,分配给应用的初始JVM堆的大小;
-Xmx
分配给应用的最大JVM堆的大小;
-Dorg.bytedeco.javacpp.maxbytes
堆外内存大小;
-Dorg.bytedeco.javacpp.maxphysicalbytes
同样为设置堆外内存的,应该设置地与maxbytes大小一样;
例如,设置堆内内存初始大小为1G,最大堆内内存为2G,最大堆外内存为8G,则有:
-Xms1G -Xmx2G -Dorg.bytedeco.javacpp.maxbytes=8G -Dorg.bytedeco.javacpp.maxphysicalbytes=8G
在IntelliJ IDEA中,需要在Run->Edit Configurations中设置VM参数。
设置如下图所示:
如此设置后,问题解决。
4.2 使用main函数缺少ND4J类库的问题
在WINDOWS操作系统下,用main函数读取词向量文件时,可能会遇到以下错误:Exception in thread "main" java.lang.ExceptionInInitializerError at org.deeplearning4j.nn.conf.NeuralNetConfiguration$Builder.seed(NeuralNetConfiguration.java:624) at org.deeplearning4j.examples.feedforward.anomalydetection.MNISTAnomalyExample.main(MNISTAnomalyExample.java:46) Caused by: java.lang.RuntimeException: org.nd4j.linalg.factory.Nd4jBackend$NoAvailableBackendException: Please ensure that you have an nd4j backend on your classpath. Please see: http://nd4j.org/getstarted.html at org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5556) at org.nd4j.linalg.factory.Nd4j.(Nd4j.java:189) ... 2 more Caused by: org.nd4j.linalg.factory.Nd4jBackend$NoAvailableBackendException: Please ensure that you have an nd4j backend on your classpath. Please see: http://nd4j.org/getstarted.html at org.nd4j.linalg.factory.Nd4jBackend.load(Nd4jBackend.java:259) at org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5553) ... 3 more
该问题是由于操作系统无法加载某些必要的类库导致。这里可以使用Dependency Walker来解决问题。
1、 首先下载类库:Dependency Walker 2.2 for x64,并解压。
2、 引入类包:
import org.bytedeco.javacpp.Loader; import org.nd4j.nativeblas.Nd4jCpu;
3、在main()方法之前,或者在初始化对象之前,插入以下代码。
try { Loader.load(Nd4jCpu.class); } catch (UnsatisfiedLinkError e) { String path = Loader.cacheResource(Nd4jCpu.class, "windows-x86_64/jniNd4jCpu.dll").getPath(); new ProcessBuilder("c:/path/to/depends.exe", path).start().waitFor(); }
由此,解决了使用main方法运行程序出错的问题。
以上,完成了使用DL4J读取词向量的全过程。
本文旨在做一个实验记录,也是抛砖引玉,欢迎大家共同探讨!
https://deeplearning4j.org/cn/index。 ↩
https://deeplearning4j.org/memory。 ↩
相关文章推荐
- 使用颜色分布法计算图像相似度
- 词语相似度计算:1、安装NLTK和下载WordNet语料库;WordNet的使用
- 2017年计算语义相似度最新论文,击败了siamese lstm,非监督学习
- Ubuntu上使用gensim计算文档间的相似度
- [转]开源Math.NET基础数学类库使用(02)矩阵向量计算
- 转载:基于《知网》的词汇语义相似度计算
- WordNet词网研究7——之JWS(Java Wordnet Similarity)语义相似度计算
- WordNet词网研究7——之JWS(Java Wordnet Similarity)语义相似度计算
- 深度学习解决NLP问题:语义相似度计算
- 基于深度学习的人脸识别系统系列——使用CUBLAS加速计算人脸向量的余弦距离
- 使用spark计算文档相似度
- 使用向量的方法计算点到直线的距离
- 使用spark TF-IDF特征计算文章间相似度
- [转]向量空间模型(VSM)在文档相似度计算上的简单介绍
- 使用Gensim建立bow TFIDF LSI模型对文本相似度计算
- iOS:使用莱文斯坦距离算法计算两串字符串的相似度
- Lucene in action 笔记 term vector——针对特定field建立的词频向量空间,不存!不会!影响搜索,其作用是告诉我们搜索结果是“如何”匹配的,用以提供高亮、计算相似度,在VSM模型中评分计算
- 使用PHP similar text计算两个字符串相似度
- 新手学信息检索4:向量空间模型与相似度计算
- WMD:基于词向量的文档相似度计算