Comment puis-je procéder à un écaillage de mots ou à une lemmatisation?

J'ai essayé PorterStemmer et boule de neige, mais les deux ne fonctionnent pas sur tous les mots, manquant certains très communs.

mes mots d'essai sont:" cats running ran cactus cactus community communities ", et les deux obtiennent moins de la moitié droite.

Voir aussi:

  • algorithme de bourrage qui produit des mots réels
  • Découlant des exemples de code ou de projets open source?
97
demandé sur Community 2009-04-21 14:07:03

20 réponses

si vous connaissez Python, le Natural Language Toolkit (NLTK) a un lemmatizer très puissant qui fait usage de WordNet .

Notez que si vous utilisez cette lemmatizer 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 à le faire qu'une fois. En supposant que vous avez maintenant 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 lemmatizers dans le nltk.module stem , mais je ne les ai pas essayés moi-même.

132
répondu theycallmemorty 2017-10-02 17:22:30

j'utilise stanford pnl pour effectuer la lemmatisation. J'ai eu un problème similaire ces derniers jours. Merci à 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 pourrait également être une bonne idée d'utiliser des mots d'arrêt pour minimiser les lemmes de sortie si elle est utilisée plus tard dans classificator. Merci de prendre un coup d'oeil à coreNlp extension écrit par John Conwell.

28
répondu CTsiddharth 2016-01-27 19:50:20

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

  • chats -> chat
  • en cours d'exécution -> exécuter
  • ran -> couru
  • cactus -> cactus
  • cactus - > cactus
  • communauté - > communiti
  • communautés - > communiti

Un stemmer est censé faire tomber les formes infléchies de mots à une racine commune. Ce n'est pas vraiment le travail d'un stemmer de faire de cette racine un mot du dictionnaire "correct". Pour cela vous avez besoin de regarder morphologiques/orthographique analyseurs .

je pense cette question , c'est plus ou moins la même chose, et Kaarel la réponse à cette question est de savoir où j'ai pris le deuxième lien.

25
répondu Stompchicken 2017-05-23 12:03:05

La stemmer vs lemmatizer débats. Il s'agit de préférer la précision à l'efficacité. Vous devriez lemmatize pour réaliser des unités linguistiquement significatives et de la tige pour utiliser le jus de calcul minimal et encore indexer 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'
18
répondu alvas 2017-05-23 11:47:15

la page officielle de Martin Porter contient un Porter Stemmer en PHP ainsi que autres langues .

si vous êtes vraiment sérieux au sujet de bon stemming même si vous allez avoir 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, et puis finalement ajouter beaucoup d'exceptions aux règles. Ceci peut être facilement mis en œuvre avec des paires clé/valeur (dbm/hash/dictionnaires) où la clé est le mot à rechercher et la valeur de l'découle mot pour remplacer l'original. Un moteur de recherche commercial sur lequel j'ai travaillé une fois a fini avec 800 quelques exceptions à un algorithme de Porter modifié.

8
répondu Van Gale 2009-04-21 10:59:58

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

pour beaucoup de mes projets, je préfère le WordNet lemmatizer basé sur le lexicon au porter plus agressif.

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

5
répondu msbmsb 2009-04-21 16:42:10

regardez WordNet, une grande base de données lexicales pour la langue anglaise:

http://wordnet.princeton.edu /

il y a des API pour y accéder en plusieurs langues.

3
répondu Ricardo J. Méndez 2009-04-21 13:52:22

basé sur diverses réponses sur le débordement de la pile et les blogs que j'ai rencontrés, c'est la méthode que j'utilise, et il semble retourner de vrais mots assez bien. L'idée est de diviser le texte entrant en un tableau de mots (utilisez la méthode que vous voulez), puis de trouver les parties de la parole (POS) pour ces mots et de l'utiliser pour aider la tige et lemmatize les mots.

vous êtes échantillon ci-dessus ne fonctionne pas trop bien, parce que le point de vente ne peut pas être déterminé. Cependant, si nous utilisons un réel phrase, les choses marchent 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', '.']
3
répondu cjbarth 2018-02-22 15:43:53

ça a l'air intéressant.: MIT Java WordnetStemmer: http://projects.csail.mit.edu/jwi/api/edu/mit/jwi/morph/WordnetStemmer.html

2
répondu user382903 2012-10-29 06:37:36

regardez LemmaGen - bibliothèque open source écrit en C# 3.0.

résultats pour vos mots d'essai ( http://lemmatise.ijs.si/Services )

  • chats -> chat
  • running
  • ran -> exécuter
  • cactus
  • cactus - > cactus
  • cactus -> cactus
  • la communauté
  • communautés - > communauté
2
répondu Alex 2014-05-17 22:27:32

faites une recherche pour Lucene, Je ne suis pas sûr s'il y a un port PHP mais je sais que Lucene est disponible pour de nombreuses plateformes. Lucene est une bibliothèque D'index et de recherche OSS (D'Apache). Naturellement lui et les extras de la communauté pourraient avoir quelque chose d'intéressant à regarder. Au minimum, vous pouvez apprendre comment il est fait dans une langue afin que vous puissiez traduire l '"idée" en PHP

1
répondu mP. 2009-04-21 10:17:32

si je peux citer ma réponse à la question StompChicken mentionné:

la question centrale ici est que les algorithmes de bourrage fonctionnent sur une base phonétique sans aucune compréhension réelle du langage avec lequel ils travaillent.

comme ils n'ont aucune compréhension de la langue et ne fuient pas un dictionnaire de termes, ils n'ont aucun moyen de reconnaître et de répondre de façon appropriée aux cas irréguliers, tels que "run"/"ran".

si vous avez besoin de gérer les cas irréguliers, vous aurez besoin de choisir une approche différente ou d'augmenter votre bourrage avec votre propre dictionnaire personnalisé de corrections à exécuter après que le stemmer a fait sa chose.

1
répondu Dave Sherohman 2009-04-21 11:07:17

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

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
répondu Edmon 2012-04-06 03:14:05

vous pouvez utiliser la Morpha stemmer. UW a envoyé morpha stemmer à Maven central si vous prévoyez de l'utiliser à partir d'une application Java. Il y a un papier qui le rend plus facile à utiliser. Vous avez juste besoin 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 original avait des champs de classe pour les variables locales inutilement). Instanciez une classe et lancez morpha et le mot que vous voulez créer.

new MorphaStemmer().morpha("climbed") // goes to "climb"
1
répondu schmmd 2012-05-23 17:53:26

. Vous pouvez essayer. Mais notez que porter stemming ne prend pas en compte le contexte des mots lors de la dérivation du lemme. (Passez en revue l'algorithme et son implémentation et vous verrez comment il fonctionne)

0
répondu Erik 2013-03-05 20:02:16

Martin Porter a écrit boule de neige (un langage pour les algorithmes de bourrage) et réécrit le "Stemmer anglais" dans boule de neige. Il y a un Stemmer anglais pour C et Java.

il déclare explicitement que le Porter Stemmer a été réimplementé seulement pour des raisons historiques, ainsi les tests de Stemmer la rectitude découlant contre le Porter Stemmer vous obtiendra des résultats que vous (devrait) déjà savoir.

de http://tartarus.org/~martin/PorterStemmer/index.html (l'emphase est mienne)

Le Portier de l'analyseur morphologique devraient être considérés comme des gelé ’, qui est, au sens strict, et ne se prête pas à une modification plus loin. Comme un stemmer, il est légèrement inférieur à la boule de neige anglais ou Porter2 stemmer, qui découle de lui, et qui est soumis à des améliorations occasionnelles. Pour le travail pratique, donc, le nouveau Stemmer boule de neige est recommandé. Bagagiste stemmer est approprié pour les travaux de recherche en IR impliquant le bourrage où les expériences doivent être exactement reproductibles.

le Dr Porter suggère d'utiliser les stemmers anglais ou Porter2 au lieu du Porter stemmer. Le stemmer anglais est ce qui est réellement utilisé dans le Démo site comme @StompChicken a répondu plus tôt.

0
répondu Oerd 2014-03-08 10:59:33

En Java, j'utilise tartargus-boule de neige à l'issu des mots

Maven:

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

code échantillon:

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
répondu ThoQ 2014-12-15 04:07:20

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

j'ai entré votre requête dans la démo "cats running ran cactus cactuses cacti community communities" et j'ai eu ["cat", "running", "run", "cactus", "cactus", "cactus", "community", "community"] avec le drapeau optionnel ALL_TOKENS .

Code Échantillon

C'est une API donc vous pouvez vous y connecter à partir de n'importe quel environnement. Voici à quoi peut ressembler L'appel de repos de PHP.

// 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
répondu Joseph Shih 2015-04-22 03:45:12

je recommande fortement d'utiliser Spacy (parsing de texte de base & tagging) et Textacy (traitement de texte de niveau supérieur construit sur le dessus de Spacy).

Lemmatisés mots sont disponibles par défaut dans Spacy comme un jeton .lemma_ attribut et le texte peuvent être lemmatisés en faisant beaucoup d'autres textes de prétraitement avec textacy. Par exemple tout en créant un sac de termes ou les mots ou généralement juste avant d'effectuer un traitement qui l'exige.

je vous encourage à vérifier les deux avant d'écrire un code, car cela peut vous faire gagner beaucoup de temps!

0
répondu QA Collective 2018-06-13 02:14:15
df_plots = pd.read_excel("Plot Summary.xlsx", index_col = 0)
df_plots
# Printing first sentence of first row and last sentence of last row
nltk.sent_tokenize(df_plots.loc[1].Plot)[0] + nltk.sent_tokenize(df_plots.loc[len(df)].Plot)[-1]

# Calculating length of all plots by words
df_plots["Length"] = df_plots.Plot.apply(lambda x : 
len(nltk.word_tokenize(x)))

print("Longest plot is for season"),
print(df_plots.Length.idxmax())

print("Shortest plot is for season"),
print(df_plots.Length.idxmin())



#What is this show about? (What are the top 3 words used , excluding the #stop words, in all the #seasons combined)

word_sample = list(["struggled", "died"])
word_list = nltk.pos_tag(word_sample)
[wnl.lemmatize(str(word_list[index][0]), pos = word_list[index][1][0].lower()) for index in range(len(word_list))]

# Figure out the stop words
stop = (stopwords.words('english'))

# Tokenize all the plots
df_plots["Tokenized"] = df_plots.Plot.apply(lambda x : nltk.word_tokenize(x.lower()))

# Remove the stop words
df_plots["Filtered"] = df_plots.Tokenized.apply(lambda x : (word for word in x if word not in stop))

# Lemmatize each word
wnl = WordNetLemmatizer()
df_plots["POS"] = df_plots.Filtered.apply(lambda x : nltk.pos_tag(list(x)))
# df_plots["POS"] = df_plots.POS.apply(lambda x : ((word[1] = word[1][0] for word in word_list) for word_list in x))
df_plots["Lemmatized"] = df_plots.POS.apply(lambda x : (wnl.lemmatize(x[index][0], pos = str(x[index][1][0]).lower()) for index in range(len(list(x)))))



#Which Season had the highest screenplay of "Jesse" compared to "Walt" 
#Screenplay of Jesse =(Occurences of "Jesse")/(Occurences of "Jesse"+ #Occurences of "Walt")

df_plots.groupby("Season").Tokenized.sum()

df_plots["Share"] = df_plots.groupby("Season").Tokenized.sum().apply(lambda x : float(x.count("jesse") * 100)/float(x.count("jesse") + x.count("walter") + x.count("walt")))

print("The highest times Jesse was mentioned compared to Walter/Walt was in season"),
print(df_plots["Share"].idxmax())
#float(df_plots.Tokenized.sum().count('jesse')) * 100 / #float((df_plots.Tokenized.sum().count('jesse') + #df_plots.Tokenized.sum().count('walt') + #df_plots.Tokenized.sum().count('walter')))
-1
répondu avi 2018-05-09 21:07:20