Word Net - 词义和相关词构造 - Java或Python

6 投票
3 回答
2609 浏览
提问于 2025-04-16 23:08

我想使用WordNet这个工具,从一组基本的词汇中找出一些相似的词。

比如,单词'discouraged'(沮丧)可能的同义词有:daunted(气馁的), glum(忧郁的), deterred(被阻止的), pessimistic(悲观的)

我还想找出一些可能的双词组合,比如:beat down(打击), put off(推迟), caved in(崩溃)等等。

我该如何用Java或Python来提取这些信息呢?有没有可以在线使用的WordNet数据库或网页接口,方便我进行这样的查询?

谢谢!

3 个回答

2

作为NLTK的替代方案,你可以使用一个可用的WordNet SPARQL接口来获取相关信息。查询示例:

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX wordnet: <http://www.w3.org/2006/03/wn/wn20/schema/>

SELECT DISTINCT ?label {
  ?input_word a wordnet:WordSense;
     rdfs:label ?input_label.
  FILTER (?input_label = 'run')
  ?synset wordnet:containsWordSense ?input_word.
  ?synset wordnet:containsWordSense ?synonym.
  ?synonym rdfs:label ?label.
} LIMIT 100

在Java的世界里,可以使用JenaSesame这两个框架。

3

这其实是两个不同的问题。

1) 关于Wordnet和Python。你可以使用NLTK这个工具,它有一个很不错的Wordnet接口。你可以自己写一些代码,但说实话,何必让自己这么麻烦呢?Lingpipe可能也有类似的功能,但NLTK用起来简单多了。我记得NLTK会下载一个数据库,但我相信也有一些API可以直接和Wordnet进行交流。

2) 如果你想在NLTK中获取二元组(bigrams),可以按照这个教程来做。一般来说,你需要先把文本分词,然后遍历句子,通过向前和向后查看来获取每个单词的所有n-grams。

3

理解WordNet数据最简单的方法是查看Prolog文件。这里有相关的文档:

http://wordnet.princeton.edu/wordnet/man/prologdb.5WN.html

WordNet中的术语被分成了同义词集合,叫做synset。一个synset是一个最大的同义词集合。每个synset都有一个主键,这样它们可以在语义关系中使用。

回答你的第一个问题,你可以列出一个词的不同含义和对应的同义词,方法如下:

Input X: Term
Output Y: Sense  
Output L: Synonyms in this Sense  

s_helper(X,Y) :- s(X,_,Y,_,_,_).  
?- setof(H,(s_helper(Y,X),s_helper(Y,H)),L).  

举个例子:

?- setof(H,(s_helper(Y,'discouraged'),s_helper(Y,H),L).  
Y = 301664880,  
L = [demoralised, demoralized, discouraged, disheartened] ;  
Y = 301992418,  
L = [discouraged] ;  
No  

关于你问题的第二部分,WordNet中的术语是由一系列单词组成的。所以你可以这样搜索WordNet中的词:

Input X: Word  
Output Y: Term

s_helper(X) :- s(_,_,X,_,_,_).  
word_in_term(X,Y) :- atom_concat(X,' ',H), sub_atom(Y,0,_,_,H).
word_in_term(X,Y) :- atom_concat(' ',X,H), atom_concat(H,' ',J), sub_atom(Y,_,_,_,J).
word_in_term(X,Y) :- atom_concat(' ',X,H), sub_atom(Y,_,_,0,H).
?- s_helper(Y), word_in_term(X,Y).

举个例子:

?- s_helper(X), word_in_term('beat',X).  
X = 'beat generation' ;  
X = 'beat in' ;  
X = 'beat about' ;  
X = 'beat around the bush' ;  
X = 'beat out' ;  
X = 'beat up' ;  
X = 'beat up' ;  
X = 'beat back' ;  
X = 'beat out' ;  
X = 'beat down' ;  
X = 'beat a retreat' ;  
X = 'beat down' ;  
X = 'beat down' ;  
No

这样你会得到潜在的n-grams(n元组),但形态变化不多。WordNet也展示了一些词汇关系,这可能会有用。

不过,我给出的这两个Prolog查询效率都不高。问题在于缺少一些单词索引。当然,Java的实现可以做得更好。想象一下这样的情况:

class Synset {  
    static Hashtable<Integer,Synset> synset_access;  
    static Hashtable<String,Vector<Synset>> term_access;  
}

一些Prolog可以通过索引指令做到同样的事情,可以指示Prolog系统在一个谓词的多个参数上进行索引。

建立一个网络服务其实也不难,无论是用Java还是Prolog。很多Prolog系统都很容易将Prolog程序嵌入到网络服务器中,而Java则擅长处理servlet。

支持网络服务器的Prolog列表可以在这里找到:

http://en.wikipedia.org/wiki/Comparison_of_Prolog_implementations#Operating_system_and_Web-related_features

祝好

撰写回答