WordNet詞網研究6——之JWI(Java Wordnet Interface)WordNet Java接口

JWI (the MIT Java Wordnet Interface) is a Java library for interfacing with Wordnet. JWI supports access to Wordnet versions 1.6 through 3.0, among other related Wordnet extensions. Wordnet is a freely and publicly available semantic dictionary of English, developed at Princeton University.

JWI is written for Java 1.5.0 and has the package namespace edu.mit.jwi. The distribution does not include the Wordnet dictionary files; these can be downloaded from the Wordnet download site. This version of software is distributed under a license that makes it free to use for all purposes, as long as proper copyright acknowledgement is made.

The javadoc API is posted online for your convenience. So is the version changelog. If you find JWI useful, have found a bug, or would like to request a new feature, please contact me.

DescriptionLinkBinary Files Onlyedu.mit.jwi_2.2.2.jar (143 kb)User's Manualedu.mit.jwi_2.2.2_manual.pdf (276 kb)Source Onlyedu.mit.jwi_2.2.2_src.zip (143 kb)Javadocsedu.mit.jwi_2.2.2_javadoc.zip (617 kb) | onlineDevelopment Kit (binaries and source)edu.mit.jwi_2.2.2_jdk.jar (273 kb)All-in-One (jdk, javadocs, manual)edu.mit.jwi_2.2.2_all.zip (1,090 kb)

 From:http://projects.csail.mit.edu/jwi/

JWI是由MIT麻省理工學院,計算機科學與人工智能實驗室, Mark Alan.Finlayson主持的項目。JWI是用於訪問WordNet的Java API。

 

一、WordNet與JWI使用實例:

 

1.先安裝WordNet

        安裝過程略,設置環境變量WNHOME,指向WordNet的安裝根目錄。例如:

      WNHOME = “E:\Commonly Application\WordNet\2.1”;

2.下載JWI

     到http://projects.csail.mit.edu/jwi/下載JWI,使用其jdk來進行測試、開發等。

3.測試

    寫一個測試類:

 

import java.io.File;

import java.io.IOException;

importjava.net.MalformedURLException;

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.IWord;

import edu.mit.jwi.item.IWordID;

import edu.mit.jwi.item.POS;

 

 

public class test {

 

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

       testDitctionary();

    }

    

    public static void testDitctionary() throws IOException{

       // construct the URL to the Wordnet dictionary directory

       String wnhome = System.getenv("WNHOME"); //獲取環境變量WNHOME

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

       URL url=new URL("file", null, path);  //創建一個URL對象,指向WordNet的ditc目錄

       

       // construct the dictionary object and open it

       IDictionary dict=new Dictionary(url);

       dict.open(); //打開詞典

       

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

       IIndexWord idxWord=dict.getIndexWord("dog", POS.NOUN);//獲取一個索引詞,(dog,名詞)

       IWordID wordID=idxWord.getWordIDs().get(0);//獲取dog第一個詞義ID

       IWord word = dict.getWord(wordID); //獲取該詞

       System .out . println ("Id = " + wordID );

       System .out . println (" 詞元 = " + word . getLemma ());

       System .out . println (" 註解 = " + word . getSynset (). getGloss ());

    }

}

 

執行得到的結果如下:

 

Id = WID-02064081-N-??-dog

 詞元 = dog

 註解 = a member of the genus Canis (probably descended from the common wolf) that has been domesticated by man since prehistoric times; occurs in many breeds; "the dog barked all night"

 

這是一個初步是使用JWI的例子。

 

二、JWI裝載WordNet到內存的遍歷性能優化:

 

JWI2.2.x系列一個新的特點是可以將WordNet裝載到內存中,這一舉措大大的改善了遍歷WordNet的性能。其中實現該功能的是,JWI的edu.mit.jwi.RAMDictionary類,該類可以設定是否將WordNet裝入內存。

 

寫一個遍歷WordNet的函數trek(),對使用RAMDictionary來打開WordNet,對不裝載入內存和裝載入內存進行比較;

 importjava.io.File;

importjava.io.IOException;

importjava.util.Iterator;

 

importedu.mit.jwi.IDictionary;

importedu.mit.jwi.IRAMDictionary;

importedu.mit.jwi.RAMDictionary;

importedu.mit.jwi.data.ILoadPolicy;

importedu.mit.jwi.item.IIndexWord;

importedu.mit.jwi.item.IWordID;

importedu.mit.jwi.item.POS;

 

public classRAMDictionaryTest {

     public static voidmain(String[] args) throwsIOException, Exception{

      String wnhome = System.getenv("WNHOME"); //獲取環境變量WNHOM 

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

       File wnDir=newFile(path);

       testRAMDictionary(wnDir);

    }

    public static voidtestRAMDictionary(File wnDir)throwsIOException, InterruptedException{

       IRAMDictionary dict=newRAMDictionary(wnDir, ILoadPolicy.NO_LOAD);

       dict.open();

       //周遊WordNet

       System.out.print("沒裝載前:\n");

       trek(dict);

       //now load into memor

       System.out.print("\nLoading Wordnet into memory...");

       longt=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 voidtrek(IDictionary dict){

       inttickNext=0;

       inttickSize=20000;

       intseen=0;

       System.out.print("Treking across Wordnet");

       longt=System.currentTimeMillis();

       for(POS pos:POS.values()){ //遍歷所有詞性

           for(Iterator<IIndexWord> 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<ISynsetID> hypernyms =synset.getRelatedSynsets(Pointer.HYPERNYM );//通過指針類型來獲取相關的詞集,其中Pointer類型爲HYPERNYM

       // print out each hypernyms id and synonyms

       List <IWord > words ;

       for( ISynsetID sid : hypernyms ){

           words = dict.getSynset(sid).getWords(); //從synset中獲取一個Word的list

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

           for( Iterator<IWord > 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有兩個父類,第一個爲文學、小說、文章等,第二個指片段、一張、片等。

 

五、JWI的詞典指針和語義指針

 

爲什麼要說明這個問題呢?

 

    是因爲有時候明明知道在WordNet中又這麼兩個詞,但卻無法使用JWI由item X指向Item Y,原因就是混用了JWI的詞典指針lexical pointers和語義指針semantic pointers。這裏的指針不是C/C++的指針,是指詞條之間、詞集之間的一個連接關係。

 

詞典指針——指詞與詞一次之間的關聯關係,比如說dog與domestic dog的近義詞等關係。包括詞同形異義的兩個詞,派生關係等等;其工作的範圍是詞與詞之間。

語義指針——指詞集與詞集之間的關聯關係,一個詞集Synset是包含多個詞的,詞集之間包括了詞典指針的關係,只要是使用關聯比如上下詞關係、部分與整體等。其工作的範圍是詞集。

WordNet結果圖如下,包括詞索引,詞,詞集以及相應的指針:

 

 

其中,紅色的指針就是語義指針,而Word之間的藍綠指針是詞典指針。

 

指針使用方法

 

      而當使用語義指針時,必須使用ISynset對象的ISynset.getRelatedSynsets(IPointer)方法。而使用詞典指針時,你可以使用IWord對象的IWord.getRelatedWords(IPointer)方法。

 

      至於如何去使用這兩個指針,什麼時候使用詞典指針,什麼時候使用語義指針,什麼時候可以兩者都是用,很不幸地是,WordNet的相關文檔解釋很少。不過M.A. Finlayson爲我們通過觀察和統計WordNet,指出瞭如圖說是的指針統計表。

 

 

WordNet2.1以上的版本都幾乎相似。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章