elasticsearch中的向量检索,语义检索,RRF,kNN,ANN,HNSW

kNN 算法 (k-Nearest Neighbor)

KNN可以说是最简单的分类算法之一,同时,它也是最常用的分类算法之一。

kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 kNN方法在类别决策时,只与极少量的相邻样本有关。由于kNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,kNN方法较其他方法更为适合。

KNN的原理就是当预测一个新的值x的类别时候,根据它距离最近的K个点是什么类别来判断x属于哪个类别。

在这里插入图片描述

图中绿色的点就是我们要预测的那个点,假设K=3。那么KNN算法就会找到与它距离最近的三个点(这里用圆圈把它圈起来了),看看哪种类别多一些,比如这个例子中是蓝色三角形多一些,新来的绿色点就归类到蓝三角了。

在这里插入图片描述

但是,当K=5的时候,判定就变成不一样了。这次变成红圆多一些,所以新来的绿点被归类成红圆。从这个例子中,我们就能看得出K的取值是很重要的。

另外一个就是距离计算,我们就使用最常用的欧式距离。所以,kNN算法需要计算x与空间中所有点的距离,然后排序,取得距离最小的k个,然后再看这k个点中哪种类别最多。

回到ES检索中来,使用kNN算法得到了k条文档,其意思就是说这k条文档就能概括你的问题query。

k的取值需要经过实验来获得,随着k值的增加,其错误率的曲线大致如下。

在这里插入图片描述

KNN算法优点

  1. 简单易用,相比其他算法,KNN算是比较简洁明了的算法。即使没有很高的数学基础也能搞清楚它的原理。
  2. 模型训练时间快,上面说到KNN算法是惰性的,这里也就不再过多讲述。
  3. 预测效果好。
  4. 对异常值不敏感

KNN算法缺点

  1. 对内存要求较高,因为该算法存储了所有训练数据
  2. 预测阶段可能很慢
  3. 对不相关的功能和数据规模敏感

至于什么时候应该选择使用KNN算法,sklearn的这张图给了我们一个答案。

在这里插入图片描述

简单得说,当需要使用分类算法,且数据比较大的时候就可以尝试使用KNN算法进行分类了。

ES中的检索器retriever

检索器retriever概述:https://www.elastic.co/guide/en/elasticsearch/reference/current/retrievers-overview.html

The following retrievers are available:

  • Standard Retriever. Returns top documents from a traditional query. Mimics a traditional query but in the context of a retriever framework. This ensures backward compatibility as existing _search requests remain supported. That way you can transition to the new abstraction at your own pace without mixing syntaxes.

  • kNN Retriever. Returns top documents from a knn search, in the context of a retriever framework.

  • RRF Retriever. Combines and ranks multiple first-stage retrievers using the reciprocal rank fusion (RRF) algorithm. Allows you to combine multiple result sets with different relevance indicators into a single result set. An RRF retriever is a compound retriever, where its filter element is propagated to its sub retrievers.

    Sub retrievers may not use elements that are restricted by having a compound retriever as part of the retriever tree. See the RRF documentation for detailed examples and information on how to use the RRF retriever.

  • Text Similarity Re-ranker Retriever. Used for semantic reranking. Requires first creating a rerank task using the Elasticsearch Inference API.

检索器retriever具体使用:https://www.elastic.co/guide/en/elasticsearch/reference/current/retriever.html

ES比单纯的向量数据库的优势在于,它支持混合检索,即一个搜索语句即能包含向量字段,也能包含常规的字段。

ES中的kNN Search

在 ES8.4及之前,kNN search api 是 _knn_search,文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/knn-search-api.html。

GET my-index/_knn_search
{
   
  "knn": {
   
    "field": "image_vector",
    "query_vector": [0.3, 0.1, 1.2],
    "k": 10,
    "num_candidates": 100
  },
  "_source": ["name", "file_type"]
}

很明显这个接口只能服务与向量检索,但是现实中更多的场景式混合检索,即一条语句同时包含向量字段也包含常规字段,所以从 8.5 版本之后此 api 被废弃,改成了混合搜索 api,更加强调检索器retriever,所以现在进行kNN搜索的api为_search,详细介绍:https://www.elastic.co/guide/en/elasticsearch/reference/current/knn-search.html

POST image-index/_search
{
   
  "knn": {
   
    "field": "image-vector",
    "query_vector": [-5, 9, -12],
    "k": 10,
    "num_candidates": 100
  },
  "fields": [ "title", "file-type" ]
}

混合搜索的例子

POST image-index/_search
{
   
  "query": {
   
    "match": 
在MATLAB中,你可以使用`cvpartition`函数来进行数据划分,然后使用`knnsearch`和`fitnet`函数分别进行KNN和神经网络(ANN)的训练。下面是一个简单的示例代码,假设你的数据存储在变量`data1`中: ```Matlab % 定义数据和标签 X = data1'; % 转置处理,因为通常输入到模型的是列向量 y = ...; % 假设y是你想要预测的目标值 % 划分数据集为训练集和验证集 c = cvpartition(size(X,1), 'HoldOut', 0.2); % 80%训练,20%验证 idxTrain = training(c); idxValid = test(c); % KNN模型 trainData = X(idxTrain,:); trainLabels = y(idxTrain,:); testData = X(idxValid,:); testLabels = y(idxValid,:); knnModel = knnsearch(trainData, testData'); % 训练KNN模型 predKNN = predict(knnModel, [X(end-29:end,:)]); % 预测后30步 % ANN模型 annModel = fitnet(10); % 假设我们用10层的神经网络 annModel = train(annModel, trainData, trainLabels); % 训练ANN predANN = net.predict(testData); % 预测验证集 predANN = net.predict([X(end-29:end,:)]); % 后30步预测 % 绘制预测结果 figure; subplot(2,1,1) plot(y, 'b', 'LineWidth', 2); hold on; plot(predKNN, 'r--', 'LineWidth', 1.5, 'DisplayName', 'KNN'); plot(predANN, 'g:', 'LineWidth', 1.5, 'DisplayName', 'ANN'); title('Predicted vs Actual Values'); legend; subplot(2,1,2) plot(range(length(y)), predKNN(end:-1:end-30)', 'r--', 'LineWidth', 1.5); plot(range(length(y)), predANN(end:-1:end-30)', 'g:', 'LineWidth', 1.5); title('Prediction for Next 30 Steps'); xlabel('Time (steps)'); ``` 请注意,你需要将上述代码中的`y`替换为你实际的标签数据,并根据需要调整神经网络的结构(例如层数、节点数)。此外,如果数据集较大,可能会更倾向于使用交叉验证而非简单的 HoldOut 分割。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值