Spaczz proporciona una coincidencia difusa y una funcionalidad de coincidencia de regex adicional para Spacy. Los componentes de Spaczz tienen API similares a sus contrapartes de Spacy y los componentes de la tubería de spaczz pueden integrarse en tuberías espacios donde se pueden guardar/cargar como modelos.
Fuzzy Matching se realiza actualmente con Matchers del módulo Fuzz de Rapidfuzz y la coincidencia de regex actualmente se basa en la biblioteca Regex. Spaczz ciertamente toma una influencia adicional de otras bibliotecas y recursos. Para obtener detalles adicionales, consulte la sección Referencias.
Admite Spacy> = 3.0
Spaczz se ha probado en Ubuntu, MacOS y Windows Server.
V0.6.0 Notas de la versión:
python<=3.11,>=3.7 , junto con rapidfuzz>=1.0.0 ."spaczz_" preprimió los argumentos opcionales SpaczzRuler init. Además, lamento hacer esto sin un ciclo de deprecación.Matcher.pipe , que estaban en desuso, ahora se eliminan.spaczz_span , que estaba en desuso, ahora se elimina.Consulte el ChangeLog para las notas de versión anteriores. Esto eventualmente se trasladará a la página Leer de Docs.
Spaczz se puede instalar usando PIP.
pip install spaczz Las características principales de Spaczz son FuzzyMatcher , RegexMatcher y TokenMatcher "difuso" que funcionan de manera similar a Matcher y PhraseMatcher de Spacy, y el SpaczzRuler que integra los Matchers de Spaczz en un componente de la tubería Spacy similar a EntityRuler de Spacy.
El uso básico del combate difuso es similar al PhraseMatcher de Spacy, excepto que devuelve la relación difusa y el patrón coincidente, junto con la ID de coincidencia, la información de inicio y finalización, así que asegúrese de incluir variables para la relación y el patrón al desempacar los resultados.
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
A diferencia de Spacy Matchers, Spaczz Matchers está escrito en Pure Python. Si bien se les exige que les pase un vocabulario espacial durante la inicialización, esto es puramente para la consistencia, ya que los Spaczz Matchers no usan actualmente el Vocab de Spacy. Es por eso que el match_id anterior es simplemente una cadena en lugar de un valor entero como en Spacy Matchers.
Spaczz Matchers también puede utilizar las reglas en el partido a través de funciones de devolución de llamada. Estas devoluciones de llamada en el partido deben aceptar el Matcher en sí, el Doc que se convocó al Matcher, el índice de partidos y los partidos producidos por el 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')
Al igual que Spacy's EntityRuler , una lógica de actualización de entidad muy similar se ha implementado en SpaczzRuler . El SpaczzRuler también se encarga de manejar partidos superpuestos. Se discute en una sección posterior.
A diferencia de los Matchers de Spacy, las reglas agregadas a Spaczz Matchers tienen argumentos de palabras clave opcionales que pueden modificar el comportamiento coincidente. Tome los siguientes ejemplos de coincidencia difusa:
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 )A continuación, cambiamos el comportamiento de coincidencia difusa para el patrón en la regla de "nombre".
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 lista completa de argumentos de palabras clave disponibles para la configuración de coincidencia difusa incluye:
ignore_case (bool): si se debe hacer un texto más bajo antes de coincidir. El valor predeterminado es True .min_r (int): requerida una relación de coincidencia mínima.thresh (int): si esta relación se excede en el escaneo inicial, y flex > 0 , no se intentará optimización. Si flex == 0 , thresh no tiene ningún efecto. El valor predeterminado es 100 .fuzzy_func (STR): nombre clave de la función de coincidencia difusa para usar. Todas las funciones de coincidencia de RapidFuzz con configuración predeterminada están disponibles. Los usuarios pueden registrar funciones de coincidencia difusa adicionales. El valor predeterminado es "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 (requiere rapidfuzz>=2.0.3 )flex (int | literal ['predeterminado', 'min', 'max']): número de tokens para mover los límites de la coincidencia de izquierda a derecha durante la optimización. Puede ser un int con un máximo de len(pattern) y un mínimo de 0 (advertirá y cambiará si es más alto o más bajo). "max" , "min" o "default" también son válidos. El valor predeterminado es "default" : len(pattern) // 2 .min_r1 (int | Ninguno): control granular opcional sobre la relación de coincidencia mínima requerida para la selección durante el escaneo inicial. Si flex == 0 , min_r1 se sobrescribirá por min_r2 . Si flex > 0 , min_r1 debe ser más bajo que min_r2 y "bajo" en general porque los límites de la coincidencia no se flexionan inicialmente. El valor predeterminado es None , lo que dará como resultado que min_r1 se establezca en round(min_r / 1.5) . El uso básico de Regex Matcher también es bastante similar al PhraseMatcher de Spacy. Acepta patrones regex como cadenas, por lo que las banderas deben estar en línea. Las regexas se compilan con el paquete Regex, por lo que se admite la coincidencia de "difusa" aproximada. Para proporcionar acceso a estos resultados de coincidencia "difusos", el combate devuelve una relación difusa calculada y un patrón coincidente, junto con ID de coincidencia, información de inicio y finalización, así que asegúrese de incluir variables para la relación y el patrón al desempacar los resultados.
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}
Spaczz Matchers también puede utilizar las reglas en el partido a través de funciones de devolución de llamada. Estas devoluciones de llamada en el partido deben aceptar el Matcher en sí, el Doc que se convocó al Matcher, el índice de partidos y los partidos producidos por el Matcher. Vea el ejemplo de uso de Matcher Fuzzy anterior para más detalles.
Al igual que Fuzzy Matcher, el Regex Matcher tiene argumentos de palabras clave opcionales que pueden modificar el comportamiento coincidente. Tome el siguiente ejemplo de coincidencia de regex.
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 lista completa de argumentos de palabras clave disponibles para la configuración de coincidencia de regex incluye:
ignore_case (bool): si se debe hacer un texto más bajo antes de coincidir. El valor predeterminado es True .min_r (int): requerida una relación de coincidencia mínima.fuzzy_weights (STR): Nombre del método de ponderación para la inserción, la eliminación y la sustitución de Regex. Los usuarios pueden registrar métodos de ponderación adicionales. El valor predeterminado es "indel" ."indel" = (1, 1, 2)"lev" = (1, 1, 1)partial : (bool): si las coincidencias parciales deben extenderse a los límites Token o Span en doc o no. Por ejemplo, el Regex solo coincide con parte de un Token o Span en doc . El valor predeterminado es True .predef (cadena): si la cadena Regex debe interpretarse como una clave para un patrón regex predefinido o no. Los usuarios pueden registrar patrones regex predefinidos adicionales. El valor predeterminado es 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" El uso básico del emparejador de similitud es similar al PhraseMatcher de Spacy, excepto que devuelve la relación de similitud vectorial y el patrón coincidente, junto con la ID de coincidencia, la información de inicio y finalización, así que asegúrese de incluir variables para la relación y el patrón al desempacar los resultados.
Para producir resultados significativos del combate de similitud, se debe utilizar un modelo espacial con vectores de palabras (ex. Modelos ingleses medianos o grandes) para inicializar el combate, procesar el documento de destino y procesar cualquier patrón agregado.
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
Tenga en cuenta que incluso para el spaczz en su mayoría puro de Python, este proceso es actualmente extremadamente lento, así que tenga en cuenta el alcance en el que se aplica. Habilitar el soporte de GPU en Spacy (ver aquí) debería mejorar un poco la velocidad, pero creo que el proceso aún se cuello de botella en el algoritmo de búsqueda de Python Pure-Python hasta que desarrolle un mejor algoritmo de búsqueda y/o deje la búsqueda al código de nivel inferior (ex C).
También como una característica algo experimental, el emparejador de similitud no es actualmente parte del SpaczzRuler ni tiene una regla separada. Si necesita agregar coincidencias de similitud a las entidades de un Doc , deberá usar una devolución de llamada en el partido por el momento. Consulte el ejemplo de devolución de llamada Fuzzy Matcher On-Match anterior para obtener ideas. Si hay suficiente interés en integrar/crear una regla para el combate de similitud, esto se puede hacer.
La lista completa de argumentos de palabras clave disponibles para la configuración de coincidencia de similitud incluye:
ignore_case (bool): si se debe al texto en caso inferior antes de la coincidencia difusa. El valor predeterminado es True .min_r (int): requerida una relación de coincidencia mínima.thresh (int): si esta relación se excede en el escaneo inicial, y flex > 0 , no se intentará optimización. Si flex == 0 , thresh no tiene ningún efecto. El valor predeterminado es 100 .flex (int | literal ['predeterminado', 'min', 'max']): número de tokens para mover los límites de la coincidencia de izquierda a derecha durante la optimización. Puede ser un int con un máximo de len(pattern) y un mínimo de 0 (advertirá y cambiará si es más alto o más bajo). "max" , "min" o "default" también son válidos. El valor predeterminado es "default" : len(pattern) // 2 .min_r1 (int | Ninguno): control granular opcional sobre la relación de coincidencia mínima requerida para la selección durante el escaneo inicial. Si flex == 0 , min_r1 se sobrescribirá por min_r2 . Si flex > 0 , min_r1 debe ser más bajo que min_r2 y "bajo" en general porque los límites de la coincidencia no se flexionan inicialmente. El valor predeterminado es None , lo que dará como resultado que min_r1 se establezca en round(min_r / 1.5) .min_r2 (int | Ninguno): control granular opcional sobre la relación de coincidencia mínima requerida para la selección durante la optimización del partido. Debe ser más alto que min_r1 y "alto" en general para garantizar que solo se devuelvan coincidencias de calidad. El valor predeterminado es None , lo que dará como resultado que min_r2 se establezca en min_r . Nota: Spacy's Matcher ahora admite la coincidencia difusa, por lo que a menos que necesite una característica específica del TokenMatcher de Spaczz, se recomienda usar Matcher mucho más rápida de Spacy.
El uso básico del token Matcher es similar al Matcher de Spacy. Acepta patrones etiquetados en forma de listas de diccionarios donde cada lista describe un patrón individual y cada diccionario describe un token individual.
El token Matcher acepta los mismos atributos tokens y sintaxis de patrones que su contraparte de Spacy, pero agrega soporte difuso y difuso-regex.
"FUZZY" y "FREGEX" son las dos opciones adicionales de patrones de tokens de espacios.
Por ejemplo:
[
{ "TEXT" : { "FREGEX" : "(database){e<=1}" }},
{ "LOWER" : { "FUZZY" : "access" , "MIN_R" : 85 , "FUZZY_FUNC" : "quick_lev" }},
]Asegúrese de usar las teclas de diccionario en mayúsculas en patrones.
La lista completa de argumentos de palabras clave disponibles para la configuración de coincidencia de tokens incluye:
ignore_case (bool): si se debe hacer un texto más bajo antes de coincidir. Solo se puede establecer en el nivel de patrón. Para patrones "difusos" y "fregex". El valor predeterminado es True .min_r (int): requerida una relación de coincidencia mínima. Para patrones "difusos" y "fregex".fuzzy_func (STR): nombre clave de la función de coincidencia difusa para usar. Solo se puede establecer en el nivel de patrón. Solo para patrones "difusos". Todas las funciones de coincidencia de RapidFuzz con configuración predeterminada están disponibles, sin embargo, cualquier función basada en token no proporciona utilidad en el nivel de token individual. Los usuarios pueden registrar funciones de coincidencia difusa adicionales. Las funciones incluidas y útiles son (el valor predeterminado es simple ):"simple" = ratio"partial" = partial_ratio"quick" = QRatio"partial_alignment" = partial_ratio_alignment (requiere rapidfuzz>=2.0.3 )fuzzy_weights (STR): Nombre del método de ponderación para la inserción, la eliminación y la sustitución de Regex. Los usuarios pueden registrar métodos de ponderación adicionales. El valor predeterminado es "indel" ."indel" = (1, 1, 2)"lev" = (1, 1, 1)predef : Si Regex debe interpretarse como una clave para un patrón Regex predefinido o no. Solo se puede establecer en el nivel de patrón. Solo para patrones "fregex". El valor predeterminado es 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"}}]
A pesar de que el token Matcher puede ser un reemplazo de Spacy's Matcher , todavía se recomienda utilizar Spacy's Matcher si no necesita las capacidades difusas de Spaczz Token Matcher; se procesará innecesariamente el procesamiento innecesario.
Recordatorio: Spacy's Matcher ahora admite una coincidencia difusa, por lo que a menos que necesite una característica específica del TokenMatcher de Spaczz, se recomienda usar Matcher 's mucho más rápido.
La regla de Spaczz combina las frases difusas y regex Matchers, y el token Matcher "difuso", en un componente de tuberías que puede actualizar un Doc.ents similar a EntityRuler de Spacy.
Los patrones deben agregarse como un iterable de diccionarios en el formato de {etiqueta (str), patrón (str o list), type (str), kwargs opcional (dict) e id (str)} .
Por ejemplo, un patrón de frase difusa:
{'label': 'ORG', 'pattern': 'Apple' 'kwargs': {'min_r2': 90}, 'type': 'fuzzy'}
O, un patrón de token:
{'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"}}]')
Vemos en el ejemplo anterior que estamos haciendo referencia a algunos atributos personalizados, que se explican a continuación.
Para más ejemplos SpaczzRuler , ver aquí. En particular, esto proporciona detalles sobre el proceso de clasificación de la regla y los parámetros de coincidencia difusa.
Spaczz inicializa algunos atributos personalizados al importar. Estos están bajo Spacy's ._. atributo y se prefieren aún más con spaczz_ por lo que no debería haber conflictos con sus propios atributos personalizados. Si hay spaczz, la fuerza sobrescribirá.
Estos atributos personalizados solo se establecen a través de la regla Spaczz a nivel de token. Las versiones SPAN y DOC de estos atributos son obtenedores que hacen referencia a los atributos de nivel de token.
Los siguientes atributos Token están disponibles. Todos son mutables:
spaczz_token : predeterminado = False . Booleano que denota si el token es parte de una entidad establecida por el gobernante Spaczz.spaczz_type : default = None . Cadena que muestra qué Matcher produjo una entidad usando el token.spaczz_ratio : default = None . Si el token es parte de una entidad coincidente, devolverá la relación difusa.spaczz_pattern : default = None . Si el token es parte de una entidad coincidente, devolverá el patrón como una cadena (JSON formateada para patrones de tokens) que produjo el partido. Los siguientes atributos Span hacen referencia a los atributos de token incluidos en el tramo. Todos son inmutables:
spaczz_ent : default = False . Booleano que denota si todas las fichas en el lapso son parte de una entidad establecida por el gobernante Spaczz.spaczz_type : default = None . Cadena que denota qué Matcher produjo una entidad utilizando los tokens incluidos.spaczz_types : default = set() . Establezca que muestra qué matchers produjo entidades utilizando los tokens incluidos. Un tramo de entidad solo debe tener un tipo, pero esto le permite ver los tipos incluidos en cualquier tramo arbitrario.spaczz_ratio : default = None . Si todas las fichas en el lapso son parte de una entidad coincidente, devolverá la relación difusa.spaczz_pattern : default = None . Si todas las fichas en un lapso son parte de una entidad coincidente, devolverá el patrón como una cadena (JSON formatizada para patrones de tokens) que produjo la coincidencia. Los siguientes atributos Doc hacen referencia a los atributos de token incluidos en el DOC. Todos son inmutables:
spaczz_doc : default = False . Booleano que denota si alguna tokens en el DOC son parte de una entidad establecida por el gobernante Spaczz.spaczz_types : default = set() . Establecer que muestra qué matchers produjo entidades en el doc. El SpaczzRuler tiene los métodos propios de/desde el disco/bytes y aceptará parámetros config pasados a spacy.load() . También tiene su propio punto de entrada de fábrica de Spacy para que Spacy sea consciente del SpaczzRuler . A continuación se muestra un ejemplo de ahorrar y cargar una tubería espacial con el pequeño modelo inglés, el EntityRuler y el 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')
Si bien Spacy hace un trabajo decente al identificar que las entidades nombradas están presentes en este ejemplo, definitivamente podemos mejorar las coincidencias, particularmente con los tipos de etiquetas aplicadas.
Agreguemos una regla de entidad para algunos partidos basados en reglas.
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')
Estamos avanzando, pero Nashville se escribe mal en el texto, por lo que el gobernante de la entidad no lo encuentra, y todavía tenemos otras entidades para arreglar/encontrar.
Agreguemos una regla de spaczz para redondear esta tubería. También incluiremos el atributo personalizado spaczz_span en los resultados para denotar qué entidades se establecieron a través de Spaczz.
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)
¡Impresionante! El pequeño modelo inglés todavía comete un error de reconocimiento de entidad nombrado ("5" en "APT 5" como CARDINAL ), pero estamos satisfechos en general.
Guardemos esta tubería en el disco y asegúrese de que podamos cargarla correctamente.
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']
Incluso podemos asegurarnos de que todos los patrones de regla Spaczz todavía estén presentes.
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 razón principal de la velocidad más lenta de Spaczz es que la C en su nombre no está capitalizada como en Spa C y. Spaczz está escrito en puro Python y sus Matchers actualmente no utilizan vocabularios del lenguaje de Spacy, lo que significa que seguir su lógica debería ser fácil para aquellos familiarizados con Python. Sin embargo, esto significa que los componentes de Spaczz funcionarán más lentamente y probablemente consumirán más memoria que sus contrapartes de Spacy, especialmente a medida que se agregan más patrones y los documentos se hacen más largos. Por lo tanto, se recomienda utilizar componentes espacios como el EntityRuler para entidades con poca incertidumbre, como errores de ortografía consistentes. Use componentes de spaczz cuando no hay alternativas de espacios viables.
Actualmente no estoy trabajando en optimizaciones de rendimiento a Spaczz, pero las sugerencias algorítmicas y de optimización son bienvenidas.
Los métodos principales para acelerar el FuzzyMatcher y SimilarityMatcher son disminuyendo el parámetro flex hacia 0 , o si flex > 0 , aumentando el parámetro min_r1 hacia el valor de min_r2 y/o bajando el parámetro thresh hacia min_r2 . Tenga en cuenta que todas estas "aceleraciones" tienen el costo de oportunidad de los partidos potencialmente mejorados.
Como se menciona en la descripción SimilarityMatcher , la utilización de una GPU también puede ayudar a acelerar su proceso de coincidencia.
Siempre soy abierto y receptivo a las solicitudes de presentar, pero solo tenga en cuenta, como un sol en solar con mucho para aprender, el desarrollo puede moverse bastante lento. La siguiente es mi hoja de ruta para Spaczz para que pueda ver dónde los problemas planteados pueden encajar en mis prioridades actuales.
Nota: Si bien quiero mantener spaczz funcional, no lo estoy desarrollando activamente. Trato de responder a los problemas y solicitudes, pero este proyecto no es actualmente un enfoque mío.
Alta prioridad
Mejoras
Las solicitudes de extracción y los contribuyentes son bienvenidos.
Spaczz está peleado con Flake8, formateado con negro, verificado de tipo con MYPY (aunque esto podría beneficiarse de una especificidad mejorada), probado con PyTest, automatizado con NOx y construido/empaquetado con poesía. Hay algunas otras herramientas de desarrollo detalladas en NoxFile.py, junto con Git Precomitar ganchos.
Para contribuir al desarrollo de Spaczz, bifurca el repositorio y luego instale Spaczz y sus dependencias con poesía. Si está interesado en ser un contribuyente habitual, contácteme directamente.
poetry install # Within spaczz's root directory.Mantengo a Nox y precomito fuera del entorno de poesía como parte de mis entornos de cadena de herramientas de Python. Con el pre-Commit instalado, también es posible que deba ejecutar los siguientes cambios para confirmar.
pre - commit install El único otro paquete que no se instalará a través de la poesía, pero se utiliza para ejemplos de pruebas y de documentación es el modelo Spacy Medium English ( en-core-web-md ). Esto deberá instalarse por separado. El siguiente comando debe hacer el truco:
poetry run python - m spacy download "en_core_web_md"