0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

数据科学经典算法 KNN 已被嫌慢,ANN 比它快 380 倍

工程师邓生 来源:towardsdatascience 作者:Marie Stephen Leo 2021-01-02 09:08 次阅读

数据科学经典算法 KNN 已被嫌慢,ANN 比它快 380 倍。

在模式识别领域中,K - 近邻算法(K-Nearest Neighbor, KNN)是一种用于分类和回归的非参数统计方法。K - 近邻算法非常简单而有效,它的模型表示就是整个训练数据集。就原理而言,对新数据点的预测结果是通过在整个训练集上搜索与该数据点最相似的 K 个实例(近邻)并且总结这 K 个实例的输出变量而得出的。KNN 可能需要大量的内存或空间来存储所有数据,并且使用距离或接近程度的度量方法可能会在维度非常高的情况下(有许多输入变量)崩溃,这可能会对算法在你的问题上的性能产生负面影响。这就是所谓的维数灾难。

近似最近邻算法(Approximate Nearest Neighbor, ANN)则是一种通过牺牲精度来换取时间和空间的方式从大量样本中获取最近邻的方法,并以其存储空间少、查找效率高等优点引起了人们的广泛关注。

近日,一家技术公司的数据科学主管 Marie Stephen Leo 撰文对 KNN 与 ANN 进行了比较,结果表明,在搜索到最近邻的相似度为 99.3% 的情况下,ANN 比 sklearn 上的 KNN 快了 380 倍。

a2e271361afb4c5889683a90ecfef23a.png

作者表示,几乎每门数据科学课程中都会讲授 KNN 算法,但它正在走向「淘汰」!

KNN 简述

机器学习社区中,找到给定项的「K」个相似项被称为相似性搜索或最近邻(NN)搜索。最广为人知的 NN 搜索算法是 KNN 算法。在 KNN 中,给定诸如手机电商目录之类的对象集合,则对于任何新的搜索查询,我们都可以从整个目录中找到少量(K 个)最近邻。例如,在下面示例中,如果设置 K = 3,则每个「iPhone」的 3 个最近邻是另一个「iPhone」。同样,每个「Samsung」的 3 个最近邻也都是「Samsung」。

3fdca620b30d40bca1be80fa1b392cb8.png

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。最近邻搜索从最上层开始进行粗略搜索,然后逐步向下处理,直至最底层。使用贪心图路径算法遍历图,并找到所需邻居数量。

7666da0523e947aa9d1330d5e601650d.png

HNSW 图结构。最近邻搜索从最顶层开始(粗放搜索),在最底层结束(精细搜索)。

HNSW Python

整个 HNSW 算法代码已经用带有 Python 绑定的 C++ 实现了,用户可以通过键入以下命令将其安装在机器上:pip install hnswlib。安装并导入软件包之后,创建 HNSW 图需要执行一些步骤,这些步骤已经被封装到了以下函数中:

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

创建 HNSW 索引后,查询「K」个最近邻就仅需以下这一行代码:

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 模型。

# Imports # For input data pre-processing importjson importgzip importpandas aspd importnumpy asnp importmatplotlib.pyplot asplt importfasttext.util fasttext.util.download_model( ‘en’, if_exists= ‘ignore’) # English pre-trained model ft = fasttext.load_model( ‘cc.en.300.bin’) # For KNN vs ANN benchmarking fromdatetime importdatetime fromtqdm importtqdm fromsklearn.neighbors importNearestNeighbors importhnswlib

数据

使用亚[马逊产品数据集],其中包含「手机及配件」类别中的 527000 种产品。然后运行以下代码将其转换为数据框架。记住仅需要产品 title 列,因为将使用它来搜索相似的产品。

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

如果全部都可以运行精细搜索,你将看到如下输出:

e76823475ea0447c8dab3b17ecbb982b.png

亚马逊产品数据集。

嵌入

要对文本数据进行相似性搜索,则必须首先将其转换为数字向量。一种快速便捷的方法是使用经过预训练的网络嵌入层,例如 Facebook [FastText] 提供的嵌入层。由于希望所有行都具有相同的长度向量,而与 title 中的单词数目无关,所以将在 df 中的 title 列调用 get_sentence_vector 方法。

嵌入完成后,将 emb 列作为一个 list 输入到 NN 算法中。理想情况下可以在此步骤之前进行一些文本清理预处理。同样,使用微调的嵌入模型也是一个好主意。

# Title Embedding using FastText Sentence Embedding 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 X = [item.tolist foritem indf[ ‘emb’].values]

基准

有了算法的输入,下一步进行基准测试。具体而言,在搜索空间中的产品数量和正在搜索的 K 个最近邻之间进行循环测试。在每次迭代中,除了记录每种算法的耗时以外,还要检查 pct_overlap,因为一定比例的 KNN 最近邻也被挑选为 ANN 最近邻。

注意整个测试在一台全天候运行的 8 核、30GB RAM 机器上运行大约 6 天,这有些耗时。理想情况下,你可以通过多进程来加快运行速度,因为每次运行都相互独立。

# Number of products for benchmark loop n_products = [ 1000, 10000, 100000, len(X)] # Number of neighbors for benchmark loop n_neighbors = [ 10, 100] # Dictionary to save metric results for each iteration metrics = { ‘products’:[], ‘k’:[], ‘knn_time’:[], ‘ann_time’:[], ‘pct_overlap’:[]} forproducts intqdm(n_products): # “products” number of products included in the search space features = X[ :products] fork intqdm(n_neighbors): # “K” Nearest Neighbor search # KNN knn_start = datetime.now nbrs = NearestNeighbors(n_neighbors=k, metric= ‘euclidean’).fit(features) knn_distances, knn_neighbor_indices = nbrs.kneighbors(X) knn_end = datetime.now metrics[ ‘knn_time’].append((knn_end - knn_start).total_seconds) # HNSW ANN ann_start = datetime.now p = fit_hnsw_index(features, ef=k* 10) ann_neighbor_indices, ann_distances = p.knn_query(features, k) ann_end = datetime.now metrics[ ‘ann_time’].append((ann_end - ann_start).total_seconds) # Average Percent Overlap in Nearest Neighbors across all “products” metrics[ ‘pct_overlap’].append(np.mean([len(np.intersect1d(knn_neighbor_indices[i], ann_neighbor_indices[i]))/k fori inrange(len(features))])) metrics[ ‘products’].append(products) metrics[ ‘k’].append(k) metrics_df = pd.DataFrame(metrics) metrics_df.to_csv( ‘metrics_df.csv’, index=False) metrics_df

运行结束时输出如下所示。从表中已经能够看出,HNSW ANN 完全超越了 KNN。

2ae31eb61e2443cd9a11c5262fd24267.png

以表格形式呈现的结果。

结果

以图表的形式查看基准测试的结果,以真正了解二者之间的差异,其中使用标准的 matplotlib 代码来绘制这些图表。这种差距是惊人的。根据查询 K=10 和 K=100 最近邻所需的时间,HNSW ANN 将 KNN 彻底淘汰。当搜索空间包含约 50 万个产品时,在 ANN 上搜索 100 个最近邻的速度是 KNN 的 380 倍,同时两者搜索到最近邻的相似度为 99.3%。

72f62f2539154d1ab460c64bf2f653c4.png

在搜索空间包含 500K 个元素,搜索空间中每个元素找到 K=100 最近邻时,HNSW ANN 的速度比 Sklearn 的 KNN 快 380 倍。

0203f1a11cb044cfa5f81724957cc9a1.png

在搜索空间包含 500K 个元素,搜索空间中每个元素找到 K=100 最近邻时,HNSW ANN 和 KNN 搜索到最近邻的相似度为 99.3%。

基于以上结果,作者认为可以大胆地说:「KNN 已死」。

责任编辑:PSY

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    7017

    浏览量

    89010
  • 算法
    +关注

    关注

    23

    文章

    4612

    浏览量

    92871
  • KNN
    KNN
    +关注

    关注

    0

    文章

    22

    浏览量

    10803
  • ANN
    ANN
    +关注

    关注

    0

    文章

    22

    浏览量

    9197
收藏 人收藏

    评论

    相关推荐

    u-blox发布新型全波段GNSS天线ANN-MB2

    近日,作为提供定位和无线通信技术及服务的全球领先供应商u-blox(SIX:UBXN)发布了适用于广覆盖、多星座高精度应用的外置GNSS天线ANN-MB2。
    的头像 发表于 11-25 17:31 374次阅读

    科学家将拉曼光谱的测量速率提高100

    专门设计和制造的拉曼光谱仪的图像,其性能比任何其他系统高出100。 东京大学光子科学与技术研究所的研究人员 Takuma Nakamura、Kazuki Hashimoto 和 Takuro
    的头像 发表于 11-15 06:24 68次阅读

    【每天学点AI】KNN算法:简单有效的机器学习分类器

    过程,其实就是一个简单的分类问题,而KNN(K-NearestNeighbors)算法正是模仿这种人类决策过程的机器学习算法。|什么是KNNKNN
    的头像 发表于 10-31 14:09 320次阅读
    【每天学点AI】<b class='flag-5'>KNN</b><b class='flag-5'>算法</b>:简单有效的机器学习分类器

    《AI for Science:人工智能驱动科学创新》第6章人AI与能源科学读后感

    了电力的实时平衡和优化,有效降低了电网的运行成本和故障率。 此外,书中还讨论了人工智能在能源科学研究中的挑战和机遇。这些挑战包括数据质量、算法优化、隐私保护等方面,而机遇则体现在技术创新、产业升级
    发表于 10-14 09:27

    AI for Science:人工智能驱动科学创新》第4章-AI与生命科学读后感

    研究的深入发展。 3. 挑战与机遇并存 尽管AI在生命科学领域取得了显著的成果,但也面临着诸多挑战。例如,数据隐私、算法偏见、伦理道德等问题都需要我们认真思考和解决。同时,如何更好地将AI技术与生命
    发表于 10-14 09:21

    《AI for Science:人工智能驱动科学创新》第二章AI for Science的技术支撑学习心得

    的物理可信度,还为科学研究提供了新的视角和方法。 5. 挑战与未来展望 第二章也提到了AI for Science面临的挑战和未来展望。尽管AI技术在科学研究中取得了显著进展,但仍存在数据隐私、
    发表于 10-14 09:16

    《AI for Science:人工智能驱动科学创新》第一章人工智能驱动的科学创新学习心得

    学科之间的交叉融合,形成了一种全新的科学研究范式。AI技术打破了学科壁垒,使得物理学、化学、生物学、天文学等领域的研究者能够共享数据算法,共同解决复杂问题。这种跨学科的合作不仅拓宽了科学
    发表于 10-14 09:12

    opa380异常损坏,放大倍数衰减十到百,不可恢复,为什么?

    在使用opa380时,经常出现原先正常工作的电路,突然信号值直线下降,输出信号衰减十到百,但是变化趋势一致,不可恢复,更换opa380芯片后正常
    发表于 07-29 06:51

    机器学习算法原理详解

    机器学习作为人工智能的一个重要分支,其目标是通过让计算机自动从数据中学习并改进其性能,而无需进行明确的编程。本文将深入解读几种常见的机器学习算法原理,包括线性回归、逻辑回归、支持向量机(SVM)、决策树和K近邻(KNN
    的头像 发表于 07-02 11:25 1033次阅读

    机器学习的经典算法与应用

    关于数据机器学习就是喂入算法数据,让算法数据中寻找一种相应的关系。Iris鸢尾花数据集是一个
    的头像 发表于 06-27 08:27 1657次阅读
    机器学习的<b class='flag-5'>经典</b><b class='flag-5'>算法</b>与应用

    超小型电源电压监控器TPS380x数据

    电子发烧友网站提供《超小型电源电压监控器TPS380x数据表.pdf》资料免费下载
    发表于 03-29 10:19 0次下载
    超小型电源电压监控器TPS<b class='flag-5'>380</b>x<b class='flag-5'>数据</b>表

    电压检测芯片TPS380x-Q1数据

    电子发烧友网站提供《电压检测芯片TPS380x-Q1数据表.pdf》资料免费下载
    发表于 03-29 10:13 0次下载
    电压检测芯片TPS<b class='flag-5'>380</b>x-Q1<b class='flag-5'>数据</b>表

    Cognex 推出由 DataMan 380 读码器的灵活数据驱动型通道解决方案

    380 Modular Vision Tunnel 扩展了物流运营的能力 马萨诸塞州内蒂克2024年3月27日 /美通社/ -- 工业机器视觉领域的领导者 Cognex Corporation
    的头像 发表于 03-27 22:53 340次阅读

    18V、380nA 电压监视器TPS3847数据

    电子发烧友网站提供《18V、380nA 电压监视器TPS3847数据表.pdf》资料免费下载
    发表于 03-14 10:52 0次下载
    18V、<b class='flag-5'>380</b>nA 电压监视器TPS3847<b class='flag-5'>数据</b>表

    电焊机220和380两用的怎么接380v

    电焊机是一种工业设备,用于将金属部件连接在一起。传统的电焊机工作电压为220V,但在某些情况下,需要使用380V的电焊机。本文将详细介绍如何连接380V的电焊机。 1.确定电压 首先,需要确定您
    的头像 发表于 03-09 15:40 1.1w次阅读