| Discuta no relevância Slack
SearchArray transforma colunas de string pandas em um índice de termo. Alora a pontuação eficiente do BM25 / TFIDF de frases e tokens individuais.
Pense no Lucene, mas como uma coluna de 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 nesses notebooks:
Guia de SearchArray | Experiência offline de SearchArray | Sobre internos
pip install searcharray
def tokenize(value: str) -> List[str] ) ao indexar.data_dir para indexado para índice mapeado de memóriaPara simplificar a pesquisa lexical na pilha de dados do Python.
Muitos profissionais de ML / AI buscam uma solução de pesquisa vetorial e depois percebem que precisam polvilhar em algum grau de pesquisa BM25 / lexical. Vamos obter a pesquisa de texto completo tradicional para se comportar como outras partes da pilha de dados.
O SearchArray cria uma maneira centrada em pandas de criar e usar um índice de pesquisa como apenas parte de uma matriz de pandas. Em certo sentido, ele constrói um mecanismo de pesquisa em pandas - para permitir que qualquer pessoa prototipe as idéias e execute reranquitação, sem sistemas externos.
Você pode ver um experimento de relevância de pesquisa completa de ponta a ponta neste notebook Colab
Por exemplo, vamos pegar um quadro de dados que tem um monte de texto, como título e visão geral do filme:
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 ...
Indexe o 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 a tokenização idiota - não se preocupe, você pode passar seu próprio tokenizador).
Em seguida, procure, obtendo o Top N com 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])
E como é apenas pandas, podemos, é claro, apenas recuperar as partidas superiores
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': [...
Mais casos de uso podem ser vistos no notebook colab
Os objetivos gerais são recriar muitos dos recursos lexicais (pesquisa de termos / frases) de um mecanismo de pesquisa como Solr ou Elasticsearch, mas em um quadro de dados de pandas.
Queremos que o índice seja o mais eficiente da memória e rápido na pesquisa possível. Queremos usá -lo para ter uma sobrecarga mínima.
Queremos que você possa trabalhar com um conjunto de dados razoável (documentos 100x-1M) de forma relativamente eficiente para avaliação offline. E 1000s para reanganizar rápido em um serviço.
Em vez de construir o 'big data', nosso objetivo é construir para pequenos dados . Ou seja, foco nas capacidades e na expressividade dos pandas, limitando a funcionalidade em favor da escalabilidade.
Para esse fim, as aplicações do SearchArray tendem a se concentrar na experimentação e na reranização de candidatos dos principais n. Para experimentação, queremos que qualquer idéia expressa em pandas tenha um caminho um pouco claro / "contrato" em como eles seriam implementados em um mecanismo clássico de busca lexical. Para reranger, queremos carregar alguns resultados principais de um sistema base e ser capaz de modificá -los.
Sabemos que as técnicas de pesquisa híbrida de pesquisa, RAG e outros problemas de recuperação dominam. No entanto, muitas vezes é elenco em termos de um mecanismo de pesquisa gigante, estranho e de big data que parece estranho para a maioria dos cientistas de dados se unindo a um banco de dados vetorial. Queremos que a pesquisa lexical seja mais acessível aos cientistas de dados e engenheiros de ML construindo esses sistemas.
As bibliotecas Python já fazem tokenização muito bem. Mesmo excedendo o que o Lucene pode fazer ... dando a você a capacidade de simular e/ou exceder as habilidades da tokenização do Lucene.
No SearchArray, um tokenizer é uma função pega uma string e emite uma série de tokens. Ou seja, tokenização de espaço em branco, idiota:
def ws_tokenizer ( string ):
return string . split ()E você pode passar por qualquer tokenizador que corresponda a essa assinatura para indexar:
def ws_lowercase_tokenizer ( string ):
return string . lower (). split ()
df [ 'title_indexed' ] = SearchArray . index ( df [ 'title' ], tokenizer = ws_lowercase_tokenizer )Crie o seu próprio usando bibliotecas Stemming, ou qualquer funcionalidade do Python que desejar.
O Solr possui sua própria consulta de função exclusiva Syntaxhttps: //solr.apache.org/guide/7_7/function-queries.html. Elasticsearch tem indolor.
Em vez de recriá -los, basta usar os pandas nas colunas de pandas existentes. Mais tarde, se você precisar implementar isso no Solr ou no Elasticsearch, tente recriar a funcionalidade. Indiscutivelmente, o que está em Solr / ES seria um subconjunto do que você poderia fazer nos pandas.
# Calculate the number of hours into the past
df['hrs_into_past'] = (now - df['timestamp']).dt.total_seconds() / 3600
Então multiplique pelo BM25 se você quiser:
df['score'] = df['title_indexed'].score('Cat') * df['hrs_into_past']
Nós nos concentramos nos problemas lexicais, ou seja, "BM25-ish" e adjacentes. Existem outras ótimas ferramentas para a pesquisa de vetores por aí.
Visite o canal #searchArray na folga relevante