成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

速度數百倍之差,有人斷言KNN面臨淘汰,更快更強的ANN將取而代之

開發 前端
在模式識別領域中,K - 近鄰算法(K-Nearest Neighbor, KNN)是一種用于分類和回歸的非參數統計方法。

在模式識別領域中,K - 近鄰算法(K-Nearest Neighbor, KNN)是一種用于分類和回歸的非參數統計方法。K - 近鄰算法非常簡單而有效,它的模型表示就是整個訓練數據集。就原理而言,對新數據點的預測結果是通過在整個訓練集上搜索與該數據點最相似的 K 個實例(近鄰)并且總結這 K 個實例的輸出變量而得出的。KNN 可能需要大量的內存或空間來存儲所有數據,并且使用距離或接近程度的度量方法可能會在維度非常高的情況下(有許多輸入變量)崩潰,這可能會對算法在你的問題上的性能產生負面影響。這就是所謂的維數災難。

近似最近鄰算法(Approximate Nearest Neighbor, ANN)則是一種通過犧牲精度來換取時間和空間的方式從大量樣本中獲取最近鄰的方法,并以其存儲空間少、查找效率高等優點引起了人們的廣泛關注。

近日,一家技術公司的數據科學主管 Marie Stephen Leo 撰文對 KNN 與 ANN 進行了比較,結果表明, 在搜索到最近鄰的相似度為 99.3% 的情況下,ANN 比 sklearn 上的 KNN 快了 380 倍 

作者表示,幾乎每門數據科學課程中都會講授 KNN 算法,但它正在走向「淘汰」!

KNN 簡述

在機器學習社區中,找到給定項的「K」個相似項被稱為相似性搜索或最近鄰(NN)搜索。最廣為人知的 NN 搜索算法是 KNN 算法。在 KNN 中,給定諸如手機電商目錄之類的對象集合,則對于任何新的搜索查詢,我們都可以從整個目錄中找到少量(K 個)最近鄰。例如,在下面示例中,如果設置 K = 3,則每個「iPhone」的 3 個最近鄰是另一個「iPhone」。同樣,每個「Samsung」的 3 個最近鄰也都是「Samsung」。

KNN 存在的問題

盡管 KNN 擅長查找相似項,但它使用詳細的成對距離計算來查找鄰居。如果你的數據包含 1000 個項,如若找出新產品的 K=3 最近鄰,則算法需要對數據庫中所有其他產品執行 1000 次新產品距離計算。這還不算太糟糕,但是想象一下,現實世界中的客戶對客戶(Customer-to-Customer,C2C)市場,其中的數據庫包含數百萬種產品,每天可能會上傳數千種新產品。將每個新產品與全部數百萬種產品進行比較是不劃算的,而且耗時良久,也就是說這種方法根本無法擴展。

解決方案

將最近鄰算法擴展至大規模數據的方法是 徹底避開暴力距離計算,使用 ANN 算法。

近似最近距離算法(ANN)

嚴格地講,ANN 是一種在 NN 搜索過程中允許少量誤差的算法。但在實際的 C2C 市場中,真實的鄰居數量比被搜索的 K 近鄰數量要多。與暴力 KNN 相比,人工神經網絡可以在短時間內獲得卓越的準確性。ANN 算法有以下幾種:

  • Spotify 的 ANNOY

  • Google 的 ScaNN

  • Facebook 的 Faiss

  • HNSW

分層的可導航小世界(Hierarchical Navigable Small World, HNSW)

在 HNSW 中,作者描述了一種使用多層圖的 ANN 算法。在插入元素階段,通過指數衰減概率分布隨機選擇每個元素的最大層,逐步構建 HNSW 圖。這確保 layer=0 時有很多元素能夠實現精細搜索,而 layer=2 時支持粗放搜索的元素數量少了 e^-2。最近鄰搜索從最上層開始進行粗略搜索,然后逐步向下處理,直至最底層。使用貪心圖路徑算法遍歷圖,并找到所需鄰居數量。

HNSW 圖結構。最近鄰搜索從最頂層開始(粗放搜索),在最底層結束(精細搜索)。

HNSW Python 包

整個 HNSW 算法代碼已經用帶有 Python 綁定的 C++ 實現了,用戶可以通過鍵入以下命令將其安裝在機器上:pip install hnswlib。安裝并導入軟件包之后,創建 HNSW 圖需要執行一些步驟,這些步驟已經被封裝到了以下函數中:

  1. <code>import hnswlib</code><code>import numpy as npdef fit_hnsw_index(features, ef=100, M=16, save_index_file=False):</code><code>    # Convenience function to create HNSW graph</code><code>    # features : list of lists containing the embeddings</code><code>    # ef, M: parameters to tune the HNSW algorithm</code><code>    </code><code>    num_elements = len(features)</code><code>    labels_index = np.arange(num_elements)    EMBEDDING_SIZE = len(features[0])    # Declaring index</code><code>    # possible space options are l2, cosine or ip</code><code>    p = hnswlib.Index(space='l2', dim=EMBEDDING_SIZE)    # Initing index - the maximum number of elements should be known</code><code>    p.init_index(max_elements=num_elements, ef_construction=ef, M=M)    # Element insertion</code><code>    int_labels = p.add_items(features, labels_index)    # Controlling the recall by setting ef</code><code>    # ef should always be > k</code><code>    p.set_ef(ef) </code><code>    </code><code>    # If you want to save the graph to a file</code><code>    if save_index_file:</code><code>         p.save_index(save_index_file)</code><code>    </code><code>    return p</code> 

創建 HNSW 索引后,查詢「K」個最近鄰就僅需以下這一行代碼:

  1. ann_neighbor_indices, ann_distances = p.knn_query(features, k) 

KNN 和 ANN 基準實驗

計劃

首先下載一個 500K + 行的大型數據集。然后將使用預訓練 fasttext 句子向量將文本列轉換為 300d 嵌入向量。然后將在不同長度的輸入數據 [1000. 10000, 100000, len(data)] 上訓練 KNN 和 HNSW ANN 模型,以度量數據大小對速度的影響。最后將查詢兩個模型中的 K=10 和 K=100 時的最近鄰,以度量「K」對速度的影響。首先導入必要的包和模型。這需要一些時間,因為需要從網絡上下載 fasttext 模型。

  1. <code># Imports</code><code># For input data pre-processing</code><code>import json</code><code>import gzip</code><code>import pandas as pd</code><code>import numpy as np</code><code>import matplotlib.pyplot as plt</code><code>import fasttext.util</code><code>fasttext.util.download_model('en', if_exists='ignore') # English pre-trained model</code><code>ft = fasttext.load_model('cc.en.300.bin')# For KNN vs ANN benchmarking</code><code>from datetime import datetime</code><code>from tqdm import tqdm</code><code>from sklearn.neighbors import NearestNeighbors</code><code>import hnswlib</code> 

數據

使用亞[馬遜產品數據集],其中包含「手機及配件」類別中的 527000 種產品。然后運行以下代碼將其轉換為數據框架。記住僅需要產品 title 列,因為將使用它來搜索相似的產品。

  1. <code># Data: http://deepyeti.ucsd.edu/jianmo/amazon/</code><code>data = []</code><code>with gzip.open('meta_Cell_Phones_and_Accessories.json.gz') as f:</code><code>    for l in f:</code><code>        data.append(json.loads(l.strip()))# Pre-Processing: https://colab.research.google.com/drive/1Zv6MARGQcrBbLHyjPVVMZVnRWsRnVMpV#scrollTo=LgWrDtZ94w89</code><code># Convert list into pandas dataframe</code><code>df = pd.DataFrame.from_dict(data)</code><code>df.fillna('', inplace=True)# Filter unformatted rows</code><code>df = df[~df.title.str.contains('getTime')]# Restrict to just 'Cell Phones and Accessories'</code><code>df = df[df['main_cat']=='Cell Phones & Accessories']# Reset index</code><code>df.reset_index(inplace=True, drop=True)# Only keep the title columns</code><code>df = df[['title']]# Check the df</code><code>print(df.shape)</code><code>df.head()</code> 

如果全部都可以運行精細搜索,你將看到如下輸出:

亞馬遜產品數據集。

嵌入

要對文本數據進行相似性搜索,則必須首先將其轉換為數字向量。一種快速便捷的方法是使用經過預訓練的網絡嵌入層,例如 Facebook [FastText] 提供的嵌入層。由于希望所有行都具有相同的長度向量,而與 title 中的單詞數目無關,所以將在 df 中的 title 列調用 get_sentence_vector 方法。

嵌入完成后,將 emb 列作為一個 list 輸入到 NN 算法中。理想情況下可以在此步驟之前進行一些文本清理預處理。同樣,使用微調的嵌入模型也是一個好主意。

  1. <code># Title Embedding using FastText Sentence Embedding</code><code>df['emb'] = df['title'].apply(ft.get_sentence_vector)# Extract out the embeddings column as a list of lists for input to our NN algos</code><code>X = [item.tolist() for item in df['emb'].values]</code> 

基準

有了算法的輸入,下一步進行基準測試。具體而言,在搜索空間中的產品數量和正在搜索的 K 個最近鄰之間進行循環測試。在每次迭代中,除了記錄每種算法的耗時以外,還要檢查 pct_overlap,因為一定比例的 KNN 最近鄰也被挑選為 ANN 最近鄰。

注意整個測試在一臺全天候運行的 8 核、30GB RAM 機器上運行大約 6 天,這有些耗時。理想情況下,你可以通過多進程來加快運行速度,因為每次運行都相互獨立。

  1. <code># Number of products for benchmark loop</code><code>n_products = [100010000100000, len(X)]# Number of neighbors for benchmark loop</code><code>n_neighbors = [10100]# Dictionary to save metric results for each iteration</code><code>metrics = {'products':[], 'k':[], 'knn_time':[], 'ann_time':[], 'pct_overlap':[]}for products in tqdm(n_products):</code><code>    # "products" number of products included in the search space</code><code>    features = X[:products]</code><code>    </code><code>    for k in tqdm(n_neighbors):   </code><code>        # "K" Nearest Neighbor search</code><code>        # KNN </code><code>        knn_start = datetime.now()</code><code>        nbrs = NearestNeighbors(n_neighbors=k, metric='euclidean').fit(features)</code><code>        knn_distances, knn_neighbor_indices = nbrs.kneighbors(X)</code><code>        knn_end = datetime.now()</code><code>        metrics['knn_time'].append((knn_end - knn_start).total_seconds())</code><code>        </code><code>        # HNSW ANN</code><code>        ann_start = datetime.now()</code><code>        p = fit_hnsw_index(features, ef=k*10)</code><code>        ann_neighbor_indices, ann_distances = p.knn_query(features, k)</code><code>        ann_end = datetime.now()</code><code>        metrics['ann_time'].append((ann_end - ann_start).total_seconds())</code><code>        </code><code>        # Average Percent Overlap in Nearest Neighbors across all "products"</code><code>        metrics['pct_overlap'].append(np.mean([len(np.intersect1d(knn_neighbor_indices[i], ann_neighbor_indices[i]))/k for i in range(len(features))]))</code><code>        </code><code>        metrics['products'].append(products)</code><code>        metrics['k'].append(k)</code><code>        </code><code>metrics_df = pd.DataFrame(metrics)</code><code>metrics_df.to_csv('metrics_df.csv', index=False)</code><code>metrics_df</code> 

運行結束時輸出如下所示。從表中已經能夠看出,HNSW ANN 完全超越了 KNN。

以表格形式呈現的結果。

結果

以圖表的形式查看基準測試的結果,以真正了解二者之間的差異,其中使用標準的 matplotlib 代碼來繪制這些圖表。這種差距是驚人的。根據查詢K=10 和 K=100 最近鄰所需的時間,HNSW ANN 將 KNN 徹底淘汰。當搜索空間包含約 50 萬個產品時,在 ANN 上搜索 100 個最近鄰的速度是 KNN 的 380 倍,同時兩者搜索到最近鄰的相似度為 99.3%。

在搜索空間包含 500K 個元素,搜索空間中每個元素找到 K=100 最近鄰時,HNSW ANN 的速度比 Sklearn 的 KNN 快 380 倍。

在搜索空間包含 500K 個元素,搜索空間中每個元素找到 K=100 最近鄰時,HNSW ANN 和 KNN 搜索到最近鄰的相似度為 99.3%。

基于以上結果,作者認為可以大膽地說:「KNN 已死」。

本篇文章的代碼作者已在 GitHub 上給出:https://github.com/stephenleo/adventures-with-ann/blob/main/knn_is_dead.ipynb

 

責任編輯:張燕妮 來源: 機器之心
相關推薦

2021-12-29 10:26:58

芯片半導體技術

2014-11-11 15:57:07

2019-06-14 08:28:32

SQL數據庫語句

2024-08-01 08:06:11

虛擬線程性能

2022-05-26 08:12:39

PandasApply技巧

2023-04-14 07:09:04

2009-07-08 11:44:40

ScalaGroovyJVM

2024-09-09 09:40:00

OpenAIGPT-4

2022-04-06 14:45:04

神經網絡框架技術

2012-11-21 17:35:21

Oracle技術嘉年華

2021-12-27 06:57:40

Maven工具性能

2016-03-04 14:40:35

華為

2015-09-24 10:18:54

程序員身價

2015-03-12 10:21:05

阿里云宕機

2020-08-30 14:29:01

Pandas數據分析函數

2022-12-12 13:36:04

Python編譯器

2023-06-26 22:15:14

ChatGPT思維模型

2023-05-31 07:24:48

2018-12-10 11:00:01

MySQL數據庫索引

2021-06-01 09:58:53

Windows 10EdgeChrono
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲小视频在线观看 | 日韩免费一区二区 | 免费国产黄网站在线观看视频 | 亚洲成a| 国产精久久久 | 久草影视在线 | 国产精品1区2区 | 日韩视频中文字幕 | 亚洲成人免费在线 | 九九热精品在线视频 | 亚洲免费影院 | 狠狠做六月爱婷婷综合aⅴ 国产精品视频网 | 色婷婷综合久久久中字幕精品久久 | 国产精品久久久久久久免费大片 | 国产高清在线精品 | 国产婷婷精品av在线 | 欧洲视频一区二区 | 中文字幕高清av | 午夜91| 成人h片在线观看 | av中文在线观看 | 亚洲视频在线观看 | 福利网站在线观看 | av片在线播放 | 草草视频在线观看 | 91一区二区三区 | 国产精品日韩欧美一区二区三区 | 免费视频一区二区 | 99精品久久 | 欧美一区二区大片 | 中文字幕一区在线观看视频 | 人人爱干 | 综合国产 | 久久天堂网 | 国产精品久久国产精品 | 中文字幕三区 | 国产欧美日韩一区二区三区 | 亚洲美女在线一区 | 日韩欧美在线观看视频 | 这里精品| 国产免费播放视频 |