L'extraction de tous les Noms à partir d'un fichier texte à l'aide nltk
Est-il un moyen plus efficace de faire cela?
Mon code se lit un fichier texte et des extraits de tous les Noms.
import nltk
File = open(fileName) #open file
lines = File.read() #read all lines
sentences = nltk.sent_tokenize(lines) #tokenize sentences
nouns = [] #empty to array to hold all nouns
for sentence in sentences:
for word,pos in nltk.pos_tag(nltk.word_tokenize(str(sentence))):
if (pos == 'NN' or pos == 'NNP' or pos == 'NNS' or pos == 'NNPS'):
nouns.append(word)
Comment puis-je réduire le temps de la complexité de ce code? Est-il un moyen d'éviter d'utiliser les boucles for imbriquées?
Merci d'avance!
- Remplacer la condition si avec
if pos.startswith('NN'):
, également utiliser unset
oucollections.Counter
, ne le gardez pas une liste. Et faire un peu de map/reduce au lieu d'une compréhension de liste. Sinon, essayez deshallow parsing
, akachunking
Vous devez vous connecter pour publier un commentaire.
Si vous êtes ouvert à d'autres options que
NLTK
, découvrezTextBlob
. Il extrait tous les noms et les expressions nominales facilement:blob.tags
pour filtrerNN
seulement quelque chose comme[n for n,t in blob.tags if t == 'NN']
.TextBlob
n'est pas presque aussi bien quenltk
textblob
appelle la NLTK pour marquer et tag. Ce pas réduire le "temps de la complexité" de l'OP du code.Astuce utile: c'est souvent le cas que les interprétations de la liste sont une méthode plus rapide de la construction d'une liste que l'ajout d'éléments à une liste avec les .insert() ou append() la méthode, au sein d'un 'pour' boucle.
is_noun = lambda pos: True if pos[:2] == 'NN'
. Remarque: la Liste de la compréhension n'est pas nécessaire plus rapidement que pour la boucle. C'est juste que vous n'avez pas à matérialiser une liste et de les traiter avec des boucles imbriquées comme des générateurs au lieu de la liste.... pos[:2] == 'NN'...
, car il peut correspondre indésirables des chaînes de caractères. Pour autant que je sache, il y a peut être unpos
qui a une valeur de "NNA", et nous ne voulons pas correspondre à ce que. Strictement parlant, leTrue if
etelse False
pièces ne sont pas nécessaires non plus, mais je les ai inclus pour plus de clarté. Bon point sur les interprétations de la liste n'étant pas forcément plus rapide qu'une boucle (je suppose que j'étais glib, il ya) - j'ai édité le post en conséquence.Vous pouvez obtenir de bons résultats en utilisant
nltk
,Textblob
,SpaCy
ou une des nombreuses autres bibliothèques. Ces bibliothèques seront tous faire le travail, mais avec différents degrés d'efficacité.Sur mon windows 10 2 cœurs, 4 processeurs, 8GO de ram, i5 hp ordinateur portable, dans jupyter ordinateur portable, j'ai couru quelques comparaisons et voici les résultats.
Pour TextBlob:
Et la sortie est
Pour nltk:
Et la sortie est
Pour spacy:
Et la sortie est
Il semble
nltk
etTextBlob
sont raisonnablement plus vite et ce n'est à prévoir puisque store rien d'autre à propos de la saisie de texte,txt
. Spacy est beaucoup plus lent. Une chose de plus.SpaCy
manqué le nomNLP
toutnltk
etTextBlob
l'a obtenu. Je voudrais lancer pournltk
ouTextBlob
sauf si il y a autre chose que je souhaite extraire à partir de l'entréetxt
.Découvrez un démarrage rapide en
spacy
ici.Découvrez quelques notions de base sur
TextBlob
ici.Découvrez
nltk
HowTos iciJe ne suis pas un expert en PNL, mais je pense que vous êtes assez proche déjà, et il n'est probablement pas un moyen d'obtenir de mieux que de complexité quadratique du temps dans ces boucles externes ici.
Les versions récentes de NLTK ont une fonction intégrée qui fait ce que vous êtes en train de faire à la main, nltk.la balise.pos_tag_sents, et elle renvoie une liste de listes de tagged mots.
Votre code n'a pas de redondance: Vous lisez le fichier une fois et visiter chaque phrase, et chaque tagged mot, exactement une fois. Peu importe la façon dont vous écrivez votre code (par exemple, l'utilisation des inclusions), vous aurez seulement à se cacher de boucles imbriquées, de ne pas sauter tout traitement.
Le seul potentiel d'amélioration est dans son espace de la complexité: au Lieu de lire le fichier en entier à la fois, vous pouvez lire en tranches. Mais puisque vous avez besoin pour traiter toute une phrase à la fois, il n'est pas aussi simple que la lecture et la transformation d'une ligne à la fois; je ne voudrais pas la peine, sauf si vos fichiers sont des giga-octets de long; pour les courts de fichiers, il ne va pas faire toute la différence.
En bref, vos boucles sont très bien. Il y a une chose ou deux dans votre code que vous pouvez nettoyer (par exemple, la
if
clause qui correspond à l'ENCAISSEMENT des balises), mais il ne va pas changer quoi que ce soit de l'efficacité-sage.