Как мне выполнить слово Stemming или Lemmatization?

Я пробовал PorterStemmer и Snowball, но оба они не работают над всеми словами, пропуская некоторые очень распространенные.

Мои тестовые слова: " кошки, бегущие как cactus cactus cactus сообщества сообщества cacti", и оба получают меньше половины прав.

См. также:

Ответ 1

Если вы знаете Python, Natural Language Toolkit (NLTK) имеет очень мощный lemmatizer, который использует WordNet.

Обратите внимание, что если вы впервые используете этот лемматизатор, вы должны загрузить его до его использования. Это можно сделать:

>>> import nltk
>>> nltk.download('wordnet')

Вам нужно только сделать это один раз. Предполагая, что вы теперь загрузили корпус, он работает следующим образом:

>>> 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'

В nltk.stem модуль есть другие лемматизаторы, но я сам их не пробовал.

Ответ 2

Я использую 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);
            }
        }
    }
}

Также может быть хорошей идеей использовать стоп-слова для минимизации выходных лемм, если они используются позже в классификаторе. Пожалуйста, взгляните на coreNlp расширение, написанное Джоном Конвелл.

Ответ 3

Я пробовал ваш список терминов на этот демонстрационный сайт снежного кома, и результаты выглядят нормально....

  • кошки → кошка
  • running → run
  • ran → ran
  • кактус → кактус
  • кактусы → кактус
  • сообщество → Communiti
  • сообщества → communiti

Предполагается, что стебельщик превратит отклоненные формы слов в какой-то общий корень. Это не настоящая работа, чтобы сделать этот корень "правильным" словарем. Для этого вам нужно посмотреть морфологические/орфографические анализаторы.

Я думаю, этот вопрос примерно такой же, и Kaarel отвечает на этот вопрос, где я взял вторую ссылку.

Ответ 4

Продолжаются дебаты о борьбе с барабанщиком против лемматизатора. Это вопрос предпочтения точности по эффективности. Вы должны использовать леммитизацию для достижения лингвистически значимых единиц и использовать минимальный вычислительный сок и по-прежнему индексировать слово и его варианты под одним и тем же ключом.

Смотрите 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'

Ответ 5

Официальная страница Мартина Портера содержит Porter Stemmer в PHP, а также другие языки.

Если вы действительно серьезно относитесь к хорошему результату, хотя вам нужно начать с чего-то вроде алгоритма Porter, уточните его, добавив правила для исправления неверных случаев, общих для вашего набора данных, а затем, наконец, добавьте множество исключений к правилам. Это может быть легко реализовано с помощью пар ключ/значение (dbm/hash/dictionaries), где ключ - это слово для поиска, а значение - это исходное слово для замены оригинала. Коммерческая поисковая система, с которой я работал, однажды закончила с 800 некоторыми исключениями для модифицированного алгоритма Porter.

Ответ 7

Посмотрите в WordNet, большую лексическую базу данных для английского языка:

http://wordnet.princeton.edu/

Существуют API для доступа к нему на нескольких языках.

Ответ 9

Взгляните на LemmaGen - библиотека с открытым исходным кодом, написанная на С# 3.0.

Результаты для ваших тестовых слов (http://lemmatise.ijs.si/Services)

  • кошки → кошка
  • работает
  • ran → run
  • кактус
  • кактусы → кактус
  • cacti → кактус
  • сообщества
  • сообщества → сообщество

Ответ 10

Сделайте поиск foR Lucene, im not sure, если theres порт PHP, но я знаю, что Lucene доступен для многих платформ. Lucene - это библиотека индексирования и поиска OSS (из Apache). Естественно, что у него и у сообщества есть что-то интересное. По крайней мере, вы можете узнать, как это делается на одном языке, чтобы вы могли перевести "идею" в PHP

Ответ 11

Если я могу процитировать мой ответ на вопрос StompChicken:

Основная проблема здесь заключается в том, что алгоритмы генерации работают на фонетической основе без реального понимания языка, с которым они работают.

Поскольку они не понимают язык и не работают из словаря терминов, они не могут распознавать и отвечать соответствующим образом на нерегулярные случаи, такие как "run" / "run".

Если вам нужно обрабатывать нерегулярные случаи, вам нужно либо выбрать другой подход, либо увеличить ваш исходный текст с помощью собственного пользовательского словаря исправлений, которые будут выполняться после того, как стволовые делали свое дело.

Ответ 13

Вы можете использовать ствол Морфы. UW имеет загруженную морфологию в центр Maven в центре, если вы планируете использовать ее из приложения Java. Там обертка, которая делает ее намного проще в использовании. Вам просто нужно добавить его как зависимость и использовать класс edu.washington.cs.knowitall.morpha.MorphaStemmer. Экземпляры являются потокобезопасными (исходный JFlex без полей классов для локальных переменных). Создайте экземпляр класса и запустите morpha и слово, которое вы хотите создать.

new MorphaStemmer().morpha("climbed") // goes to "climb"

Ответ 14

.Net lucene имеет встроенный стример портера. Вы можете попробовать это. Но обратите внимание, что при построении леммы портер не учитывает контекст слова. (Пройдите алгоритм и его реализацию, и вы увидите, как он работает)

Ответ 15

Мартин Портер написал "Снежок" (язык для алгоритмов генерации) и переписал "Английский стриммер" в Snowball. Есть английский стриммер для C и Java.

Он явно заявляет, что Портерский Стеммер был переопределен только по историческим причинам, поэтому проверка правильности верности против Портер-Стэммера даст вам результаты, которые вы (должны) уже знать.

Из http://tartarus.org/~martin/PorterStemmer/index.html (внимание мое)

Штокер Портера следует рассматривать как " замороженный, то есть строго определенный и не поддающийся дальнейшей модификации. Как стволовый, он немного уступает стебельке Snowball English или Porter2, который вытекает из него, и который подвергается случайным улучшениям. Поэтому для практической работы рекомендуется использовать новый сноуборд. Основатель Porter подходит для исследований IR-исследований, связанных с производством, где эксперименты должны быть точно повторяемыми.

р. Портер предлагает использовать английские или портер2-стволовые средства вместо стебля Портера. Английский стволовый - это то, что фактически используется в демонстрационный сайт, поскольку @StompChicken ответил ранее.

Ответ 16

В Java я использую tartargus-snowball для словесного слова

Maven:

<dependency>
        <groupId>org.apache.lucene</groupId>
        <artifactId>lucene-snowball</artifactId>
        <version>3.0.3</version>
        <scope>test</scope>
</dependency>

Пример кода:

SnowballProgram stemmer = new EnglishStemmer();
String[] words = new String[]{
    "testing",
    "skincare",
    "eyecare",
    "eye",
    "worked",
    "read"
};
for (String word : words) {
    stemmer.setCurrent(word);
    stemmer.stem();
    //debug
    logger.info("Origin: " + word + " > " + stemmer.getCurrent());// result: test, skincar, eyecar, eye, work, read
}

Ответ 17

Попробуйте здесь: http://www.twinword.com/lemmatizer.php

Я ввел ваш запрос в демо "cats running ran cactus cactuses cacti community communities" и получил ["cat", "running", "run", "cactus", "cactus", "cactus", "community", "community"] с необязательным флагом ALL_TOKENS.

Пример кода

Это API, поэтому вы можете подключиться к нему из любой среды. Вот как выглядит вызов PHP REST.

// These code snippets use an open-source library. http://unirest.io/php
$response = Unirest\Request::post([ENDPOINT],
  array(
    "X-Mashape-Key" => [API KEY],
    "Content-Type" => "application/x-www-form-urlencoded",
    "Accept" => "application/json"
  ),
  array(
    "text" => "cats running ran cactus cactuses cacti community communities"
  )
);