使用Solr 9.4的密集矢量搜索-knn搜索返回的点积和余弦值不正确

nx7onnlm  于 2024-01-07  发布在  Solr
关注(0)|答案(1)|浏览(301)

我正在使用Solr 9.4进行密集矢量搜索,但是knn搜索返回了奇怪的点积值。
下面是一个基本的例子:
1.将向量[0.57735027,0.57735027,0.57735027]存储在集合中
1.使用查询向量[0.26726124, 0.53452248, 0.80178373]执行knn查询
点积应为0.92582,但返回的分数为0.96291006
最奇怪的是,当我使用一个流表达式dotProduct(array(0.57735027,0.57735027,0.57735027),array(0.26726124,0.53452248,0.80178373))时,Solr返回正确的值:0.92582

任何想法为什么有这样的差异,我如何才能获得正确的点产品从knn搜索?

复制步骤

启动本地Solr

下面是我的docker-compose.yaml文件:

  1. version: '3'
  2. services:
  3. solr:
  4. image: solr:9.4
  5. ports:
  6. - "8983:8983"
  7. volumes:
  8. - 'solr_data:/var/solr'
  9. command:
  10. - solr-precreate
  11. - documents
  12. volumes:
  13. solr_data:
  14. driver: local

字符串

向集合中添加vector

我添加一个向量[0.57735026, 0.57735026, 0.57735026](单位向量)。

  1. # Create a 3D vector type
  2. curl -X POST \
  3. 'http://localhost:8983/api/cores/documents/schema' \
  4. --header 'Content-Type: application/json' \
  5. --data-raw '{
  6. "add-field-type": {
  7. "name": "3D-vector",
  8. "class": "solr.DenseVectorField",
  9. "vectorDimension": "3",
  10. "vectorEncoding": "FLOAT32",
  11. "similarityFunction": "dot_product"
  12. }
  13. }'
  14. # Add a field "vector" in the collection
  15. curl -X POST \
  16. 'http://localhost:8983/api/cores/documents/schema' \
  17. --header 'Content-Type: application/json' \
  18. --data-raw '{
  19. "add-field": [
  20. {
  21. "name": "vector",
  22. "type": "3D-vector"
  23. }
  24. ]
  25. }'
  26. # Add a single vector (normalized) into the collection "documents"
  27. curl -X POST \
  28. 'http://localhost:8983/api/cores/documents/update?commit=true' \
  29. --header 'Content-Type: application/json' \
  30. --data-raw '[
  31. {
  32. "vector": [
  33. 0.57735027,
  34. 0.57735027,
  35. 0.57735027
  36. ]
  37. }
  38. ]'

执行knn搜索

现在,我使用向量查询[0.26726124, 0.53452248, 0.80178373]执行knn搜索
对应的点积应该是0.92582(与余弦相似性相同,因为我使用了归一化向量)。
我添加了一个计算字段,它使用函数query vectorSimilarity来仔细检查点积的返回值:
回应:

  1. {
  2. "responseHeader": {
  3. "status": 0,
  4. "QTime": 1,
  5. "params": {
  6. "json": "{\n \"fields\": [\n \"vector\",\n \"score\",\n \"vectorSimilarity(FLOAT32, DOT_PRODUCT, vector, [0.26726124, 0.53452248, 0.80178373])\"\n ],\n \"query\": \"{!knn f=vector topK=10}[0.26726124, 0.53452248, 0.80178373]\"\n}"
  7. }
  8. },
  9. "response": {
  10. "numFound": 1,
  11. "start": 0,
  12. "maxScore": 0.96291006,
  13. "numFoundExact": true,
  14. "docs": [
  15. {
  16. "vector": [
  17. 0.57735026,
  18. 0.57735026,
  19. 0.57735026
  20. ],
  21. "score": 0.96291006,
  22. "vectorSimilarity(FLOAT32, DOT_PRODUCT, vector, [0.26726124, 0.53452248, 0.80178373])": 0.96291006
  23. }
  24. ]
  25. }
  26. }


正如我们所看到的,点积的返回值是0.96291006,这与0.92582有很大的不同。
最奇怪的是,如果我使用带有表达式dotProduct(array(0.57735027,0.57735027,0.57735027),array(0.26726124,0.53452248,0.80178373))的流式表达式端点,Solr会计算正确的点积:

  1. curl -X GET \
  2. 'http://localhost:8983/solr/documents/stream?expr=dotProduct(array(0.57735027%2C0.57735027%2C0.57735027)%2Carray(0.26726124%2C0.53452248%2C0.80178373))' \
  3. --header 'Content-Type: application/json


回应:

  1. {
  2. "result-set": {
  3. "docs": [
  4. {
  5. "return-value": 0.9258201002207116
  6. },
  7. {
  8. "EOF": true,
  9. "RESPONSE_TIME": 15
  10. }
  11. ]
  12. }
  13. }

9vw9lbht

9vw9lbht1#

我终于明白为什么分数似乎不正确感谢this issue
看起来Solr正在计算归一化余弦相似度:(1 + cosine_sim) / 2,这解释了为什么我计算的值和knn搜索返回的值之间存在差距。
为了得到余弦相似度,可以应用公式:2 * normalized_cosine_sim - 1
对于我在问题中给出的答案:2 * 0.96291006 - 1给出0.92582

相关问题