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:
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.
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.
J'ai essayé votre liste de termes sur ce site de démonstration de Snowball et les résultats semblent corrects ....
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.
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é.
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'
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é.
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.
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', '.']
Regardez dans WordNet, une grande base de données lexicale en anglais:
Il existe des API pour y accéder dans plusieurs langues.
Cela semble intéressant: MIT Java WordnetStemmer: http://projects.csail.mit.edu/jwi/api/edu/mit/jwi/morph/WordnetStemmer. html
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 )
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.
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
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"
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
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.
.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)
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!
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
}
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"
)
);
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.