WordNet--JWI( the MIT Java Wordnet Interface) 获取信息

首先要从http://wordnet.princeton.edu/上下载WordNet,支持Windows系统的最新版本是WordNet2.1,是可执行文件,下载之后双击安装就可以了,记住安装目录,以后会用到。我的安装目录是C:/Program Files/WordNet/2.1。

然后下载MIT Java WordNet Interface,下载地址如下http://www.mit.edu/~markaf/prj/jwi/,我下载的版本是2.1.4,下载之后解压,会发现有一个 edu.mit.jwi_2.1.4_jdk的jar包。

现在准备工作已经做完了,除非你的机器还没有安装JDK或Eclipse,因为这两者是需要的,至少JDK是需要的。接下来打开Eclipse,创建一个新的Java Project,然后右键点击你的Project,在Build Path-->Configue Build Path...-->Java Build Path-->Libraries-->Add External Jars...选择刚才的edu.mit.jwi_2.1.4_jdk,这样你的Project里就包含了这个MIT的Library了。然后回到桌面右键点击“我的电脑”-->“属性”-->“高级”-->"环境变量",在系统变量中添加一个叫做WNHOME的变量,值就是你刚才安装WordNet的安装目录,我这里的值就是C:/Program Files/WordNet/2.1。这样做的目的一会儿就会明白。

重新启动Eclipse,在你的Project里建立一个新的包,在包里新建一个Java文件,内容如下:

package wordnettest;

import java.io.*;
import java.net.*;
import edu.mit.jwi.Dictionary;
import edu.mit.jwi.IDictionary;
import edu.mit.jwi.item.*;

 


public class hiwordnet {

 public static void main(String[] args) throws IOException {
  //建立指向WordNet词典目录的URL。
    String wnhome = System.getenv("WNHOME");
    String path = wnhome + File.separator + "dict";
    URL url=null;
    try{
     url = new URL("file", null, path);
    }
    catch(MalformedURLException e){
     e.printStackTrace();
    }
    if(url == null)
        return;
  //建立词典对象并打开它。
    IDictionary dict = new Dictionary(url);
   
    dict.open();

  //查询dog这个词的第一种意思。
    IIndexWord idxWord = dict.getIndexWord("enough", POS.ADVERB);
    IWordID wordID = (IWordID)idxWord.getWordIDs().get(0);
    IWord word = dict.getWord(wordID);
    System.out.println("Id = " + wordID);
    System.out.println("Lemma 词元 = " + word.getLemma());
    System.out.println("Gloss注解 = " + word.getSynset().getGloss());

   }


 
}

 

看过以上的代码就应该知道刚才添加WNHOME这个系统变量的意图了,就是为了在程序中使用WordNet的字典。现在运行这个Java程序,可得结果下:

Id = WID-00146900-R-??-enough
Lemma = enough
Gloss = as much as necessary; "Have I eaten enough?"; (`plenty' is nonstandard) "I've had plenty, thanks"


二、JWI装载WordNet到内存的遍历性能优化:

JWI2.2.x系列一个新的特点是可以将WordNet装载到内存中,这一举措大大的改善了遍历WordNet的性能。其中实现该功能的是,JWI的edu.mit.jwi.RAMDictionary类,该类可以设定是否将WordNet装入内存。

写一个遍历WordNet的函数trek(),对使用RAMDictionary来打开WordNet,对不装载入内存和装载入内存进行比较;

package wordnettest;
//JWI的edu.mit.jwi.RAMDictionary类,该类可以设定是否将WordNet装入内存。
//写一个遍历WordNet的函数trek(),对使用RAMDictionary来打开WordNet,对不装载入内存和装载入内存进行比较;


import java.io.File;
import java.io.IOException;
import java.util.Iterator;

import edu.mit.jwi.IDictionary;
import edu.mit.jwi.IRAMDictionary;
import edu.mit.jwi.RAMDictionary;
import edu.mit.jwi.data.ILoadPolicy;
import edu.mit.jwi.item.IIndexWord;
import edu.mit.jwi.item.IWordID;
import edu.mit.jwi.item.POS;


public class classramdictionaryTest {

  public static void main(String[] args ) throws IOException, Exception{
       String wnhome = System.getenv("WNHOME"); //获取环境变量WNHOM
        String path = wnhome + File.separator+ "dict";
        File wnDir=new File(path);
        testRAMDictionary(wnDir);
     }

     public static void testRAMDictionary(File wnDir) throws IOException, InterruptedException{

        IRAMDictionary dict=new RAMDictionary(wnDir, ILoadPolicy.NO_LOAD);
        dict.open();
        //周游WordNet
        System.out.print("没装载前:\n");
        trek(dict);
        //now load into memor
        System.out.print("\nLoading Wordnet into memory...");
        long t=System.currentTimeMillis();
        dict.load(true);
        System.out.printf("装载时间:done(%1d msec)\n", System.currentTimeMillis()-t);

        //装载后在周游

        System.out.print("\n装载后:\n");
        trek(dict);
     } 

     /*

      * this method is Achieved to trek around the WordNet

      */

     public static void trek(IDictionary dict){
        int tickNext=0;
        int tickSize=20000;
        int seen=0;
        System.out.print("Treking across Wordnet");
        long t=System.currentTimeMillis();
        for(POS pos:POS.values()){ //遍历所有词性
            for(Iterator i=dict.getIndexWordIterator(pos);i.hasNext();){

               //遍历某一个词性的所有索引
               for(IWordID wid:i.next().getWordIDs()){
                   //遍历每一个词的所有义项
                   seen+=dict.getWord(wid).getSynset().getWords().size();//获取某一个synsets所具有的词

                   if(seen>tickNext){
                      System.out.print(".");
                      tickNext=seen + tickSize;

                   }

               }

            }

        } 

        System.out.printf("done (%1d msec)\n",System.currentTimeMillis()-t);
        System.out.println("In my trek I saw "+ seen + " words");

     }


    
}

 

 

 

执行的效果为:

没装载前

Treking across Wordnet...........................done (3765 msec)

In my trek I saw 523260 words

Loading Wordnet into memory...装载时间:done(10625 msec)

装载后:

Treking across Wordnet...........................done (328 msec)

In my trek I saw 523260 words

由结果可见,不装如内存的周游WordNet的时间为3765 ms,而装入内存后的周游时间为328 ms,结果中的10625ms把装入内存所消耗的时间。就周游的时间而言转入内存后的时间更快速。

三、JWI获取同义词以及抛出NullPointerException原因解析

获取一个词的Synset内的同义词,一下是一个示例:获取“go”的同义词。

import java.io.File;

import java.io.IOException;

import java.net.URL;

import edu.mit.jwi.Dictionary;

import edu.mit.jwi.IDictionary;

import edu.mit.jwi.item.IIndexWord;

import edu.mit.jwi.item.ISynset;

import edu.mit.jwi.item.IWord;

import edu.mit.jwi.item.IWordID;

import edu.mit.jwi.item.POS;

public class GetWordSynsetsTest {

public static void main(String[] args) throws IOException{

String wnhome = System.getenv("WNHOME"); //获取WordNet根目录环境变量WNHOME

String path = wnhome + File.separator+ "dict";

File wnDir=new File(path);

URL url=new URL("file", null, path);

IDictionary dict=new Dictionary(url);

dict.open();//打开词典

getSynonyms(dict); //testing

}

public static void getSynonyms(IDictionary dict){

// look up first sense of the word "go"

IIndexWord idxWord =dict.getIndexWord("go", POS.VERB);

IWordID wordID = idxWord.getWordIDs().get(0) ; // 1st meaning

IWord word = dict.getWord(wordID);

ISynset synset = word.getSynset (); //ISynset是一个词的同义词集的接口

// iterate over words associated with the synset

for(IWord w : synset.getWords())

System.out.println(w.getLemma());//打印同义词集中的每个同义词

}

}

执行的结果为:

travel

go

move

locomote

在获取一个IndexWord时,很容易抛出一个运行异常,即NullPointerException。这是因为在WordNet里找不着你想要的词。但是这个词在实际英语环境中是存在的。可能的原因如下:

1.所输入的词形式不对,比如:go写成了gone,或者dog写成dogs等非源词形式了。

2.可能是你在构造词时,在如getIndexWord("go", POS.VERB)函数中词性参数输入错误,比如上例中输入的词性是POS.ADVERB。由于go没有副词,所以汇报NullPointerException异常。

3.一些新的单词根本还没录入WordNet。

四、JWI寻找父类词

上义词Hypernyms,即俗称的父类,再次称为父类词。查找一个词的父类词,则使用JWI提供的ISynset对象的getRelatedSynsets(IPointerType)方法来寻找,其中IPointerType为Synsets之间的关系指针,通过设置其为Pointer.HYPERNYM则可以实现寻找该词的父类。

实例:

import java.io.File;

import java.io.IOException;

import java.util.Iterator;

import java.util.List;

import edu.mit.jwi.Dictionary;

import edu.mit.jwi.IDictionary;

import edu.mit.jwi.item.IIndexWord;

import edu.mit.jwi.item.ISynset;

import edu.mit.jwi.item.ISynsetID;

import edu.mit.jwi.item.IWord;

import edu.mit.jwi.item.IWordID;

import edu.mit.jwi.item.POS;

import edu.mit.jwi.item.Pointer;

public class GetHypernymsTest {

public static void main(String[] args) throws IOException{

String wnhome = System.getenv("WNHOME"); //获取WordNet根目录环境变量WNHOME

String path = wnhome + File.separator+ "dict";

File wnDir=new File(path);

IDictionary dict=new Dictionary(wnDir);

dict.open();//打开词典

getHypernyms(dict);//testing

}

public static void getHypernyms(IDictionary dict){

//获取指定的synset

IIndexWord idxWord = dict.getIndexWord("article", POS.NOUN);//获取dog的IndexWord

IWordID wordID = idxWord.getWordIDs().get(0); //取出第一个词义的词的ID号

IWord word = dict.getWord(wordID); //获取词

ISynset synset = word.getSynset(); //获取该词所在的Synset

// 获取hypernyms

List hypernyms =synset.getRelatedSynsets(Pointer.HYPERNYM );//通过指针类型来获取相关的词集,其中Pointer类型为HYPERNYM

// print out each hypernyms id and synonyms

List words ;

for( ISynsetID sid : hypernyms ){

words = dict.getSynset(sid).getWords(); //从synset中获取一个Word的list

System.out.print(sid + "{");

for( Iterator i = words.iterator(); i.hasNext();){

System.out.print(i.next().getLemma ());

if(i. hasNext ()){

System.out.print(", ");

}

}

System .out . println ("}");

}

}

}

执行结果为:

SID-06282025-N{nonfiction, nonfictional_prose}

SID-06186871-N{piece}

从结果看出article有两个父类,第一个为文学、小说、文章等,第二个指片段、一张、片等。










你可能感兴趣的:(词义消岐,WordNet)