web-dev-qa-db-fra.com

Comment puis-je créer un cliché ou une lemmatisation?

J'ai essayé PorterStemmer et Snowball, mais les deux ne fonctionnent pas sur tous les mots, il en manque des très courants. 

Mes mots de test sont les suivants: "cats qui couraient couraient des communautés de communautés de cactus de cactus", et les deux obtiennent moins de la moitié.

Voir également:

104
manixrock

Si vous connaissez Python, Le Boîte à outils en langage naturel (NLTK) a un très puissant lemmatiseur qui utilise WordNet .

Notez que si vous utilisez ce lemmatiseur pour la première fois, vous devez télécharger le corpus avant de l’utiliser. Cela peut être fait par:

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

Vous n'avez qu'à le faire une fois. En supposant que vous ayez téléchargé le corpus, cela fonctionne comme ceci:

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

Il y a d'autres lemmatiseurs dans le module nltk.stem , mais je ne les ai pas essayés moi-même.

140
theycallmemorty

J'utilise stanford nlp pour effectuer la lemmatisation. J'ai eu un problème similaire au cours des derniers jours. Tout cela grâce à stackoverflow pour m'aider à résoudre le problème. 

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);
            }
        }
    }
}

Il peut également être judicieux d’utiliser des mots vides pour minimiser les lemmes de sortie s’ils sont utilisés ultérieurement dans Classificator. Veuillez jeter un oeil à coreNlp extension écrit par John Conwell.

29
CTsiddharth

J'ai essayé votre liste de termes sur ce site de démonstration de Snowball et les résultats semblent corrects .... 

  • chats -> chat 
  • courir -> courir 
  • a couru -> a couru
  • cactus -> cactus 
  • cactus -> cactus
  • communauté -> communiti 
  • communautés -> communiti

Un stemmer est censé transformer des formes de mots infléchies en une racine commune. Ce n'est pas vraiment le travail d'un stemmer de transformer cette racine en un dictionnaire "approprié". Pour cela, vous devez regarder les analyseurs morphologiques/orthographiques .

Je pense cette question est à peu près la même chose, et la réponse de Kaarel à cette question est d'où je tire le deuxième lien.

24
Stompchicken

Les débats entre stemmer et lemmatizer se poursuivent. Il s'agit de préférer la précision à l'efficacité. Vous devriez lemmatiser pour obtenir des unités significatives sur le plan linguistique et utiliser un minimum de calcul, tout en indexant un mot et ses variations sous la même clé. 

Voir Stemmers vs Lemmatizers

Voici un exemple avec 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'
20
alvas

La page officielle de Martin Porter contient un Porter Stemmer en PHP ainsi que d'autres langues .

Si vous êtes vraiment sérieux au sujet de la résolution de problèmes bien que vous ayez besoin de commencer avec quelque chose comme l'algorithme de Porter, affinez-le en ajoutant des règles pour corriger les cas incorrects communs à votre ensemble de données, puis ajoutez enfin de nombreuses exceptions aux règles. . Cela peut être facilement implémenté avec des paires clé/valeur (dbm/hachage/dictionnaires) où la clé est le mot à rechercher et la valeur est le mot tronqué pour remplacer l'original. Un moteur de recherche commercial sur lequel j'ai travaillé une fois s'est retrouvé avec 800 exceptions à un algorithme de Porter modifié.

8
Van Gale

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

Pour beaucoup de mes projets, je préfère le lemmatiseur WordNet basé sur le lexique sur le portier plus agressif. 

http://wordnet.princeton.edu/links#PHP a un lien vers une interface PHP aux API WN.

5
msbmsb

En me basant sur diverses réponses à Stack Overflow et sur les blogs que j'ai rencontrés, c’est la méthode que j’utilise et qui semble bien renvoyer les vrais mots. L'idée est de scinder le texte entrant en un tableau de mots (utilisez la méthode de votre choix), puis de trouver les parties du discours (POS) correspondant à ces mots et de les utiliser pour aider à caler et lemmatiser les mots.

Votre échantillon ci-dessus ne fonctionne pas très bien, car le point de vente ne peut pas être déterminé. Cependant, si nous utilisons une phrase réelle, les choses fonctionnent beaucoup mieux.

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', '.']
4
cjbarth

Regardez dans WordNet, une grande base de données lexicale en anglais:

http://wordnet.princeton.edu/

Il existe des API pour y accéder dans plusieurs langues.

3
Ricardo J. Méndez

Cela semble intéressant: MIT Java WordnetStemmer: http://projects.csail.mit.edu/jwi/api/edu/mit/jwi/morph/WordnetStemmer. html

2
user382903

Jetez un coup d'œil à LemmaGen - bibliothèque open source écrite en C # 3.0.

Résultats pour vos mots de test ( http://lemmatise.ijs.si/Services )

  • chats -> chat
  • fonctionnement
  • couru -> couru
  • cactus
  • cactus -> cactus
  • cactus -> cactus
  • communauté
  • communautés -> communauté
2
Alex

Les meilleurs packages Python pour la lemmatisation (sans ordre spécifique) sont: spacy, nltk, gensim, pattern, CoreNLP et TextBlob. Je préfère l'implémentation de spaCy et de gensim (selon un modèle), car ils identifient l'étiquette du mot de vente et attribuent automatiquement le lemme approprié. Le donne des lemmes plus pertinents, en gardant le sens intact.

Si vous envisagez d’utiliser nltk ou TextBlob, vous devez veiller à trouver manuellement la bonne étiquette de point de vente et à trouver le bon lemme. 

Exemple de lemmatisation avec spaCy:

# Run below statements in terminal once. 
pip install spacy
spacy download en

import spacy

# Initialize spacy 'en' model
nlp = spacy.load('en', disable=['parser', 'ner'])

sentence = "The striped bats are hanging on their feet for best"

# Parse
doc = nlp(sentence)

# Extract the lemma
" ".join([token.lemma_ for token in doc])
#> 'the strip bat be hang on -PRON- foot for good'

Exemple de lemmatisation avec Gensim:

from gensim.utils import lemmatize
sentence = "The striped bats were hanging on their feet and ate best fishes"
lemmatized_out = [wd.decode('utf-8').split('/')[0] for wd in lemmatize(sentence)]
#> ['striped', 'bat', 'be', 'hang', 'foot', 'eat', 'best', 'fish']

Les exemples ci-dessus ont été empruntés à cette lemmatization page.

1
Selva

Faites une recherche sur Lucene, je ne suis pas sûr qu'il y ait un port PHP mais je sais que Lucene est disponible sur de nombreuses plateformes. Lucene est une bibliothèque de recherche et d’indexation OSS (d’Apache). Naturellement, les extras de la communauté pourraient avoir quelque chose d’intéressant à regarder. À tout le moins, vous pouvez apprendre comment cela se fait dans une langue afin de pouvoir traduire "l'idée" en PHP

1
mP.

Vous pouvez utiliser le stemmer Morpha. UW a téléchargé morpha stemmer vers Maven central si vous prévoyez de l’utiliser à partir d’une application Java. Il y a un emballage qui le rend beaucoup plus facile à utiliser. Il vous suffit de l'ajouter en tant que dépendance et d'utiliser la classe edu.washington.cs.knowitall.morpha.MorphaStemmer. Les instances sont threadsafe (le JFlex d'origine avait des champs de classe pour les variables locales inutilement). Instanciez une classe et exécutez morpha et le mot que vous souhaitez endiguer.

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

Snowball est la version la plus récente du stemmer de NLTK.

Vous pouvez trouver des exemples sur la façon de l'utiliser ici:

http://nltk.googlecode.com/svn/trunk/doc/api/nltk.stem.Snowball2-pysrc.html#demo

1
Edmon

Si je peux citer ma réponse à la question posée par StompChicken:

Le problème fondamental ici est que les algorithmes d'extraction fonctionnent sur une base phonétique sans comprendre réellement la langue avec laquelle ils travaillent.

Comme ils ne comprennent pas la langue et ne partent pas d'un dictionnaire de termes, ils n'ont aucun moyen de reconnaître et de répondre de manière appropriée aux cas irréguliers, tels que "run"/"run".

Si vous devez gérer des cas irréguliers, vous devrez soit choisir une approche différente, soit compléter votre dictionnaire avec votre propre dictionnaire de corrections personnalisé à exécuter une fois que le stemmer aura fait son travail.

1
Dave Sherohman

.Net Lucene a un portier incorporé. Vous pouvez essayer ça. Mais notez que porter stemming ne considère pas le contexte de Word pour dériver le lemme. (Passez en revue l'algorithme et son implémentation et vous verrez comment ça marche)

0

Je recommande fortement d'utiliser Spacy (traitement et étiquetage de texte de base) et Textacy (traitement de texte de niveau supérieur basé sur Spacy).

Les mots lemmatisés sont disponibles par défaut dans Spacy en tant qu'attribut .lemma_ d'un jeton et le texte peut être lemmatisé tout en effectuant beaucoup d'autres traitements de texte avec du textacy. Par exemple lors de la création d'un sac de termesou de mots ou généralement juste avant d'effectuer un traitement qui l'exige.

Je vous encourage à vérifier les deux avant d'écrire n'importe quel code, car cela pourrait vous faire économiser beaucoup de temps!

0
QA Collective

En Java, j'utilise tartargus-Snowball à des mots dérivés

Maven:

<dependency>
        <groupId>org.Apache.lucene</groupId>
        <artifactId>lucene-Snowball</artifactId>
        <version>3.0.3</version>
        <scope>test</scope>
</dependency>

Exemple de code:

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
}
0
Tho

Essayez celui-ci ici: http://www.twinword.com/lemmatizer.php

J'ai saisi votre requête dans la démo "cats running ran cactus cactuses cacti community communities" et obtenu ["cat", "running", "run", "cactus", "cactus", "cactus", "community", "community"] avec l'indicateur facultatif ALL_TOKENS.

Exemple de code

Ceci est une API afin que vous puissiez vous y connecter à partir de n'importe quel environnement. Voici à quoi l’appel PHP REST peut ressembler.

// 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"
  )
);
0
Joseph Shih

Martin Porter a écrit Snowball (un langage permettant de résoudre des algorithmes) et a réécrit "English Stemmer" dans Snowball. Il existe un Stemmer anglais pour C et Java.

Il déclare explicitement que le Porter Stemmer a été réimplémenté seulement pour des raisons historiques. Par conséquent, si vous testez la vérité sur le Porter Stemmer, vous obtiendrez des résultats que vous (devriez) déjà connaître.

De http://tartarus.org/~martin/PorterStemmer/index.html (c'est moi qui souligne)

Le terme Porter doit être considéré comme «congelé», c’est-à-dire strictement défini et ne pouvant faire l’objet d’autres modifications. En tant que stemmer, il est légèrement inférieur à celui de Snowball English ou de Porter2 stemmer, qui en dérive et qui est sujet à des améliorations occasionnelles. Par conséquent, pour les travaux pratiques, le nouvel appareil de contrôle de la boule de neige est recommandé. Porter stemmer convient aux travaux de recherche IR impliquant des essais où les expériences doivent être exactement reproductibles.

Le Dr Porter suggère d'utiliser les souches anglais ou Porter2 au lieu de la souche Porter. Le stemmer anglais est ce qui est réellement utilisé dans le site de démonstration comme @StompChicken a répondu plus tôt.

0
Oerd