| Discuta en relevante holgura
SearchArray convierte las columnas de cadena Pandas en un índice de término. Afecta la puntuación eficiente de BM25 / TFIDF de frases y tokens individuales.
Piensa en Lucene, pero como una columna Pandas.
from searcharray import SearchArray
import pandas as pd
df [ 'title_indexed' ] = SearchArray . index ( df [ 'title' ])
np . sort ( df [ 'title_indexed' ]. array . score ([ 'cat' , 'in' , 'the' , 'hat' ])) # Search w/ phrase
> BM25 scores :
> array ([ 0. , 0. , 0. , ..., 15.84568033 , 15.84568033 , 15.84568033 ])SearchArray está documentado en estos cuadernos:
SearchArray Guide | SearchArray Experimento fuera de línea | Sobre las partes internas
pip install searcharray
def tokenize(value: str) -> List[str] ) al indexar.data_dir al índice para el índice mapeado de memoriaPara simplificar la búsqueda léxica en la pila de datos de Python.
Muchos practicantes de ML / AI alcanzan una solución de búsqueda vectorial, luego se dan cuenta de que necesitan espolvorear en cierto grado de BM25 / búsqueda léxica. Obtenemos una búsqueda tradicional de texto completo para comportarse como otras partes de la pila de datos.
SearchArray crea una forma centrada en los pandas de crear y usar un índice de búsqueda como solo parte de una matriz de pandas. En cierto sentido, construye un motor de búsqueda en los pandas, para permitir que cualquiera protot sea de prototipo de ideas y realice un rescate, sin sistemas externos.
Puede ver un experimento completo de relevancia de búsqueda de extremo a extremo en este cuaderno de colab.
Es decir, tomemos un marco de datos que tenga un montón de texto, como el título de la película y las descripción general:
In[1]: df = pd.DataFrame({'title': titles, 'overview': overviews}, index=ids)
Out[1]:
title overview
374430 Black Mirror: White Christmas This feature-length special consists of three ...
19404 The Brave-Hearted Will Take the Bride Raj is a rich, carefree, happy-go-lucky second...
278 The Shawshank Redemption Framed in the 1940s for the double murder of h...
372058 Your Name. High schoolers Mitsuha and Taki are complete s...
238 The Godfather Spanning the years 1945 to 1955, a chronicle o...
... ... ...
65513 They Came Back The lives of the residents of a small French t...
65515 The Eleventh Hour An ex-Navy SEAL, Michael Adams, (Matthew Reese...
65521 Pyaar Ka Punchnama Outspoken and overly critical Nishant Agarwal ...
32767 Romero Romero is a compelling and deeply moving look ...
Index el texto:
In[2]: df['title_indexed'] = SearchArray.index(df['title'])
df
Out[2]:
title overview title_indexed
374430 Black Mirror: White Christmas This feature-length special consists of three ... Terms({'Black', 'Mirror:', 'White'...
19404 The Brave-Hearted Will Take the Bride Raj is a rich, carefree, happy-go-lucky second... Terms({'The', 'Brave-Hearted', 'Wi...
278 The Shawshank Redemption Framed in the 1940s for the double murder of h... Terms({'The', 'Shawshank', 'Redemp...
372058 Your Name. High schoolers Mitsuha and Taki are complete s... Terms({'Your', 'Name.'}, {'Your': ...
238 The Godfather Spanning the years 1945 to 1955, a chronicle o... Terms({'The', 'Godfather'}, {'The'...
... ... ... ...
65513 They Came Back The lives of the residents of a small French t... Terms({'Back', 'They', 'Came'},...
65515 The Eleventh Hour An ex-Navy SEAL, Michael Adams, (Matthew Reese... Terms({'The', 'Hour', 'Eleventh': ...
65521 Pyaar Ka Punchnama Outspoken and overly critical Nishant Agarwal ... Terms({'Ka', 'Pyaar', 'Punchnama':...
32767 Romero Romero is a compelling and deeply moving look ... Terms({'Romero'})
65534 Poison Paul Braconnier and his wife Blandine only hav... Terms({'Poison'})```
(Observe la tokenización tonta: no se preocupe, puede pasar su propio tokenizador).
Luego busca, conseguir que Top n con Cat
In[3]: np.sort(df['title_indexed'].array.score('Cat'))
Out[3]: array([ 0. , 0. , 0. , ..., 15.84568033,
15.84568033, 15.84568033])
In[4]: df['title_indexed'].score('Cat').argsort()
Out[4]:
array([0, 18561, 18560, ..., 15038, 19012, 4392])
Y dado que es solo pandas, podemos, por supuesto, solo recuperar los mejores partidos
In[5]: df.iloc[top_n_cat[-10:]]
Out[5]:
title overview title_indexed
24106 The Black Cat American honeymooners in Hungary are trapped i... Terms({'Black': 1, 'The': 1, 'Cat': 1}, ...
12593 Fritz the Cat A hypocritical swinging college student cat ra... Terms({'Cat': 1, 'the': 1, 'Fritz': 1}, ...
39853 The Cat Concerto Tom enters from stage left in white tie and ta... Terms({'The': 1, 'Cat': 1, 'Concerto': 1...
75491 The Rabbi's Cat Based on the best-selling graphic novel by Joa... Terms({'The': 1, 'Cat': 1, "Rabbi's": 1}...
57353 Cat Run When a sexy, high-end escort holds the key evi... Terms({'Cat': 1, 'Run': 1}, {'Cat': [0],...
25508 Cat People Sketch artist Irena Dubrovna (Simon) and Ameri... Terms({'Cat': 1, 'People': 1}, {'Cat': [...
11694 Cat Ballou A woman seeking revenge for her murdered fathe... Terms({'Cat': 1, 'Ballou': 1}, {'Cat': [...
25078 Cat Soup The surreal black comedy follows Nyatta, an an... Terms({'Cat': 1, 'Soup': 1}, {'Cat': [0]...
35888 Cat Chaser A Miami hotel owner finds danger when be becom... Terms({'Cat': 1, 'Chaser': 1}, {'Cat': [...
6217 Cat People After years of separation, Irina (Nastassja Ki... Terms({'Cat': 1, 'People': 1}, {'Cat': [...
Se pueden ver más casos de uso en el cuaderno Colab
Los objetivos generales son recrear muchas de las características léxicas (búsqueda de términos / frases) de un motor de búsqueda como Solr o Elasticsearch, pero en un marco de datos PANDAS.
Queremos que el índice sea lo más eficiente y rápido en la búsqueda posible. Queremos usarlo para tener una sobrecarga mínima.
Queremos que pueda trabajar con un conjunto de datos razonable (documentos de 100x-1 m) de manera relativamente eficiente para la evaluación fuera de línea. Y 1000 para volver a ser rápido en un servicio.
En lugar de construir 'Big Data', nuestro objetivo es construir para datos pequeños . Es decir, centrarse en las capacidades y la expresividad de los pandas, sobre la funcionalidad limitante a favor de la escalabilidad.
Con este fin, las aplicaciones de SearchArray tenderán a centrarse en la experimentación y el mejor candidato de los candidatos. Para la experimentación, queremos que cualquier idea expresada en los pandas tenga una ruta / "contrato" algo clara sobre cómo se implementarían en un motor de búsqueda léxico clásico. Para el rescate, queremos cargar algunos resultados principales de un sistema base y poder modificarlos.
Sabemos que en la búsqueda, el trapo y otros problemas de recuperación dominan las técnicas de búsqueda híbrida. Sin embargo, a menudo su elenco en términos de un motor de búsqueda léxico gigante y extraño y big data que parece extraño para la mayoría de los científicos de datos que se unen con una base de datos vectorial. Queremos que la búsqueda léxica sea más accesible para los científicos de datos e ingenieros de ML que construyen estos sistemas.
Las bibliotecas de Python ya hacen la tokenización muy bien. Incluso superando lo que Lucene puede hacer ... dándote la capacidad de simular y/o exceder las habilidades de la tokenización de Lucene.
En SearchArray, un tokenizer es una función que toma una cadena y emite una serie de tokens. Es decir, tonta, tokenización predeterminada de espacios blancos:
def ws_tokenizer ( string ):
return string . split ()Y puede pasar cualquier tokenizador que coincida con esta firma con el índice:
def ws_lowercase_tokenizer ( string ):
return string . lower (). split ()
df [ 'title_indexed' ] = SearchArray . index ( df [ 'title' ], tokenizer = ws_lowercase_tokenizer )Cree el suyo con las bibliotecas Stemming, o cualquier funcionalidad de Python que desee.
SOLR tiene su propia función única de consulta sintaxhttps: //solr.apache.org/guide/7_7/function-queries.html. Elasticsearch tiene dolor.
En lugar de recrearlos, simplemente use pandas en las columnas de pandas existentes. Luego, más tarde, si necesita implementar esto en Solr o Elasticsearch, intente recrear la funcionalidad. Podría decirse que lo que hay en Solr / ES sería un subconjunto de lo que podría hacer en los pandas.
# Calculate the number of hours into the past
df['hrs_into_past'] = (now - df['timestamp']).dt.total_seconds() / 3600
Luego multiplique por BM25 si desea:
df['score'] = df['title_indexed'].score('Cat') * df['hrs_into_past']
Nos centramos en los problemas léxicos, es decir, "BM25-ish" y adyacentes. Hay otras grandes herramientas para la búsqueda de vectores.
Visite el canal #SearchArray en relevancia