Comparez le travail de Python open source - bibliothèques pour la reconnaissance des entités nommées

introduction


Nous, dans l'entreprise, créons un service qui vous permet de créer, gérer et stocker automatiquement en toute sécurité des accords de licence et d'autres accords entre les indépendants et leurs clients.

Pour résoudre ce problème, j'ai essayé des dizaines de solutions dans le domaine du traitement du langage naturel, y compris des solutions open source et je voudrais partager mon expérience avec les bibliothèques Python open source pour reconnaître les entités nommées.

Entités nommées reconnues


Quelques mots sur le problème lui-même. La reconnaissance d'entité nommée (NER) est une branche de la technologie de traitement du langage humain, dont l'implémentation logicielle permet de trouver des catégories objectivées de mots et de phrases dans la parole et le texte. Au début, il s'agissait de noms géographiques, de noms de personnes, d'organisations, d'adresses, mais maintenant ce concept a été largement développé et avec l'aide de NER, nous recherchons des dates, des nombres, des nombres relatifs et absolus, etc.
L'identification des entités nommées est la «passerelle» vers le langage humain, elle permet d'identifier et de traiter les intentions d'une personne, d'établir la connexion des mots dans son discours et le monde réel.


Inégalité linguistique


Pour commencer, je voudrais attirer l'attention sur l'inégalité évidente dans les solutions logicielles pour différentes langues. Ainsi, la plupart des développements (y compris ceux créés par des programmeurs russes) fonctionnent avec l'anglais. Trouver des modèles prêts à l'emploi pour le bahasa, l'hindi ou l'arabe est une tâche ingrate.

Les langues européennes sont pour le moins représentées dans les bibliothèques les plus populaires; les langues africaines n'existent pas en principe dans le traitement du langage naturel moderne. Pendant ce temps, d'après ma propre expérience, je sais que le continent africain est un marché immense et riche, et cette attitude est très probablement l'inertie du marché.

Il existe plusieurs solutions pour la langue russe qui sont surprenantes par leur qualité, cependant, elles ne ressentent pas une puissance commerciale et un potentiel académique tels que les bibliothèques développées "construites" pour traiter l'anglais.

Texte à traiter


J'ai pris plusieurs suggestions de différentes sources, et les ai combinées en un texte quelque peu hypnotique pour tester dans quelle mesure les bibliothèques sélectionnées feraient leur travail.

english_text = ''' I want a person available 7 days and with prompt response all most every time. Only Indian freelancer need I need PHP developer who have strong experience in Laravel and Codeigniter framework for daily 4 hours. I need this work by Monday 27th Jan. should be free from plagiarism . 
Need SAP FICO consultant for support project needs to be work on 6 months on FI AREAWe.  Want a same site to be created as the same as this https://www.facebook.com/?ref=logo, please check the site before contacting to me and i want this site to be ready in 10 days. They will be ready at noon tomorrow .'''

russian_text = '''   110     ,     .        https://www.sobyanin.ru/  , 1 .     .51 (   :  , )  ?     2107   47     24,    . 
 c        10  1970 ,     -, . ,  5/1 8 000 ( )  00  .               .              - .'''



Bibliothèque NLTK


NLTK est une bibliothèque classique pour le traitement du langage naturel, elle est facile à utiliser, ne nécessite pas d'étude à long terme et effectue 99% des tâches qui peuvent survenir lors de la résolution des problèmes des élèves.
import nltk
nltk.download('punkt')
nltk.download('averaged_perceptron_tagger')
nltk.download('maxent_ne_chunker')
nltk.download('words')
for sent in nltk.sent_tokenize(english_text):
   for chunk in nltk.ne_chunk(nltk.pos_tag(nltk.word_tokenize(sent))):
      if hasattr(chunk, 'label'):
         print(chunk)

Sortie: Comme nous pouvons le voir, NLTK a fait du bon travail, cependant, pour rendre le résultat plus riche, nous devrons former notre propre tagueur (ou en choisir un autre dans une liste assez large). Mais en vaut-il la peine en 2020 s'il existe des solutions plus simples?
(GPE Indian/JJ)
(ORGANIZATION PHP/NNP)
(GPE Laravel/NNP)
(PERSON Need/NNP)
(ORGANIZATION SAP/NNP)
(ORGANIZATION FI/NNP)




Stanford CoreNLP


image

Une façon d'étendre les capacités de NLTK consiste à utiliser la bibliothèque Java classique de Stanford CoreNLP avec la bibliothèque Python classique. La qualité s'améliore considérablement, avec des exigences relativement faibles.
from nltk.tag.stanford import StanfordNERTagger
jar = "stanford-ner-2015-04-20/stanford-ner-3.5.2.jar"
model = "stanford-ner-2015-04-20/classifiers/" 
st_3class = StanfordNERTagger(model + "english.all.3class.distsim.crf.ser.gz", jar, encoding='utf8') 
st_4class = StanfordNERTagger(model + "english.conll.4class.distsim.crf.ser.gz", jar, encoding='utf8') 
st_7class = StanfordNERTagger(model + "english.muc.7class.distsim.crf.ser.gz", jar, encoding='utf8')
for i in [st_3class.tag(english_text.split()), st_4class.tag(english_text.split()), st_7class.tag(english_text.split())]:
  for b in i:
    if b[1] != 'O':
        print(b)

Sortie: Comme nous pouvons le voir, la qualité de la sortie s'est considérablement améliorée, et maintenant, compte tenu de la vitesse et de la facilité d'utilisation, il est évident que NLTK est également tout à fait adapté aux applications industrielles.
('PHP', 'ORGANIZATION')
('Laravel', 'LOCATION')
('Indian', 'MISC')
('PHP', 'ORGANIZATION')
('Laravel', 'LOCATION')
('Codeigniter', 'PERSON')
('SAP', 'ORGANIZATION')
('FICO', 'ORGANIZATION')
('PHP', 'ORGANIZATION')
('Laravel', 'LOCATION')
('Monday', 'DATE')
('27th', 'DATE')
('Jan.', 'DATE')
('SAP', 'ORGANIZATION')



Spacy



image

Spacy est une bibliothèque Python open source pour le traitement du langage naturel, elle est publiée sous licence MIT (!), Elle a été créée et développée par Matthew Hannibal et Ines Montany, fondateurs de la société de développement Explosion.
En règle générale, tous ceux qui sont confrontés à la nécessité de résoudre certains problèmes de traitement d'une langue naturelle apprendront tôt ou tard cette bibliothèque. La plupart des fonctions sont accessibles «prêtes à l'emploi», les développeurs veillent à ce que la bibliothèque soit facile à utiliser.
Space propose 18 balises qui marquent les entités nommées, ainsi qu'un moyen simple de recycler votre propre modèle. Ajoutez une excellente documentation, une énorme communauté et un bon support ici - et il sera clair pourquoi cette solution est devenue si populaire au cours des deux dernières années.

import spacy
model_sp = en_core_web_lg.load()
for ent in model_sp(english_text).ents:
  print(ent.text.strip(), ent.label_)

Sortie: Comme vous pouvez le voir, le résultat est bien meilleur et le code est beaucoup plus simple et plus compréhensible. Inconvénients du travail - un grand poids de modèles, un fonctionnement lent, des "balises" relativement illogiques, un manque de modèles pour de nombreuses langues, y compris le russe (bien qu'il existe des modèles multilingues).
7 days DATE
New York GPE
Indian NORP
Laravel LOC
Codeigniter NORP
4 hours TIME
Monday 27th Jan. DATE
FICO ORG
6 months DATE
10 days DATE
noon TIME
tomorrow DATE
Iceland GPE



Flair


image

Flair offre une immersion beaucoup plus profonde dans le domaine, la bibliothèque a été créée, en fait, pour résoudre les problèmes de recherche, la documentation n'est pas mauvaise, mais avec quelques échecs, il y a intégration avec un grand nombre d'autres bibliothèques, code clair, logique et lisible.
La bibliothèque a une communauté développée, et non seulement orientée vers l'anglais, en raison du grand nombre de modèles disponibles, Flair est beaucoup plus démocratique dans le choix des langues que Spacy.
from flair.models import SequenceTagger
tagger = SequenceTagger.load('ner')
from flair.data import Sentence
s = Sentence(english_text)
tagger.predict(s)
for entity in s.get_spans('ner'):
    print(entity)

Résultat: Comme vous pouvez le voir, le modèle formé n'a pas fonctionné de la meilleure façon. Cependant, peu de gens utilisent Flair «prêt à l'emploi» - c'est principalement une bibliothèque pour créer leurs propres outils. La même chose, avec des réserves, peut être dite à propos de la prochaine bibliothèque.
Span [6,7]: "7 days" [− Labels: DATE (0.9329)]
Span [17]: "Indian" [− Labels: NORP (0.9994)]
Span [35,36]: "4 hours." [− Labels: TIME (0.7594)]
Span [42,43,44]: "Monday 27th Jan." [− Labels: DATE (0.9109)]
Span [53]: "FICO" [− Labels: ORG (0.6987)]
Span [63,64]: "6 months" [− Labels: DATE (0.9412)]
Span [98,99]: "10 days." [− Labels: DATE (0.9320)]
Span [105,106]: "noon tomorrow" [− Labels: TIME (0.8667)]




Deeppavlov


image
DeepPavlov est une bibliothèque open source construite par TensorFlow et Keras.

Les développeurs suggèrent d'utiliser le système principalement pour les systèmes «conversationnels», les robots de discussion, etc., mais la bibliothèque est également excellente pour résoudre les problèmes de recherche. L'utiliser «en production» sans travail sérieux pour «personnaliser» et «finir» la solution est une tâche qui, semble-t-il, n'est même pas suggérée par les créateurs du MIPT.
L'approche étrange et illogique de l'architecture du code, qui contredit Python Zen, apporte néanmoins de bons résultats si vous passez suffisamment de temps pour y faire face.
from deeppavlov import configs, build_model
from deeppavlov import build_model, configs

ner_model = build_model(configs.ner.ner_ontonotes_bert, download=True)
result = ner_model([english_text])
for i in range(len(result[0][0])):
     if result [1][0][i] != 'O':
         print(result[0][0][i], result[1][0][i])

Sortie: Le résultat est prévisible, compréhensible, détaillé et l'un des meilleurs. Le modèle lui-même peut également être utilisé directement dans Hugging Face Transformers, ce qui supprime, à bien des égards, les prétentions à l'architecture de code.
7 B-DATE
days I-DATE
Indian B-NORP
Laravel B-PRODUCT
Codeigniter B-PRODUCT
daily B-DATE
4 B-TIME
hours I-TIME
Monday B-DATE
27th I-DATE
Jan I-DATE
6 B-DATE
months I-DATE
FI B-PRODUCT
AREAWe I-PRODUCT
10 B-DATE
days I-DATE
noon B-TIME
tomorrow B-DATE




deepmipt / ner


Il s'agit en fait de la bibliothèque avec laquelle Deep Pavlov a commencé. Il peut être utilisé pour comprendre l'orientation des pensées des développeurs et les progrès qu'ils ont réalisés.
import ner
example = russian_text
def deepmint_ner(text):
  extractor = ner.Extractor()
  for m in extractor(text):
     print(m)
deepmint_ner(example)

Production:
Match(tokens=[Token(span=(7, 13), text='')], span=Span(start=7, end=13), type='LOC')
Match(tokens=[Token(span=(492, 499), text='')], span=Span(start=492, end=499), type='PER')
Match(tokens=[Token(span=(511, 520), text=''), Token(span=(521, 525), text='')], span=Span(start=511, end=525), type='PER')
Match(tokens=[Token(span=(591, 600), text='')], span=Span(start=591, end=600), type='LOC')
Match(tokens=[Token(span=(814, 820), text=''), Token(span=(821, 829), text='')], span=Span(start=814, end=829), type='PER')


Polyglotte


L'une des plus anciennes bibliothèques, un travail rapide et un grand nombre de langues prises en charge la rendent toujours populaire. En revanche, la licence virale GPLv3 ne permet pas sa pleine utilisation en développement commercial.
from polyglot.text import Text
for ent in Text(english_text).entities:
 print(ent[0],ent.tag)

Sortie: Et pour la langue russe:
Laravel I-LOC
SAP I-ORG
FI I-ORG


!polyglot download embeddings2.ru ner2.ru
for ent in Text(russian_text).entities:
 print(ent[0],ent.tag)

Sortie: Le résultat n'est pas le meilleur, mais la vitesse et un bon support peuvent l'améliorer si vous faites un effort.
24 I-ORG
I-PER
I-LOC
I-PER
I-ORG
I-PER




AdaptNLP


image
Une autre nouvelle bibliothèque avec un seuil d'entrée extrêmement bas pour le chercheur.
AdaptNLP permet aux utilisateurs, des étudiants aux ingénieurs de données expérimentés, d'utiliser des modèles de PNL et des méthodes de formation modernes.
La bibliothèque est construite au-dessus des bibliothèques populaires Flair et Hugging Face Transformers.

from adaptnlp import EasyTokenTagger
tagger = EasyTokenTagger()
sentences = tagger.tag_text(
    text = english_text, model_name_or_path = "ner-ontonotes"
)
spans = sentences[0].get_spans("ner")
for sen in sentences:
    for entity in sen.get_spans("ner"):
        print(entity)

Sortie: Le résultat est acceptable, mais la bibliothèque vous permet d'utiliser une variété de modèles pour terminer la tâche, et il peut être amélioré à plusieurs reprises si vous faites des efforts (mais pourquoi, si vous avez Flair et Hugging Face Transformers directement). Néanmoins, la simplicité, une grande liste de tâches et une bonne architecture, ainsi que les efforts systématiques des développeurs nous permettent d'espérer que la bibliothèque a un avenir.
DATE-span [6,7]: "7 days"
NORP-span [18]: "Indian"
PRODUCT-span [30]: "Laravel"
TIME-span [35,36,37]: "daily 4 hours"
DATE-span [44,45,46]: "Monday 27th Jan."
ORG-span [55]: "FICO"
DATE-span [65,66]: "6 months"
DATE-span [108,109]: "10 days"
TIME-span [116,117]: "noon tomorrow"




Strophe


image
Stanza de StanfordNlp est un cadeau aux développeurs en 2020 de l'Université de Stanford. Ce qui manquait à Spacy, c'était le multilinguisme, une immersion profonde dans la langue et une facilité d'utilisation.
Si la communauté soutient cette bibliothèque, elle a toutes les chances de devenir l'une des plus populaires.
import stanza
stanza.download('en')
def stanza_nlp(text):
  nlp = stanza.Pipeline(lang='en', processors='tokenize,ner')
  doc = nlp(text)
  print(*[f'entity: {ent.text}\ttype: {ent.type}' for sent in doc.sentences for ent in sent.ents], sep='\n')
stanza_nlp(english_text)

Sortie: Et pour la langue russe:
entity: 7 days type: DATE
entity: Indian type: NORP
entity: Laravel type: ORG
entity: Codeigniter type: PRODUCT
entity: daily 4 hours type: TIME
entity: Monday 27th Jan. type: DATE
entity: SAP type: ORG
entity: FICO type: ORG
entity: 6 months type: DATE
entity: FI AREAWe type: ORG
entity: 10 days type: DATE
entity: noon tomorrow type: TIME



import stanza
stanza.download('ru')
def stanza_nlp_ru(text):
  nlp = stanza.Pipeline(lang='ru', processors='tokenize,ner')
  doc = nlp(text)
  print(*[f'entity: {ent.text}\ttype: {ent.type}' for sent in doc.sentences for ent in sent.ents], sep='\n')
stanza_nlp_ru(russian_text)

Sortie: travail rapide, beau code, bon résultat.
2020-05-15 08:01:18 INFO: Use device: cpu
2020-05-15 08:01:18 INFO: Loading: tokenize
2020-05-15 08:01:18 INFO: Loading: ner
2020-05-15 08:01:19 INFO: Done loading processors!
entity: type: LOC
entity: type: LOC
entity: type: PER
entity: 2107 type: MISC
entity: 47 type: MISC
entity: 24 type: MISC
entity: type: PER
entity: - type: LOC
entity: . type: LOC
entity: type: LOC
entity: type: LOC
entity: type: PER




Allennlp


image
Bibliothèque de recherche, construite sur PyTorch /
D'une part - architecture simple et vitesse rapide, d'autre part, les développeurs changent constamment quelque chose dans l'architecture, ce qui affecte le travail de la bibliothèque dans son ensemble.
from allennlp.predictors.predictor import Predictor
import allennlp_models.ner.crf_tagger
predictor = Predictor.from_path("https://storage.googleapis.com/allennlp-public-models/ner-model-2020.02.10.tar.gz")
allen_result = predictor.predict(
  sentence=english_text
)
for i in zip(allen_result['tags'], allen_result['words']):
    if (i[0]) != 'O':
      print(i)

Sortie:
('U-MISC', 'Indian') ('U-MISC', '
PHP')
('U-MISC', 'Laravel')
('U-MISC', 'Codeigniter')
('B- ORG ',' SAP ')
(' L-ORG ',' FICO ')
Le module fonctionne rapidement, mais le résultat est inacceptable.

Hanlp


image
HanLP est l'une des bibliothèques open source de développeurs chinois. Un projet intelligent, bien développé et actif, qui, il me semble, trouvera sa niche au-delà des frontières de l'Empire céleste.
Bibliothèque PNL pour chercheurs et entreprises créée sur TensorFlow 2.0.
HanLP est livré avec des modèles pré-préparés pour différentes langues, dont l'anglais, le chinois et bien d'autres.
Le seul problème est la qualité des "sauts" de sortie après chaque mise à jour de la bibliothèque.
recognizer = hanlp.load(hanlp.pretrained.ner.MSRA_NER_BERT_BASE_ZH)
recognizer([list('上海华安工业(集团)公司董事长谭旭光和秘书张晚霞来到美国纽约现代艺术博物馆参观。'),
                list('萨哈夫说,伊拉克将同联合国销毁伊拉克大规模杀伤性武器特别委员会继续保持合作。')])

Production:

[[('上海华安工业(集团)公司', 'NT', 0, 12), ('谭旭光', 'NR', 15, 18),
('张晚霞', 'NR', 21, 24),
('美国', 'NS', 26, 28),
('纽约现代艺术博物馆', 'NS', 28, 37)],
[('萨哈夫', 'NR', 0, 3),
('伊拉克', 'NS', 5, 8),
('联合国销毁伊拉克大规模杀伤性武器特别委员会', 'NT', 10, 31)]]


import hanlp
tokenizer = hanlp.utils.rules.tokenize_english
testing = tokenizer('Need SAP FICO consultant for support project needs to be work on 6 months on FI AREAWe')
recognizer = hanlp.load(hanlp.pretrained.ner.CONLL03_NER_BERT_BASE_UNCASED_EN)
recognizer(testing)

Sortie: Pour l'anglais, le résultat est instable, mais cela est résolu en utilisant le tokenizer de NLTK.
[('SAP FICO', 'ORG', 1, 3)]




PullEnti


Bibliothèque C # pour NER en russe. En 2016, elle a remporté la première place du concours factRuEval-2016. En 2018, l'auteur a porté le code sur Java et Python.
Probablement la plus jolie solution pour la langue russe.
Rapidement, profondément, avec une attention aux détails. La décision est fondée sur des règles, ce qui limite naturellement son développement, mais son autonomie, sa rapidité et ses résultats permettent d'espérer le développement du projet.
Il existe un wrapper python pour la bibliothèque, bien qu'il semble «abandonné».
from pullenti_wrapper.processor import (
    Processor,
    MONEY,
    URI,
    PHONE,
    DATE,
    KEYWORD,
    DEFINITION,
    DENOMINATION,
    MEASURE,
    BANK,
    GEO,
    ADDRESS,
    ORGANIZATION,
    PERSON,
    MAIL,
    TRANSPORT,
    DECREE,
    INSTRUMENT,
    TITLEPAGE,
    BOOKLINK,
    BUSINESS,
    NAMEDENTITY,
    WEAPON,
)

processor = Processor([PERSON, ORGANIZATION, GEO, DATE, MONEY])
text = russian_text
result = processor(text)
result.graph


Production:image

Natasha


image
Natasha, cela semble être l'un des principaux projets de PNL pour la langue russe. Il a une longue histoire, et a commencé avec une solution basée sur des règles qui a été développée par le populaire Yargy Parser, et résout maintenant les principales tâches de PNL pour la langue russe: tokenisation, segmentation de phrase, lemmatisation, normalisation de phrase, analyse, marquage NER, extraction de faits.
from natasha import (
    Segmenter,
    MorphVocab,
    
    NewsEmbedding,
    NewsMorphTagger,
    NewsSyntaxParser,
    NewsNERTagger,
    
    PER,
    NamesExtractor,

    Doc
)

segmenter = Segmenter()
morph_vocab = MorphVocab()

emb = NewsEmbedding()
morph_tagger = NewsMorphTagger(emb)
syntax_parser = NewsSyntaxParser(emb)
ner_tagger = NewsNERTagger(emb)

names_extractor = NamesExtractor(morph_vocab)

doc = Doc(russian_text)

Sortie: Le résultat, malheureusement, n'est pas stable, contrairement aux règles personnalisées de Yargy Parser du même développeur, cependant, le projet se développe activement et montre un résultat décent pour une utilisation commerciale.
110 ,
LOC───
.
https://www.sobyanin.ru/ , 1 .
.51 ( :
LOC───────────────
, ) ?
ORG PER────────────
2107 47
24, .
ORG──
c
PER────────────────
10 1970 ,
─────────
-, . , 5/1 8 000 ( )
LOC──────────── PER─────────
00
LO
.

PER────────────
- .




intello


Le dernier module est un projet privé, pas particulièrement populaire, construit au-dessus de Spacy et Thinc et, néanmoins, digne d'attention à l'approche choisie pour l'architecture (accent mis sur la facilité d'utilisation).
from nerd import ner
doc_nerd_d = ner.name(english_text)
text_label = [(X.text, X.label_) for X in doc_nerd_d]
print(text_label)


Résultat: De tous les projets, le plus «équilibré» et le plus pratique, avec des résultats acceptables et une facilité d'utilisation me semble être Stanza de StanfordNlp - le travail de la plupart des langues prêtes à l'emploi, une étude académique de haute qualité et le soutien de la communauté scientifique de l'université elle-même font du projet le plus prometteur, à mon avis . La prochaine fois, je partagerai mon expérience de travail avec des solutions «fermées» et l'API proposée pour le traitement du langage naturel. Tout le code disponible par Google Colab
[('7 days', 'DATE'), ('Indian', 'NORP'), ('PHP', 'ORG'), ('Laravel', 'GPE'), ('daily 4 hours', 'DATE'), ('Monday 27th Jan.', 'DATE'), ('Need SAP FICO', 'PERSON'), ('6 months', 'DATE'), ('10 days', 'DATE'), ('noon', 'TIME'), ('tomorrow', 'DATE')]







All Articles