Spaczz fournit une correspondance floue et des fonctionnalités de correspondance regex supplémentaires pour Spacy. Les composants de Spaczz ont des API similaires à leurs homologues spacy et les composants du pipeline Spaczz peuvent s'intégrer dans des pipelines spacy où ils peuvent être enregistrés / chargés en tant que modèles.
La correspondance floue est actuellement réalisée avec des matchs du module Fuzz de RapidFuzz et de la correspondance Regex s'appuie actuellement sur la bibliothèque Regex. Spaczz prend certainement une influence supplémentaire d'autres bibliothèques et ressources. Pour plus de détails, voir la section des références.
Prend en charge Spacy> = 3.0
Spaczz a été testé sur Ubuntu, MacOS et Windows Server.
V0.6.0 Notes de version:
python<=3.11,>=3.7 , avec rapidfuzz>=1.0.0 .SpaczzRuler en option "spaczz_" . Aussi, désolé de le faire sans cycle de dépréciation.Matcher.pipe , qui ont été obsolètes, sont désormais supprimées.spaczz_span , qui a été obsolète, est désormais supprimé.Veuillez consulter le Changelog pour les notes de publication précédentes. Cela sera finalement déplacé vers la page de lecture du document.
Spaczz peut être installé à l'aide de PIP.
pip install spaczz Les principales caractéristiques de Spaczz sont le TokenMatcher FuzzyMatcher , RegexMatcher et "Fuzzy" qui fonctionne de manière similaire avec Matcher et PhraseMatcher de Spacy, et le SpaczzRuler qui intègre les matchs Spaczz dans un composant de pipeline Spacy similaire à Spacy's EntityRuler .
L'utilisation de base du Matcher Fuzzy est similaire à celle de PhraseMatcher de Spacy, sauf qu'elle renvoie le rapport flou et le modèle correspondant, ainsi que l'ID de correspondance, les informations de début et de fin, alors assurez-vous d'inclure des variables pour le rapport et le modèle lors du déballage des résultats.
import spacy
from spaczz . matcher import FuzzyMatcher
nlp = spacy . blank ( "en" )
text = """Grint M Anderson created spaczz in his home at 555 Fake St,
Apt 5 in Nashv1le, TN 55555-1234 in the US.""" # Spelling errors intentional.
doc = nlp ( text )
matcher = FuzzyMatcher ( nlp . vocab )
matcher . add ( "NAME" , [ nlp ( "Grant Andersen" )])
matcher . add ( "GPE" , [ nlp ( "Nashville" )])
matches = matcher ( doc )
for match_id , start , end , ratio , pattern in matches :
print ( match_id , doc [ start : end ], ratio , pattern ) NAME Grint M Anderson 80 Grant Andersen
GPE Nashv1le 82 Nashville
Contrairement aux matchs de spacy, les matchs Spaczz sont écrits en pur python. Bien qu'ils soient tenus de faire passer un vocabulaire spactif lors de l'initialisation, cela est purement pour la cohérence car les matchs Spaczz n'utilisent pas actuellement le vocabulaire Spacy. C'est pourquoi le match_id ci-dessus est simplement une chaîne au lieu d'une valeur entière comme dans Spacy Matchers.
Les matchs Spaczz peuvent également utiliser les règles de match via des fonctions de rappel. Ces rappels sur le match doivent accepter le matchur lui-même, le DOC le matchur a été appelé, l'index de matchs et les matchs produits par le Matcher.
import spacy
from spacy . tokens import Span
from spaczz . matcher import FuzzyMatcher
nlp = spacy . blank ( "en" )
text = """Grint M Anderson created spaczz in his home at 555 Fake St,
Apt 5 in Nashv1le, TN 55555-1234 in the US.""" # Spelling errors intentional.
doc = nlp ( text )
def add_name_ent ( matcher , doc , i , matches ):
"""Callback on match function. Adds "NAME" entities to doc."""
# Get the current match and create tuple of entity label, start and end.
# Append entity to the doc's entity. (Don't overwrite doc.ents!)
_match_id , start , end , _ratio , _pattern = matches [ i ]
entity = Span ( doc , start , end , label = "NAME" )
doc . ents += ( entity ,)
matcher = FuzzyMatcher ( nlp . vocab )
matcher . add ( "NAME" , [ nlp ( "Grant Andersen" )], on_match = add_name_ent )
matches = matcher ( doc )
for ent in doc . ents :
print (( ent . text , ent . start , ent . end , ent . label_ )) ('Grint M Anderson', 0, 3, 'NAME')
Comme EntityRuler de Spacy, une logique de mise à jour d'entité très similaire a été implémentée dans le SpaczzRuler . Le SpaczzRuler s'occupe également de gérer les matchs qui se chevauchent. Il est discuté dans une section ultérieure.
Contrairement aux correspondances de Spacy, les règles ajoutées aux matchs Spaczz ont des arguments de mots clés en option qui peuvent modifier le comportement de correspondance. Prenez les exemples de correspondance floue ci-dessous:
import spacy
from spaczz . matcher import FuzzyMatcher
nlp = spacy . blank ( "en" )
# Let's modify the order of the name in the text.
text = """Anderson, Grint created spaczz in his home at 555 Fake St,
Apt 5 in Nashv1le, TN 55555-1234 in the US.""" # Spelling errors intentional.
doc = nlp ( text )
matcher = FuzzyMatcher ( nlp . vocab )
matcher . add ( "NAME" , [ nlp ( "Grant Andersen" )])
matches = matcher ( doc )
# The default fuzzy matching settings will not find a match.
for match_id , start , end , ratio , pattern in matches :
print ( match_id , doc [ start : end ], ratio , pattern )Ensuite, nous modifions le comportement de correspondance floue pour le modèle dans la règle "Nom".
import spacy
from spaczz . matcher import FuzzyMatcher
nlp = spacy . blank ( "en" )
# Let's modify the order of the name in the text.
text = """Anderson, Grint created spaczz in his home at 555 Fake St,
Apt 5 in Nashv1le, TN 55555-1234 in the US.""" # Spelling errors intentional.
doc = nlp ( text )
matcher = FuzzyMatcher ( nlp . vocab )
matcher . add ( "NAME" , [ nlp ( "Grant Andersen" )], kwargs = [{ "fuzzy_func" : "token_sort" }])
matches = matcher ( doc )
# The default fuzzy matching settings will not find a match.
for match_id , start , end , ratio , pattern in matches :
print ( match_id , doc [ start : end ], ratio , pattern ) NAME Anderson, Grint 83 Grant Andersen
La liste complète des arguments de mots clés disponibles pour les paramètres de correspondance floue comprend:
ignore_case (bool): s'il faut le texte inférieur avant la correspondance. La valeur par défaut est True .min_r (int): rapport de correspondance minimum requis.thresh (int): Si ce rapport est dépassé dans le scan initial et flex > 0 , aucune optimisation ne sera tentée. Si flex == 0 , thresh n'a aucun effet. La valeur par défaut est 100 .fuzzy_func (STR): Nom de clé de la fonction de correspondance floue à utiliser. Toutes les fonctions de correspondance RapidFuzz avec des paramètres par défaut sont disponibles. Des fonctions de correspondance floues supplémentaires peuvent être enregistrées par les utilisateurs. La valeur par défaut est "simple" :"simple" = ratio"partial" = partial_ratio"token" = token_ratio"token_set" = token_set_ratio"token_sort" = token_sort_ratio"partial_token" = partial_token_ratio"partial_token_set" = partial_token_set_ratio"partial_token_sort" = partial_token_sort_ratio"weighted" = WRatio"quick" = QRatio"partial_alignment" = partial_ratio_alignment (nécessite rapidfuzz>=2.0.3 )flex (int | littéral ['par défaut', 'min', 'max']): nombre de jetons pour déplacer les limites de correspondance à gauche et à droite pendant l'optimisation. Peut être un int avec un maximum de len(pattern) et un min de 0 , (avertira et changera s'il est supérieur ou plus bas). "max" , "min" ou "default" sont également valides. La valeur par défaut est "default" : len(pattern) // 2 .min_r1 (int | Aucun): contrôle granulaire facultatif sur le rapport de correspondance minimum requis pour la sélection pendant le scan initial. Si flex == 0 , min_r1 sera écrasé par min_r2 . Si flex > 0 , min_r1 doit être inférieur à min_r2 et "Low" en général car les limites des correspondances ne sont pas fléchies initialement. La valeur par défaut None , ce qui entraînera le défilé min_r1 sur round(min_r / 1.5) . L'utilisation de base du Matcher Regex est également assez similaire à PhraseMatcher de Spacy. Il accepte les modèles regex comme des chaînes, les drapeaux doivent donc être en ligne. Les regex sont compilés avec le package Regex, donc l'appariement approximatif "flou" est pris en charge. Pour fournir un accès à ces résultats de correspondance "flou", le matchur renvoie un rapport flou calculé et un modèle correspondant, ainsi que l'ID de correspondance, les informations de début et de fin, alors assurez-vous d'inclure des variables pour le rapport et le modèle lors du déballage des résultats.
import spacy
from spaczz . matcher import RegexMatcher
nlp = spacy . blank ( "en" )
text = """Anderson, Grint created spaczz in his home at 555 Fake St,
Apt 5 in Nashv1le, TN 55555-1234 in the US.""" # Spelling errors intentional.
doc = nlp ( text )
matcher = RegexMatcher ( nlp . vocab )
# Use inline flags for regex strings as needed
matcher . add (
"ZIP" ,
[ r"bd{5}(?:[-s]d{4})?b" ],
)
matcher . add ( "GPE" , [ r"(usa){d<=1}" ]) # Fuzzy regex.
matches = matcher ( doc )
for match_id , start , end , ratio , pattern in matches :
print ( match_id , doc [ start : end ], ratio , pattern ) ZIP 55555-1234 100 bd{5}(?:[-s]d{4})?b
GPE US 80 (usa){d<=1}
Les matchs Spaczz peuvent également utiliser les règles de match via des fonctions de rappel. Ces rappels sur le match doivent accepter le matchur lui-même, le DOC le matchur a été appelé, l'index de matchs et les matchs produits par le Matcher. Voir l'exemple d'utilisation du Matcher flou ci-dessus pour plus de détails.
Comme le Matcher Fuzzy, le Matcher Regex a des arguments de mots clés facultatifs qui peuvent modifier le comportement de correspondance. Prenez l'exemple de correspondance regex ci-dessous.
import spacy
from spaczz . matcher import RegexMatcher
nlp = spacy . blank ( "en" )
text = """Anderson, Grint created spaczz in his home at 555 Fake St,
Apt 5 in Nashv1le, TN 55555-1234 in the USA.""" # Spelling errors intentional. Notice 'USA' here.
doc = nlp ( text )
matcher = RegexMatcher ( nlp . vocab )
# Use inline flags for regex strings as needed
matcher . add (
"STREET" , [ "street_addresses" ], kwargs = [{ "predef" : True }]
) # Use predefined regex by key name.
# Below will not expand partial matches to span boundaries.
matcher . add ( "GPE" , [ r"(?i)[U](nited|.?) ?[S](tates|.?)" ], kwargs = [{ "partial" : False }])
matches = matcher ( doc )
for match_id , start , end , ratio , pattern in matches :
print (
match_id , doc [ start : end ], ratio , pattern
) # comma in result isn't ideal - see "Roadmap" STREET 555 Fake St, 100 street_addresses
La liste complète des arguments de mots clés disponibles pour les paramètres de correspondance regex comprend:
ignore_case (bool): s'il faut le texte inférieur avant la correspondance. La valeur par défaut est True .min_r (int): rapport de correspondance minimum requis.fuzzy_weights (STR): Nom de la méthode de pondération pour les dénombrements d'insertion, de suppression et de substitution regex. Des méthodes de pondération supplémentaires peuvent être enregistrées par les utilisateurs. La valeur par défaut est "indel" ."indel" = (1, 1, 2)"lev" = (1, 1, 1)partial : (Bool): Le fait que les correspondances partielles soient étendues à des frontières Token ou Span dans doc ou non. Par exemple, le regex ne correspond qu'une partie d'un Token ou Span dans doc . La valeur par défaut est True .predef (String): si la chaîne regex doit être interprétée comme une clé d'un motif regex prédéfini ou non. Des modèles regex prédéfinis supplémentaires peuvent être enregistrés par les utilisateurs. La valeur par défaut est False."dates""times""phones""phones_with_exts""links""emails""ips""ipv6s""prices""hex_colors""credit_cards""btc_addresses""street_addresses""zip_codes""po_boxes""ssn_numbers" L'utilisation de base du matchateur de similitude est similaire à celle de PhraseMatcher de Spacy, sauf qu'elle renvoie le rapport de similitude vectoriel et le modèle correspondant, ainsi que l'ID de correspondance, les informations de début et de fin, alors assurez-vous d'inclure des variables pour le rapport et le modèle lors du déballage des résultats.
Afin de produire des résultats significatifs de la partage de similitude, un modèle de spacy avec des vecteurs de mots (ex. Modèles moyens ou grands anglais) doit être utilisé pour initialiser le correspondant, traiter le document cible et traiter tous les modèles ajoutés.
import spacy
from spaczz . matcher import SimilarityMatcher
nlp = spacy . load ( "en_core_web_md" )
text = "I like apples, grapes and bananas."
doc = nlp ( text )
# lowering min_r2 from default of 75 to produce matches in this example
matcher = SimilarityMatcher ( nlp . vocab , min_r2 = 65 )
matcher . add ( "FRUIT" , [ nlp ( "fruit" )])
matches = matcher ( doc )
for match_id , start , end , ratio , pattern in matches :
print ( match_id , doc [ start : end ], ratio , pattern ) FRUIT apples 70 fruit
FRUIT grapes 73 fruit
FRUIT bananas 70 fruit
Veuillez noter que même pour le Spaczz principalement pur-python, ce processus est actuellement extrêmement lent, alors soyez conscient de la portée dans laquelle il est appliqué. L'activation du support GPU dans Spacy (voir ici) devrait quelque peu améliorer la vitesse, mais je pense que le processus sera toujours goulot d'étranglement dans l'algorithme de recherche pur-python jusqu'à ce que je développe un meilleur algorithme de recherche et / ou dépose la recherche sur le code de niveau inférieur (EX C).
Également en tant que caractéristique quelque peu expérimentale, le Matcher de similitude ne fait actuellement pas partie du SpaczzRuler et n'a pas non plus de règle distincte. Si vous avez besoin d'ajouter des correspondances de similitude aux entités d'un Doc , vous devrez utiliser un rappel sur le match pour le moment. Veuillez consulter l'exemple de rappel de match flou sur le match ci-dessus pour les idées. S'il y a suffisamment d'intérêt à intégrer / créer une règle pour le correspondant de similitude, cela peut être fait.
La liste complète des arguments de mots clés disponibles pour les paramètres de correspondance de similitude comprend:
ignore_case (bool): si le texte des cas inférieurs avant la correspondance floue. La valeur par défaut est True .min_r (int): rapport de correspondance minimum requis.thresh (int): Si ce rapport est dépassé dans le scan initial et flex > 0 , aucune optimisation ne sera tentée. Si flex == 0 , thresh n'a aucun effet. La valeur par défaut est 100 .flex (int | littéral ['par défaut', 'min', 'max']): nombre de jetons pour déplacer les limites de correspondance à gauche et à droite pendant l'optimisation. Peut être un int avec un maximum de len(pattern) et un min de 0 , (avertira et changera s'il est supérieur ou plus bas). "max" , "min" ou "default" sont également valides. La valeur par défaut est "default" : len(pattern) // 2 .min_r1 (int | Aucun): contrôle granulaire facultatif sur le rapport de correspondance minimum requis pour la sélection pendant le scan initial. Si flex == 0 , min_r1 sera écrasé par min_r2 . Si flex > 0 , min_r1 doit être inférieur à min_r2 et "Low" en général car les limites des correspondances ne sont pas fléchies initialement. La valeur par défaut None , ce qui entraînera le défilé min_r1 sur round(min_r / 1.5) .min_r2 (int | Aucun): contrôle granulaire facultatif sur le rapport de correspondance minimum requis pour la sélection pendant l'optimisation de la correspondance. Doit être supérieur à min_r1 et "High" en général pour garantir que seules les correspondances de qualité sont retournées. La valeur par défaut None , ce qui entraînera le défilé min_r2 sur min_r . Remarque: Matcher de Spacy prend désormais en charge la correspondance floue, donc à moins que vous ayez besoin d'une fonctionnalité spécifique de TokenMatcher de Spaczz, il est fortement recommandé d'utiliser Matcher beaucoup plus rapide de Spacy.
L'utilisation de base du correspondant de jeton est similaire au Matcher de Spacy. Il accepte les modèles étiquetés sous la forme de listes de dictionnaires où chaque liste décrit un modèle individuel et chaque dictionnaire décrit un jeton individuel.
Le correspondant de jeton accepte tous les mêmes attributs de jetons et syntaxe de motif car il est homologue spacy mais ajoute une prise en charge floue et floue-regex.
"FUZZY" et "FREGEX" sont les deux options de motifs de jeton Spacy supplémentaires.
Par exemple:
[
{ "TEXT" : { "FREGEX" : "(database){e<=1}" }},
{ "LOWER" : { "FUZZY" : "access" , "MIN_R" : 85 , "FUZZY_FUNC" : "quick_lev" }},
]Assurez-vous d'utiliser des clés de dictionnaire en majuscules dans les modèles.
La liste complète des arguments de mots clés disponibles pour les paramètres de correspondance de jetons comprend:
ignore_case (bool): s'il faut le texte inférieur avant la correspondance. Ne peut être réglé qu'au niveau du motif. Pour les modèles "flou" et "Fregex". La valeur par défaut est True .min_r (int): rapport de correspondance minimum requis. Pour les modèles "flou" et "Fregex".fuzzy_func (STR): Nom de clé de la fonction de correspondance floue à utiliser. Ne peut être réglé qu'au niveau du motif. Pour les modèles "flous" uniquement. Toutes les fonctions de correspondance RapidFuzz avec des paramètres par défaut sont disponibles, mais toutes les fonctions basées sur les jetons ne fournissent aucune utilité au niveau de jeton individuel. Des fonctions de correspondance floues supplémentaires peuvent être enregistrées par les utilisateurs. Les fonctions incluses et utiles sont (la valeur par défaut est simple ):"simple" = ratio"partial" = partial_ratio"quick" = QRatio"partial_alignment" = partial_ratio_alignment (nécessite rapidfuzz>=2.0.3 )fuzzy_weights (STR): Nom de la méthode de pondération pour les dénombrements d'insertion, de suppression et de substitution regex. Des méthodes de pondération supplémentaires peuvent être enregistrées par les utilisateurs. La valeur par défaut est "indel" ."indel" = (1, 1, 2)"lev" = (1, 1, 1)predef : Qu'il s'agisse de regex doit être interprété comme une clé d'un motif regex prédéfini ou non. Ne peut être réglé qu'au niveau du motif. Pour les modèles "Fregex" uniquement. La valeur par défaut est False . import spacy
from spaczz . matcher import TokenMatcher
# Using model results like POS tagging in token patterns requires model that provides these.
nlp = spacy . load ( "en_core_web_md" )
text = """The manager gave me SQL databesE acess so now I can acces the Sequal DB.
My manager's name is Grfield"""
doc = nlp ( text )
matcher = TokenMatcher ( vocab = nlp . vocab )
matcher . add (
"DATA" ,
[
[
{ "TEXT" : "SQL" },
{ "LOWER" : { "FREGEX" : "(database){s<=1}" }},
{ "LOWER" : { "FUZZY" : "access" }},
],
[{ "TEXT" : { "FUZZY" : "Sequel" }, "POS" : "PROPN" }, { "LOWER" : "db" }],
],
)
matcher . add ( "NAME" , [[{ "TEXT" : { "FUZZY" : "Garfield" }}]])
matches = matcher ( doc )
for match_id , start , end , ratio , pattern in matches :
print ( match_id , doc [ start : end ], ratio , pattern ) DATA SQL databesE acess 91 [{"TEXT":"SQL"},{"LOWER":{"FREGEX":"(database){s<=1}"}},{"LOWER":{"FUZZY":"access"}}]
DATA Sequal DB 87 [{"TEXT":{"FUZZY":"Sequel"},"POS":"PROPN"},{"LOWER":"db"}]
NAME Grfield 93 [{"TEXT":{"FUZZY":"Garfield"}}]
Même si le correspondant de jeton peut être un remplacement sans rendez-vous pour Matcher de Spacy, il est toujours recommandé d'utiliser Matcher de Spacy si vous n'avez pas besoin des capacités floues du correspondant de jeton Spaczz - cela ralentira le traitement inutilement.
Rappel: Matcher de Spacy prend désormais en charge la correspondance floue, donc à moins que vous ayez besoin d'une fonctionnalité spécifique de TokenMatcher de Spaczz, il est fortement recommandé d'utiliser Matcher beaucoup plus rapide de Spacy.
La règle Spaczz combine les matchs de phrase floue et regex et le correspondant de jeton "flou", en un composant de pipeline qui peut mettre à jour un Doc.ents similaire à EntityRuler de Spacy.
Des motifs doivent être ajoutés comme un itérable de dictionnaires dans le format de {label (str), motif (str ou list), type (str), kwargs facultatif (dict) et id facultatif (str)} .
Par exemple, un modèle de phrase floue:
{'label': 'ORG', 'pattern': 'Apple' 'kwargs': {'min_r2': 90}, 'type': 'fuzzy'}
Ou, un motif de jeton:
{'label': 'ORG', 'pattern': [{'TEXT': {'FUZZY': 'Apple'}}], 'type': 'token'}
import spacy
from spaczz . pipeline import SpaczzRuler
nlp = spacy . blank ( "en" )
text = """Anderson, Grint created spaczz in his home at 555 Fake St,
Apt 5 in Nashv1le, TN 55555-1234 in the USA.
Some of his favorite bands are Converg and Protet the Zero.""" # Spelling errors intentional.
doc = nlp ( text )
patterns = [
{
"label" : "NAME" ,
"pattern" : "Grant Andersen" ,
"type" : "fuzzy" ,
"kwargs" : { "fuzzy_func" : "token_sort" },
},
{
"label" : "STREET" ,
"pattern" : "street_addresses" ,
"type" : "regex" ,
"kwargs" : { "predef" : True },
},
{ "label" : "GPE" , "pattern" : "Nashville" , "type" : "fuzzy" },
{
"label" : "ZIP" ,
"pattern" : r"b(?:55554){s<=1}(?:(?:[-s])?d{4}b)" ,
"type" : "regex" ,
}, # fuzzy regex
{ "label" : "GPE" , "pattern" : "(?i)[U](nited|.?) ?[S](tates|.?)" , "type" : "regex" },
{
"label" : "BAND" ,
"pattern" : [{ "LOWER" : { "FREGEX" : "(converge){e<=1}" }}],
"type" : "token" ,
},
{
"label" : "BAND" ,
"pattern" : [
{ "TEXT" : { "FUZZY" : "Protest" }},
{ "IS_STOP" : True },
{ "TEXT" : { "FUZZY" : "Hero" }},
],
"type" : "token" ,
},
]
ruler = SpaczzRuler ( nlp )
ruler . add_patterns ( patterns )
doc = ruler ( doc )
for ent in doc . ents :
print (
(
ent . text ,
ent . start ,
ent . end ,
ent . label_ ,
ent . _ . spaczz_ratio ,
ent . _ . spaczz_type ,
ent . _ . spaczz_pattern ,
)
) ('Anderson, Grint', 0, 3, 'NAME', 83, 'fuzzy', 'Grant Andersen')
('555 Fake St,', 9, 13, 'STREET', 100, 'regex', 'street_addresses')
('Nashv1le', 17, 18, 'GPE', 82, 'fuzzy', 'Nashville')
('55555-1234', 20, 23, 'ZIP', 90, 'regex', '\b(?:55554){s<=1}(?:(?:[-\s])?\d{4}\b)')
('USA', 25, 26, 'GPE', 100, 'regex', '(?i)[U](nited|\.?) ?[S](tates|\.?)')
('Converg', 34, 35, 'BAND', 93, 'token', '[{"LOWER":{"FREGEX":"(converge){e<=1}"}}]')
('Protet the Zero', 36, 39, 'BAND', 89, 'token', '[{"TEXT":{"FUZZY":"Protest"}},{"IS_STOP":true},{"TEXT":{"FUZZY":"Hero"}}]')
Nous voyons dans l'exemple ci-dessus que nous faisons référence à certains attributs personnalisés, qui sont expliqués ci-dessous.
Pour plus d'exemples SpaczzRuler consultez ici. En particulier, cela fournit des détails sur le processus de tri de la règle et les paramètres de correspondance floue.
Spaczz initialise certains attributs personnalisés lors de l'importation. Ce sont sous Spacy ._. Attribut et sont en outre apparentes avec spaczz_ , il ne devrait donc pas y avoir de conflits avec vos propres attributs personnalisés. S'il y a Spaczz forcera les écraser.
Ces attributs personnalisés ne sont définis que via la règle Spaczz au niveau du jeton. Les versions SPAN et DOC de ces attributs sont des getters qui font référence aux attributs de niveau de jeton.
Les attributs Token suivants sont disponibles. Tous sont mutables:
spaczz_token : default = False . Boolean qui indique si le jeton fait partie d'une entité définie par le souverain Spaczz.spaczz_type : par défaut = None . String qui montre quel correspondant a produit une entité à l'aide du jeton.spaczz_ratio : default = None . Si le jeton fait partie d'une entité appariée, il renverra le rapport flou.spaczz_pattern : default = None . Si le jeton fait partie d'une entité appariée, il renverra le motif en tant que chaîne (format JSON pour motifs de jetons) qui ont produit le match. Les attributs Span suivants font référence aux attributs de jeton inclus dans la travée. Tous sont immuables:
spaczz_ent : default = False . Boolean qui indique si tous les jetons dans la travée font partie d'une entité définie par la souverain Spaczz.spaczz_type : par défaut = None . String qui désigne le matchur a produit une entité à l'aide des jetons inclus.spaczz_types : default = set() . Ensemble qui montre quels correspondants ont produit des entités à l'aide des jetons inclus. Une durée d'entité ne devrait avoir qu'un seul type, mais cela vous permet de voir les types inclus dans n'importe quelle portée arbitraire.spaczz_ratio : default = None . Si tous les jetons en période font partie d'une entité appariée, il renverra le rapport flou.spaczz_pattern : default = None . Si tous les jetons d'une période font partie d'une entité appariée, il renverra le motif en tant que chaîne (format JSON pour les motifs de jetons) qui ont produit le match. Les attributs Doc suivants font référence aux attributs de jeton inclus dans le DOC. Tous sont immuables:
spaczz_doc : default = False . Boolean qui désigne si des jetons dans le DOC font partie d'une entité définie par le souverain Spaczz.spaczz_types : default = set() . Ensemble qui montre quels correspondants ont produit des entités dans le DOC. Le SpaczzRuler a ses propres méthodes de disque / octets et acceptera les paramètres config transmis à spacy.load() . Il a également son propre point d'entrée d'usine Spacy, donc Spacy est conscient du SpaczzRuler . Vous trouverez ci-dessous un exemple d'économie et de chargement d'un pipeline spacy avec le petit modèle anglais, l' EntityRuler et le SpaczzRuler .
import spacy
from spaczz . pipeline import SpaczzRuler
nlp = spacy . load ( "en_core_web_md" )
text = """Anderson, Grint created spaczz in his home at 555 Fake St,
Apt 5 in Nashv1le, TN 55555-1234 in the USA.
Some of his favorite bands are Converg and Protet the Zero.""" # Spelling errors intentional.
doc = nlp ( text )
for ent in doc . ents :
print (( ent . text , ent . start , ent . end , ent . label_ )) ('Anderson, Grint', 0, 3, 'ORG')
('555', 9, 10, 'CARDINAL')
('Apt 5', 14, 16, 'PRODUCT')
('Nashv1le', 17, 18, 'GPE')
('TN 55555-1234', 19, 23, 'ORG')
('USA', 25, 26, 'GPE')
('Converg', 34, 35, 'PERSON')
('Zero', 38, 39, 'CARDINAL')
Bien que Spacy ait un travail décent d'identification que les entités nommées sont présentes dans cet exemple, nous pouvons certainement améliorer les correspondances - en particulier avec les types d'étiquettes appliquées.
Ajoutons une règle d'entité pour certaines correspondances basées sur des règles.
from spacy . pipeline import EntityRuler
entity_ruler = nlp . add_pipe ( "entity_ruler" , before = "ner" ) #spaCy v3 syntax
entity_ruler . add_patterns (
[{ "label" : "GPE" , "pattern" : "Nashville" }, { "label" : "GPE" , "pattern" : "TN" }]
)
doc = nlp ( text )
for ent in doc . ents :
print (( ent . text , ent . start , ent . end , ent . label_ )) ('Anderson, Grint', 0, 3, 'ORG')
('555', 9, 10, 'CARDINAL')
('Apt 5', 14, 16, 'PRODUCT')
('Nashv1le', 17, 18, 'GPE')
('TN', 19, 20, 'GPE')
('USA', 25, 26, 'GPE')
('Converg', 34, 35, 'PERSON')
('Zero', 38, 39, 'CARDINAL')
Nous progressons, mais Nashville est mal orthographié dans le texte afin que le souverain d'entité ne le trouve pas, et nous avons encore d'autres entités à réparer / trouver.
Ajoutons une règle Spaczz pour compléter ce pipeline. Nous inclurons également l'attribut personnalisé spaczz_span dans les résultats pour indiquer les entités définies via Spaczzz.
spaczz_ruler = nlp . add_pipe ( "spaczz_ruler" , before = "ner" ) #spaCy v3 syntax
spaczz_ruler . add_patterns (
[
{
"label" : "NAME" ,
"pattern" : "Grant Andersen" ,
"type" : "fuzzy" ,
"kwargs" : { "fuzzy_func" : "token_sort" },
},
{
"label" : "STREET" ,
"pattern" : "street_addresses" ,
"type" : "regex" ,
"kwargs" : { "predef" : True },
},
{ "label" : "GPE" , "pattern" : "Nashville" , "type" : "fuzzy" },
{
"label" : "ZIP" ,
"pattern" : r"b(?:55554){s<=1}(?:[-s]d{4})?b" ,
"type" : "regex" ,
}, # fuzzy regex
{
"label" : "BAND" ,
"pattern" : [{ "LOWER" : { "FREGEX" : "(converge){e<=1}" }}],
"type" : "token" ,
},
{
"label" : "BAND" ,
"pattern" : [
{ "TEXT" : { "FUZZY" : "Protest" }},
{ "IS_STOP" : True },
{ "TEXT" : { "FUZZY" : "Hero" }},
],
"type" : "token" ,
},
]
)
doc = nlp ( text )
for ent in doc . ents :
print (( ent . text , ent . start , ent . end , ent . label_ , ent . _ . spaczz_ent )) ('Anderson, Grint', 0, 3, 'NAME', True)
('555 Fake St,', 9, 13, 'STREET', True)
('Apt 5', 14, 16, 'PRODUCT', False)
('Nashv1le', 17, 18, 'GPE', True)
('TN', 19, 20, 'GPE', False)
('55555-1234', 20, 23, 'ZIP', True)
('USA', 25, 26, 'GPE', False)
('Converg', 34, 35, 'BAND', True)
('Protet the Zero', 36, 39, 'BAND', True)
Génial! Le petit modèle anglais fait toujours une erreur de reconnaissance entités nommée ("5" dans "APT 5" en tant que CARDINAL ), mais nous sommes satisfaits dans l'ensemble.
Enregistrons ce pipeline sur le disque et assurez-vous que nous pouvons le recharger correctement.
import tempfile
with tempfile . TemporaryDirectory () as tmp_dir :
nlp . to_disk ( f" { tmp_dir } /example_pipeline" )
nlp = spacy . load ( f" { tmp_dir } /example_pipeline" )
nlp . pipe_names ['tok2vec',
'tagger',
'parser',
'attribute_ruler',
'lemmatizer',
'entity_ruler',
'spaczz_ruler',
'ner']
Nous pouvons même nous assurer que tous les modèles de règle Spaczz sont toujours présents.
spaczz_ruler = nlp . get_pipe ( "spaczz_ruler" )
spaczz_ruler . patterns [{'label': 'NAME',
'pattern': 'Grant Andersen',
'type': 'fuzzy',
'kwargs': {'fuzzy_func': 'token_sort'}},
{'label': 'GPE', 'pattern': 'Nashville', 'type': 'fuzzy'},
{'label': 'STREET',
'pattern': 'street_addresses',
'type': 'regex',
'kwargs': {'predef': True}},
{'label': 'ZIP',
'pattern': '\b(?:55554){s<=1}(?:[-\s]\d{4})?\b',
'type': 'regex'},
{'label': 'BAND',
'pattern': [{'LOWER': {'FREGEX': '(converge){e<=1}'}}],
'type': 'token'},
{'label': 'BAND',
'pattern': [{'TEXT': {'FUZZY': 'Protest'}},
{'IS_STOP': True},
{'TEXT': {'FUZZY': 'Hero'}}],
'type': 'token'}]
La raison principale de la vitesse plus lente de Spaczz est que le C dans son nom n'est pas capitalisé comme il est en spa c y. Spaczz est écrit en pur python et ses correspondants n'utilisent actuellement pas de vocabulaires de langage spacy, ce qui signifie que suivre sa logique devrait être facile pour ceux qui connaissent Python. Cependant, cela signifie que les composants Spaczz fonctionneront plus lentement et consomment probablement plus de mémoire que leurs homologues spacy, d'autant plus que plus de modèles sont ajoutés et que les documents s'allongent. Il est donc recommandé d'utiliser des composants spactifs comme l'entitéruleur pour les entités avec peu d'incertitude, comme des erreurs d'orthographe cohérentes. Utilisez des composants Spaczz lorsqu'il n'y a pas de alternatives de spacy viables.
Je ne travaille pas actuellement sur les optimisations des performances à Spaczz, mais les suggestions algorithmiques et d'optimisation sont les bienvenues.
Les principales méthodes pour accélérer le FuzzyMatcher et SimilarityMatcher sont de diminuer le paramètre flex vers 0 , ou si flex > 0 , augmentant le paramètre min_r1 vers la valeur de min_r2 et / ou abaissant le paramètre thresh vers min_r2 . Sachez que toutes ces "accélérations" sont au coût d'opportunité de matchs potentiellement améliorés.
Comme mentionné dans la description de SimilarityMatcher , l'utilisation d'un GPU peut également aider à accélérer son processus de correspondance.
Je suis toujours ouvert et réceptif aux demandes de fonctionnalités, mais sachez simplement, en tant que solo-DEV avec beaucoup de choses à apprendre, le développement peut se déplacer assez lentement. Ce qui suit est ma feuille de route pour Spaczz afin que vous puissiez voir où les problèmes soulevés pourraient s'intégrer dans mes priorités actuelles.
Remarque: Bien que je souhaite garder spaczz fonctionnelle, je ne le développe pas activement. J'essaie d'être sensible aux problèmes et aux demandes, mais ce projet n'est pas actuellement au centre de mes objectifs.
Priorité élevée
Améliorations
Les demandes de traction et les contributeurs sont les bienvenues.
Spaczz est liné avec Flake8, formaté avec du noir, vérifié avec MyPy (bien que cela puisse bénéficier d'une spécificité améliorée), testée avec Pytest, automatisée avec NOx et construite / emballée avec de la poésie. Il existe quelques autres outils de développement détaillés dans noxfile.py, ainsi que les crochets pré-comités GIT.
Pour contribuer au développement de Spaczz, fourrez le référentiel puis installez Spaczz et ses dépendances de développement avec poésie. Si vous êtes intéressé à être un contributeur régulier, veuillez me contacter directement.
poetry install # Within spaczz's root directory.Je garde NOx et pré-engagement en dehors de mon environnement de poésie dans le cadre de mes environnements Python Toolchain. Avec le pré-engagement installé, vous devrez peut-être également exécuter ce qui précède pour commettre des modifications.
pre - commit install Le seul autre package qui ne sera pas installé via la poésie mais qui est utilisé pour les tests et les exemples de documentation est le modèle Spacy Medium English ( en-core-web-md ). Cela devra être installé séparément. La commande ci-dessous devrait faire l'affaire:
poetry run python - m spacy download "en_core_web_md"