如何在R中进行词形还原?

30

这个问题可能是 Lemmatizer in R or python (am, are, is -> be?) 的重复,但我仍然再次添加它,因为之前的一个问题被关闭了,理由是太广泛了,且唯一的答案并不高效(因为它需要访问一个外部网站来完成这个过程,而我的语料库非常大,所以速度太慢)。因此,这个问题的一部分将与上述问题类似。

根据维基百科的定义,词形还原(lemmatization或lemmatisation)在语言学中是指将单词的不同屈折形式分组在一起,以便可以将它们分析为一个单一的项目。

Lemmatisation(或lemmatization)在语言学中是指将单词的不同屈折形式分组在一起,以便可以将它们分析为一个单一的项目。

在R中搜索词形还原的结果只会提到R的wordnet包。当我尝试使用该包时,期望将一个字符向量c("run", "ran", "running")输入到词形还原函数中,得到的结果应该是c("run", "run", "run")。但我发现该包只提供了类似于grepl函数的功能,通过各种过滤器名称和字典来实现。

wordnet包中的一个示例代码,它会给出以“car”开头的最多5个单词,如过滤器名称所解释的那样:

filter <- getTermFilter("StartsWithFilter", "car", TRUE)
terms <- getIndexTerms("NOUN", 5, filter)
sapply(terms, getLemma)

以上并不是我所要寻找的词形还原。我要寻找的是,使用R找到单词的真正词根:(例如,从c("run", "ran", "running")c("run", "run", "run"))。


2
抱歉,但我认为这是“寻找软件包或工具”,而不是尝试解决特定的编程问题。也许有一些计算语言学/文本挖掘论坛可以询问? - Ben Bolker
3
我认为这个问题与通常被关闭的包/工具搜索问题略有不同。它是在询问如何在R中执行词形还原,这是一个编程问题。@StrikeR:我建议您修改最后一行“有没有...”,以避免此问题被关闭。 - Chthonic Project
@ChthonicProject 感谢您的建议。已经相应地进行了更改。 - StrikeR
这不是一个编程问题。其中编程部分有一个简单的答案 - 找到/创建一个字典,然后执行查找。 - eddi
3
我不同意你的评论,认为这是一个编程问题。在你的评论中,你假设只有一种使用字典查找的词形还原形式,但是还有其他基于规则的形式。因此,我认为编程部分并不像你想象的那么简单。我可以接受使用R进行词形还原的任何答案,无论是基于字典还是规则的。但唯一的限制是处理大文本语料库时速度不能慢。 - StrikeR
@StrikeR 好的,那么你在实现这些规则方面遇到了问题吗?那将是一个编程问题。你在实现基于字典的解决方案时遇到了问题吗?那也是一个编程问题。但这不是。 - eddi
6个回答

31

你可以尝试使用 koRpus 软件包,该软件包允许使用 Treetagger

tagged.results <- treetag(c("run", "ran", "running"), treetagger="manual", format="obj",
                      TT.tknz=FALSE , lang="en",
                      TT.options=list(path="./TreeTagger", preset="en"))
tagged.results@TT.res

##     token tag lemma lttr wclass                               desc stop stem
## 1     run  NN   run    3   noun             Noun, singular or mass   NA   NA
## 2     ran VVD   run    3   verb                   Verb, past tense   NA   NA
## 3 running VVG   run    7   verb Verb, gerund or present participle   NA   NA

查看lemma列以获取您所要求的结果。


谢谢Victor。那个答案对我很有帮助。但我还在继续努力。如果没有更好的答案,我想再等两天来寻找其他解决方案并接受这个答案。 - StrikeR
没问题,我明白,使用外部软件可能会有些棘手。 - Victorp

23

如先前的帖子所提到的,R软件包textstem中的函数lemmatize_words()可以执行此操作并给出您理解的所需结果:

lemmatize_words()函数来自于R软件包textstem,可以实现词形还原操作,并得到您所期望的结果。

library(textstem)
vector <- c("run", "ran", "running")
lemmatize_words(vector)

## [1] "run" "run" "run"

9

当@Andy和@Arunkumar说到textstem库可以用来执行词干提取和/或词形还原时,他们是正确的。然而,lemmatize_words()函数只能处理单词向量。但在语料库中,我们没有单词向量,我们有字符串,每个字符串都是一个文档的内容。因此,要在语料库上执行词形还原,您可以使用函数lemmatize_strings()作为tm包中的tm_map()的参数。

> corpus[[1]]
[1] " earnest roughshod document serves workable primer regions recent history make 
terrific th-grade learning tool samuel beckett applied iranian voting process bard 
black comedy willie loved another trumpet blast may new mexican cinema -bornin "
> corpus <- tm_map(corpus, lemmatize_strings)
> corpus[[1]]
[1] "earnest roughshod document serve workable primer region recent history make 
terrific th - grade learn tool samuel beckett apply iranian vote process bard black 
comedy willie love another trumpet blast may new mexican cinema - bornin"

在进行词形还原后,请不要忘记运行以下代码:

> corpus <- tm_map(corpus, PlainTextDocument)

这是因为要创建文档-术语矩阵,需要具有“PlainTextDocument”类型的对象,但在使用lemmatize_strings()后该对象会发生变化(更具体地说,语料库对象不再包含每个文档的内容和元数据,而是仅包含文档内容的结构;这不是DocumentTermMatrix()作为参数所接受的对象类型)。 希望这可以帮到你!

4
也许词干提取对您来说已经足够了?典型的自然语言处理任务使用词干化文本。您可以在NLP的CRAN任务视图中找到几个包:http://cran.r-project.org/web/views/NaturalLanguageProcessing.html 如果您确实需要更复杂的内容,则有基于将句子映射到神经网络的专门解决方案。据我所知,这些需要大量的训练数据。斯坦福NLP小组创建并提供了许多开放软件。
如果您真的想深入研究这个主题,那么您可以通过同一斯坦福NLP小组出版物部分链接的事件档案进行挖掘。还有一些关于这个主题的书籍。

目前我正在使用词干提取算法来处理我的语料库,但实际上我真正想要的是词形还原,并且我想比较一下在使用词形还原代替词干提取时结果会有多大的改善(持怀疑态度)。不过还是谢谢你提供的信息。 - StrikeR

4
我认为这里的答案有点过时了。现在应该使用R软件包udpipe-可以在https://CRAN.R-project.org/package=udpipe找到-参见https://github.com/bnosac/udpipe或文档https://bnosac.github.io/udpipe/en

请注意在进行词形还原和进行词干提取时以下示例中名词meeting和动词meet之间的差异,以及在进行词干提取时使单词“someone”出现错误成“someon”的麻烦之处。

library(udpipe)
x <- c(doc_a = "In our last meeting, someone said that we are meeting again tomorrow",
       doc_b = "It's better to be good at being the best")
anno <- udpipe(x, "english")
anno[, c("doc_id", "sentence_id", "token", "lemma", "upos")]
#>    doc_id sentence_id    token    lemma  upos
#> 1   doc_a           1       In       in   ADP
#> 2   doc_a           1      our       we  PRON
#> 3   doc_a           1     last     last   ADJ
#> 4   doc_a           1  meeting  meeting  NOUN
#> 5   doc_a           1        ,        , PUNCT
#> 6   doc_a           1  someone  someone  PRON
#> 7   doc_a           1     said      say  VERB
#> 8   doc_a           1     that     that SCONJ
#> 9   doc_a           1       we       we  PRON
#> 10  doc_a           1      are       be   AUX
#> 11  doc_a           1  meeting     meet  VERB
#> 12  doc_a           1    again    again   ADV
#> 13  doc_a           1 tomorrow tomorrow  NOUN
#> 14  doc_b           1       It       it  PRON
#> 15  doc_b           1       's       be   AUX
#> 16  doc_b           1   better   better   ADJ
#> 17  doc_b           1       to       to  PART
#> 18  doc_b           1       be       be   AUX
#> 19  doc_b           1     good     good   ADJ
#> 20  doc_b           1       at       at SCONJ
#> 21  doc_b           1    being       be   AUX
#> 22  doc_b           1      the      the   DET
#> 23  doc_b           1     best     best   ADJ
lemmatisation <- paste.data.frame(anno, term = "lemma", 
                                  group = c("doc_id", "sentence_id"))
lemmatisation
#>   doc_id sentence_id
#> 1  doc_a           1
#> 2  doc_b           1
#>                                                             lemma
#> 1 in we last meeting , someone say that we be meet again tomorrow
#> 2                          it be better to be good at be the best

library(SnowballC)
tokens   <- strsplit(x, split = "[[:space:][:punct:]]+")
stemming <- lapply(tokens, FUN = function(x) wordStem(x, language = "en"))
stemming
#> $doc_a
#>  [1] "In"       "our"      "last"     "meet"     "someon"   "said"    
#>  [7] "that"     "we"       "are"      "meet"     "again"    "tomorrow"
#> 
#> $doc_b
#>  [1] "It"     "s"      "better" "to"     "be"     "good"   "at"     "be"    
#>  [9] "the"    "best"

1
使用textStem包可以轻松地在R中进行词形还原。 步骤如下: 1)安装textstem 2)通过library(textstem)加载包 3)stem_word=lemmatize_words(word, dictionary = lexicon::hash_lemmas),其中stem_word是词形还原的结果,word是输入的单词。

这并不是一个很好的代码示例。它甚至没有正确格式化。你如何将其应用于VCorpus对象? - wordsforthewise

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接