我如何做词干或词形还原?

man*_*ock 109 nlp stemming lemmatization

我已经尝试过PorterStemmer和Snowball,但两个都不能用于所有单词,缺少一些非常常见的单词.

我的测试词是:" 猫跑仙人掌仙人掌仙人掌社区社区 ",两者都不到一半.

也可以看看:

the*_*rty 142

如果你了解Python,那么自然语言工具包(NLTK)就有一个非常强大的使用WordNet的变形器.

请注意,如果您是第一次使用此词形变换器,则必须在使用它之前下载语料库.这可以通过以下方式完成:

>>> import nltk
>>> nltk.download('wordnet')
Run Code Online (Sandbox Code Playgroud)

你只需要这样做一次.假设您现在已经下载了语料库,它的工作原理如下:

>>> from nltk.stem.wordnet import WordNetLemmatizer
>>> lmtzr = WordNetLemmatizer()
>>> lmtzr.lemmatize('cars')
'car'
>>> lmtzr.lemmatize('feet')
'foot'
>>> lmtzr.lemmatize('people')
'people'
>>> lmtzr.lemmatize('fantasized','v')
'fantasize'
Run Code Online (Sandbox Code Playgroud)

nltk.stem模块中还有其他的引理器,但我自己没有尝试过.

  • nltk WordNetLemmatizer需要一个pos标记作为参数.默认情况下,它是'n'(代表名词).所以它对动词不起作用.如果POS标签不可用,一种简单(但是特别)的方法是两次进行词形化,一个用于'n',另一个用于'v'(代表动词),并选择不同于原始单词(通常较短,但'run'和'run'具有相同的长度).似乎我们不需要担心'adj','adv','prep'等,因为它们在某种意义上已经处于原始形式. (21认同)
  • 在第一次使用**nltk**之前不要忘记安装语料库!http://www.velvetcache.org/2010/03/01/looking-up-words-in-a-dictionary-using-python (12认同)
  • 哦,伤心......在我知道搜索之前我实现了自己的! (11认同)
  • 知道"WordNetLemmatizer"错误引理的词是什么? (3认同)

CTs*_*rth 29

我使用stanford nlp来执行词形还原.在过去的几天里,我一直遇到类似的问题.感谢stackoverflow帮助我解决问题.

import java.util.*; 
import edu.stanford.nlp.pipeline.*;
import edu.stanford.nlp.ling.*; 
import edu.stanford.nlp.ling.CoreAnnotations.*;  

public class example
{
    public static void main(String[] args)
    {
        Properties props = new Properties(); 
        props.put("annotators", "tokenize, ssplit, pos, lemma"); 
        pipeline = new StanfordCoreNLP(props, false);
        String text = /* the string you want */; 
        Annotation document = pipeline.process(text);  

        for(CoreMap sentence: document.get(SentencesAnnotation.class))
        {    
            for(CoreLabel token: sentence.get(TokensAnnotation.class))
            {       
                String word = token.get(TextAnnotation.class);      
                String lemma = token.get(LemmaAnnotation.class); 
                System.out.println("lemmatized version :" + lemma);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果稍后在分类器中使用,则使用停用词来最小化输出引理也可能是个好主意.请查看John Conwell撰写的coreNlp扩展.


Sto*_*ken 24

我在这个雪球演示网站上尝试了你的术语列表,结果看起来还不错....

  • 猫 - >猫
  • 跑 - >跑
  • 跑 - >跑
  • 仙人掌 - >仙人掌
  • 仙人掌 - >仙人掌
  • 社区 - >社区
  • 社区 - >社区

一个词干分子应该将变形的词汇转换成一些共同的词根.将root作为一个"正确的"词典单词并不是一个干扰者的工作.为此,您需要查看形态/正交分析仪.

我认为这个问题或多或少是相同的,Kaarel对这个问题的回答是我从第二个链接开始的.

  • 谨慎使用术语,词干不是单词的基本形式.如果你想要一个基本形式,你需要一个lemmatizer.词干是单词的最大部分,不包含前缀或后缀.单词更新的主干确实是"更新".通过添加结尾和后缀(例如updat-e或updat-ing)从词干创建单词.(http://en.wikipedia.org/wiki/Word_stem) (11认同)
  • 关键是干("更新")==干("更新"),它做(更新 - >更新) (6认同)
  • 在第一次试用版“更新->更新”后没有留下深刻的印象 (2认同)

alv*_*vas 20

词干与引理论辩论还在继续.这是一个优于精确而不是效率的问题.你应该使用lemotize来获得语言上有意义的单位,并且使用最少的计算成果,并且仍然在同一个键下索引一个单词及其变体.

Stemmers vs Lemmatizers

这是python NLTK的一个例子:

>>> sent = "cats running ran cactus cactuses cacti community communities"
>>> from nltk.stem import PorterStemmer, WordNetLemmatizer
>>>
>>> port = PorterStemmer()
>>> " ".join([port.stem(i) for i in sent.split()])
'cat run ran cactu cactus cacti commun commun'
>>>
>>> wnl = WordNetLemmatizer()
>>> " ".join([wnl.lemmatize(i) for i in sent.split()])
'cat running ran cactus cactus cactus community community'
Run Code Online (Sandbox Code Playgroud)

  • 如前所述,`WordNetLemmatizer`的`lemmatize()`可以采用POS标签.所以从你的例子:`"".join([wnl.lemmatize(i,pos = VERB)for i in sent.split()])`给`'cat run run cactus cactuses cacti community communities'`. (3认同)

Van*_*ale 8

Martin Porter的官方页面包含PHP中的Porter Stemmer以及其他语言.

如果您真的认真考虑好干预,虽然您需要从像Porter算法这样的东西开始,通过添加规则来修改它来修复数据集常见的不正确的情况,然后最后添加很多例外规则.这可以通过键/值对(dbm/hash/dictionaries)轻松实现,其中键是要查找的单词,值是用于替换原始单词的词干单词.我曾经使用的商业搜索引擎最终得到了一些改进的Porter算法的800个例外.


cjb*_*rth 6

根据我遇到的 Stack Overflow 和博客上的各种答案,这是我正在使用的方法,它似乎可以很好地返回真实单词。这个想法是将传入的文本分成一组单词(使用您喜欢的任何方法),然后找到这些单词的词性 (POS) 并使用它来帮助词干和词形还原。

您上面的示例效果不佳,因为无法确定 POS。但是,如果我们使用真正的句子,事情会好得多。

import nltk
from nltk.corpus import wordnet

lmtzr = nltk.WordNetLemmatizer().lemmatize


def get_wordnet_pos(treebank_tag):
    if treebank_tag.startswith('J'):
        return wordnet.ADJ
    elif treebank_tag.startswith('V'):
        return wordnet.VERB
    elif treebank_tag.startswith('N'):
        return wordnet.NOUN
    elif treebank_tag.startswith('R'):
        return wordnet.ADV
    else:
        return wordnet.NOUN


def normalize_text(text):
    word_pos = nltk.pos_tag(nltk.word_tokenize(text))
    lemm_words = [lmtzr(sw[0], get_wordnet_pos(sw[1])) for sw in word_pos]

    return [x.lower() for x in lemm_words]

print(normalize_text('cats running ran cactus cactuses cacti community communities'))
# ['cat', 'run', 'ran', 'cactus', 'cactuses', 'cacti', 'community', 'community']

print(normalize_text('The cactus ran to the community to see the cats running around cacti between communities.'))
# ['the', 'cactus', 'run', 'to', 'the', 'community', 'to', 'see', 'the', 'cat', 'run', 'around', 'cactus', 'between', 'community', '.']
Run Code Online (Sandbox Code Playgroud)


msb*_*msb 5

http://wordnet.princeton.edu/man/morph.3WN

对于我的很多项目,我更喜欢基于词典的WordNet lemmatizer而不是更具攻击性的搬运工.

http://wordnet.princeton.edu/links#PHP有一个指向WN API的PHP接口的链接.


mP.*_*mP. 1

搜索 Lucene,我不确定是否有 PHP 端口,但我知道 Lucene 可用于许多平台。Lucene 是一个 OSS(来自 Apache)索引和搜索库。当然,它和社区的额外内容可能会有一些有趣的东西值得一看。至少您可以了解它是如何用一种语言完成的,这样您就可以将“想法”翻译成 PHP。