Redisearch魔法:輕松實(shí)現(xiàn)K近鄰查詢(xún)

Redis作為一款高性能的內(nèi)存數(shù)據(jù)庫(kù)熊榛,廣泛應(yīng)用于各種場(chǎng)景蹬敲,如緩存识藤、消息隊(duì)列和實(shí)時(shí)計(jì)算挖垛。今天,我們將探討Redisearch模塊刻两,它可以讓我們輕松實(shí)現(xiàn)K近鄰查詢(xún)增蹭。本文旨在幫助Redis初學(xué)者理解K近鄰查詢(xún),并學(xué)會(huì)如何利用Redisearch實(shí)現(xiàn)這一功能磅摹。

什么是K近鄰查詢(xún)滋迈?

K近鄰(K-Nearest Neighbors,簡(jiǎn)稱(chēng)KNN)查詢(xún)是一種機(jī)器學(xué)習(xí)方法户誓,它可以用于分類(lèi)饼灿、回歸和推薦等任務(wù)。在K近鄰查詢(xún)中帝美,我們根據(jù)數(shù)據(jù)點(diǎn)之間的距離(如歐幾里得距離或余弦相似度)來(lái)確定它們之間的相似性碍彭。KNN算法的基本思想是:對(duì)于待分類(lèi)的數(shù)據(jù)點(diǎn),找到距離它最近的K個(gè)訓(xùn)練樣本點(diǎn)悼潭,根據(jù)這K個(gè)鄰居的信息來(lái)預(yù)測(cè)待分類(lèi)點(diǎn)的屬性庇忌。

什么是Redisearch?

Redisearch是Redis的一個(gè)模塊舰褪,它提供了全文搜索皆疹、索引和聚合功能。通過(guò)Redisearch占拍,我們可以輕松地為Redis中的數(shù)據(jù)創(chuàng)建索引略就,執(zhí)行復(fù)雜的搜索查詢(xún),并實(shí)現(xiàn)高級(jí)功能晃酒,如自動(dòng)完成表牢、分面搜索和排序。使用Redisearch贝次,我們可以利用Redis的高性能特點(diǎn)崔兴,實(shí)現(xiàn)高效的搜索和實(shí)時(shí)分析。
如何使用Redisearch實(shí)現(xiàn)K近鄰查詢(xún)?

為了實(shí)現(xiàn)K近鄰查詢(xún)敲茄,我們首先需要為數(shù)據(jù)創(chuàng)建一個(gè)Redisearch索引螺戳,其中包括一個(gè)用于存儲(chǔ)向量表示的字段。這些向量通常是由深度學(xué)習(xí)模型生成的高維數(shù)據(jù)表示折汞,可以捕捉數(shù)據(jù)之間的相似性。接下來(lái)盖腿,我們將使用自定義查詢(xún)函數(shù)爽待,結(jié)合Redisearch提供的搜索和排序功能,實(shí)現(xiàn)K近鄰查詢(xún)翩腐。

什么是文本向量表示?

文本向量表示是將自然語(yǔ)言文本轉(zhuǎn)換為固定長(zhǎng)度的數(shù)值向量鸟款。這些向量可以捕捉文本的語(yǔ)義信息,使得相似的文本具有相似的向量表示茂卦。文本向量通常是由諸如word2vec何什、GloVe、BERT等龙、GPT等預(yù)訓(xùn)練的神經(jīng)網(wǎng)絡(luò)模型生成的处渣。

以下是一個(gè)使用Gensim庫(kù)加載預(yù)訓(xùn)練的word2vec模型并獲取單詞“apple”的向量表示的示例:


import gensim.downloader as api

# 加載預(yù)訓(xùn)練的word2vec模型
model = api.load("word2vec-google-news-300")

# 獲取單詞"apple"的向量表示
word_vector = model["apple"]

# 輸出向量表示
print(word_vector)

輸出示例(前10個(gè)數(shù)值):

[ 0.10644531  0.04785156 -0.02258301 -0.06225586  0.01318359  0.05834961 -0.07666016  0.01525879  0.02563477 -0.06787109 ...]

請(qǐng)注意,實(shí)際的向量表示將包含300個(gè)浮點(diǎn)數(shù)值蛛砰,但這里僅顯示了前10個(gè)罐栈。這個(gè)向量表示捕捉了單詞“apple”的語(yǔ)義信息,可以用于文本相似性計(jì)算泥畅、文本分類(lèi)等自然語(yǔ)言處理任務(wù)荠诬。

文本向量怎么進(jìn)行對(duì)比?

通過(guò)比較兩個(gè)文本生成的向量位仁,我們可以衡量它們的語(yǔ)義相似性柑贞。通常,我們使用一種相似性度量方法來(lái)計(jì)算兩個(gè)向量之間的相似性得分聂抢。常用的相似性度量方法包括余弦相似性和歐幾里得距離钧嘶。

  1. 余弦相似性:余弦相似性衡量的是兩個(gè)向量之間的夾角的余弦值。它的取值范圍是[-1, 1]涛浙,值越接近1康辑,表示向量越相似;值越接近-1轿亮,表示向量越不相似疮薇。余弦相似性計(jì)算公式如下:

cos_sim(A, B) = dot_product(A, B) / (norm(A) * norm(B))

其中,dot_product(A, B)表示向量A和向量B的點(diǎn)積我注,norm(A)表示向量A的模長(zhǎng)按咒。

  1. 歐幾里得距離:歐幾里得距離衡量的是兩個(gè)向量在空間中的直線(xiàn)距離。數(shù)值越小,表示兩個(gè)向量越相似励七。歐幾里得距離計(jì)算公式如下:

    euclidean_distance(A, B) = sqrt(sum((A_i - B_i)^2 for i in range(len(A))))

    其中智袭,A_i和B_i分別表示向量A和向量B的第i個(gè)分量。

通過(guò)計(jì)算文本向量之間的相似性得分掠抬,我們可以確定哪些文本在語(yǔ)義上更相似吼野。這種方法可以用于許多自然語(yǔ)言處理任務(wù),如文本聚類(lèi)两波、文檔檢索和推薦系統(tǒng)等瞳步。

如何使用Redisearch實(shí)現(xiàn)K近鄰查詢(xún)

在這一部分,我們將詳細(xì)說(shuō)明如何使用Redisearch實(shí)現(xiàn)K近鄰查詢(xún)腰奋。主要分為以下幾個(gè)步驟:

1. 安裝Redisearch模塊并啟用单起。
2. 為數(shù)據(jù)創(chuàng)建一個(gè)Redisearch索引,包括一個(gè)用于存儲(chǔ)向量表示的字段劣坊。
3. 使用深度學(xué)習(xí)模型(如BERT嘀倒、Word2Vec等)為數(shù)據(jù)生成向量表示,并將它們存儲(chǔ)在Redisearch索引中局冰。
4. 構(gòu)建一個(gè)自定義查詢(xún)字符串测蘑,用于執(zhí)行K近鄰查詢(xún)。
5. 使用Redisearch的搜索和排序功能康二,根據(jù)查詢(xún)向量找到最相關(guān)的數(shù)據(jù)帮寻。

1. 安裝Redisearch模塊并啟用

要使用Redisearch,您需要安裝并啟用Redisearch模塊赠摇。有關(guān)詳細(xì)的安裝說(shuō)明固逗,請(qǐng)參閱Redisearch官方文檔:安裝Redisearch

2. 為數(shù)據(jù)創(chuàng)建Redisearch索引

創(chuàng)建Redisearch索引的語(yǔ)法如下:

FT.CREATE {index_name} [NOOFFSETS] [NOFIELDS] [NOSCOREIDX] [STOPWORDS {num}] [SCHEMA {field_name} {type} [options] ...]

在我們的例子中藕帜,假設(shè)我們有一組文本數(shù)據(jù)烫罩,我們想要根據(jù)它們的向量表示執(zhí)行K近鄰查詢(xún)。我們可以創(chuàng)建一個(gè)包含textembedding字段的索引:

FT.CREATE myindex SCHEMA text TEXT embedding VECTOR

3. 生成向量表示并將其存儲(chǔ)在Redisearch索引中

為了計(jì)算文本數(shù)據(jù)的向量表示洽故,您需要選擇一個(gè)合適的深度學(xué)習(xí)模型贝攒,如BERT、Word2Vec或GPT时甚。然后隘弊,您可以使用這些模型將文本轉(zhuǎn)換為高維向量。

以BERT模型為例荒适,您可以使用huggingface/transformers庫(kù)為文本生成向量表示梨熙。將向量表示存儲(chǔ)在Redisearch索引中的示例代碼如下:

import redis
from transformers import AutoTokenizer, AutoModel

# 初始化BERT模型和tokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModel.from_pretrained("bert-base-uncased")

# 準(zhǔn)備文本數(shù)據(jù)
text = "This is an example sentence."

# 使用tokenizer將文本轉(zhuǎn)換為token
tokens = tokenizer(text, return_tensors="pt")

# 使用BERT模型為文本生成向量表示
embeddings = model(**tokens).last_hidden_state.mean(dim=1).squeeze().tolist()

# 連接Redis,并將文本和embeddings存儲(chǔ)在索引中
r = redis.StrictRedis()
r.execute_command("FT.ADD", "myindex", "doc1", "1.0", "FIELDS", "text", text, "embedding", ",".join(map(str, embeddings)))

4. 構(gòu)建自定義查詢(xún)字符串

為了執(zhí)行K近鄰查詢(xún)刀诬,我們需要構(gòu)建一個(gè)自定義查詢(xún)字符串咽扇。在這個(gè)例子中,我們使用了如下格式的查詢(xún)字符串:

"*=>[KNN {num_relevant} @embedding $vector AS vector_score]"

其中,num_relevant是我們想要返回的最相關(guān)結(jié)果的數(shù)量质欲,$vector是我們想要與索引中的數(shù)據(jù)進(jìn)行比較的查詢(xún)向量树埠。
在查詢(xún)字符串中,* 表示搜索所有文檔嘶伟,=>是一個(gè)映射操作符怎憋,用于將輸入文檔映射到新的搜索結(jié)果。KNN 是一個(gè)特殊的聚合函數(shù)九昧,用于計(jì)算查詢(xún)向量與索引中文檔的向量之間的相似度盛霎。@embedding 表示我們要使用索引中的embedding字段作為向量。AS vector_score 表示將每個(gè)文檔的相似度得分存儲(chǔ)在名為vector_score的字段中耽装。

案例分析:

*=>[KNN 5 @embedding $vector AS vector_score]
    • 是一個(gè)通配符,表示返回所有文檔期揪。這是查詢(xún)的起點(diǎn)掉奄,之后會(huì)應(yīng)用其他過(guò)濾器或函數(shù)。
  1. => 是一個(gè)箭頭操作符凤薛,它用于將查詢(xún)結(jié)果傳遞給下一個(gè)步驟姓建。在這里,它將所有文檔傳遞給 [KNN 5 @embedding $vector AS vector_score]函數(shù)缤苫。
  2. [KNN 5 @embedding $vector AS vector_score] 是一個(gè)自定義函數(shù)速兔,它的目的是對(duì)所有文檔進(jìn)行排序,以便返回最相關(guān)的結(jié)果活玲。這個(gè)函數(shù)有以下參數(shù):
    • KNN 5 表示返回與查詢(xún)向量最接近的5個(gè)文檔涣狗。
    • @embedding 是Redisearch索引中的字段名,用于存儲(chǔ)嵌入向量舒憾。
    • $vector 是傳遞給查詢(xún)的參數(shù)镀钓,表示要與文檔中的向量進(jìn)行比較的向量。
    • AS vector_score 表示將排序結(jié)果的分?jǐn)?shù)(相關(guān)性度量)存儲(chǔ)在名為vector_score的字段中镀迂。

實(shí)際上丁溅,base_query字符串并不是固定的。您可以根據(jù)需要修改查詢(xún)字符串探遵,以適應(yīng)您的應(yīng)用程序需求窟赏。例如,您可以更改KNN參數(shù)以返回更多或更少的相關(guān)結(jié)果箱季。但請(qǐng)注意涯穷,修改查詢(xún)字符串可能會(huì)影響查詢(xún)的結(jié)果和性能。

5. 使用Redisearch搜索和排序功能執(zhí)行K近鄰查詢(xún)

最后藏雏,我們可以使用Redisearch的搜索和排序功能執(zhí)行K近鄰查詢(xún)求豫。以下是一個(gè)示例Python代碼:

from redisearch import Client, Query

def knn_search(query_vector, num_relevant=5):
    # 創(chuàng)建Redisearch客戶(hù)端
    client = Client("myindex")
    
    # 構(gòu)建基本查詢(xún)字符串
    base_query = f"*=>[KNN {num_relevant} @embedding $vector AS vector_score]"
    
    # 使用Query類(lèi)構(gòu)建查詢(xún)
    query = Query(base_query).return_fields("text", "vector_score").sort_by("vector_score").dialect(2)

    # 將查詢(xún)向量轉(zhuǎn)換為字符串
    query_vector_str = ",".join(map(str, query_vector))

    # 執(zhí)行查詢(xún),并將查詢(xún)向量傳遞給Redisearch
    results = client.search(query, query_params={"vector": query_vector_str})
    
    # 返回查詢(xún)結(jié)果
    return results

# 示例查詢(xún)向量
example_query_vector = [0.1, 0.2, 0.3, 0.4, 0.5]

# 執(zhí)行K近鄰查詢(xún)
result = knn_search(example_query_vector)

# 打印查詢(xún)結(jié)果
print(result)

這個(gè)示例代碼首先創(chuàng)建了一個(gè)Client對(duì)象,用于與Redisearch索引進(jìn)行通信蝠嘉。然后最疆,我們使用Query類(lèi)構(gòu)建查詢(xún),并指定要返回的字段(textvector_score)以及按照相似度得分(vector_score)排序蚤告。最后努酸,我們使用client.search()方法執(zhí)行查詢(xún),并將查詢(xún)向量傳遞給Redisearch杜恰。

這樣获诈,我們就完成了使用Redisearch實(shí)現(xiàn)K近鄰查詢(xún)的過(guò)程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末心褐,一起剝皮案震驚了整個(gè)濱河市舔涎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌逗爹,老刑警劉巖亡嫌,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異掘而,居然都是意外死亡挟冠,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)袍睡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)知染,“玉大人,你說(shuō)我怎么就攤上這事斑胜】氐” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵止潘,是天一觀的道長(zhǎng)逸寓。 經(jīng)常有香客問(wèn)我,道長(zhǎng)覆山,這世上最難降的妖魔是什么竹伸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮簇宽,結(jié)果婚禮上勋篓,老公的妹妹穿的比我還像新娘。我一直安慰自己魏割,他們只是感情好譬嚣,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著钞它,像睡著了一般拜银。 火紅的嫁衣襯著肌膚如雪殊鞭。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,842評(píng)論 1 290
  • 那天尼桶,我揣著相機(jī)與錄音操灿,去河邊找鬼。 笑死泵督,一個(gè)胖子當(dāng)著我的面吹牛趾盐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播小腊,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼救鲤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了秩冈?” 一聲冷哼從身側(cè)響起本缠,我...
    開(kāi)封第一講書(shū)人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎入问,沒(méi)想到半個(gè)月后丹锹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡队他,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了峻村。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片麸折。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖粘昨,靈堂內(nèi)的尸體忽然破棺而出垢啼,到底是詐尸還是另有隱情,我是刑警寧澤张肾,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布芭析,位于F島的核電站,受9級(jí)特大地震影響吞瞪,放射性物質(zhì)發(fā)生泄漏馁启。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一芍秆、第九天 我趴在偏房一處隱蔽的房頂上張望惯疙。 院中可真熱鬧,春花似錦妖啥、人聲如沸霉颠。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蒿偎。三九已至朽们,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間诉位,已是汗流浹背骑脱。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留不从,地道東北人惜姐。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像椿息,于是被迫代替她去往敵國(guó)和親歹袁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容