faiss-7: 基础索引类型
数据准备
import faiss
import numpy as np d = 512 # 维数
# 向量集合
n_data = 2000
np.random.seed(0)
data = []
mu = 3
sigma = 0.1
for i in range(n_data):data.append(np.random.normal(mu, sigma, d))
data = np.array(data).astype('float32')# query 向量
n_query = 10
np.random.seed(12)
query = []
for i in range(n_query):query.append(np.random.normal(mu, sigma, d))
query = np.array(query).astype('float32')
精确搜索-L2距离(Exact Search for L2)
baseline
index = faiss.IndexFlatL2(d) # L2距离
# index = faiss.index_factory(d, "Flat") # 两种定义方式
index.add(data)
dis, ind = index.search(query, 10)
print(dis)
print(ind)
[[8.61838 8.782156 8.782816 8.832027 8.837635 8.8484955 8.8979788.9166355 8.919006 8.937399 ][9.033302 9.038906 9.091706 9.155842 9.164592 9.200113 9.2018859.220333 9.279479 9.312859 ][8.063819 8.211029 8.306456 8.373353 8.459253 8.459894 8.4985568.546466 8.555407 8.621424 ][8.193895 8.211957 8.34701 8.446963 8.45299 8.45486 8.4735728.504771 8.513636 8.530685 ][8.369623 8.549446 8.704066 8.736764 8.760081 8.777317 8.8313458.835485 8.858271 8.860057 ][8.299071 8.432397 8.434382 8.457373 8.539217 8.562357 8.5790338.618738 8.630859 8.6433935][8.615003 8.615164 8.72604 8.730944 8.762621 8.796932 8.7970668.797366 8.813984 8.834725 ][8.377228 8.522776 8.711159 8.724562 8.745737 8.763845 8.76868.7728 8.786858 8.828223 ][8.3429165 8.488056 8.655106 8.662771 8.701336 8.741288 8.74360758.770506 8.786265 8.8490505][8.522163 8.575702 8.684618 8.767246 8.782908 8.850494 8.8837328.903692 8.909395 8.917681 ]][[1269 1525 1723 1160 1694 48 1075 1028 544 916][1035 259 1279 1116 1398 879 289 882 1420 1927][ 327 345 1401 389 1904 1992 1612 106 981 1179][1259 112 351 804 1412 1987 1377 250 1624 133][1666 854 1135 616 94 280 30 99 1212 3][ 574 1523 366 766 1046 91 456 649 46 896][1945 944 244 655 1686 981 256 1555 1280 1969][ 879 1025 390 269 1115 1662 1831 610 11 191][ 156 154 99 31 1237 289 769 1524 56 661][ 427 182 375 1826 610 1384 1299 750 2 1430]]
精确搜索-点乘距离(Exact Search for Inner Product)
当数据库向量是标准化的,计算返回的distance就是余弦相似度
index = faiss.IndexFlatIP(d) # 点乘
index.add(data)
dis, ind = index.search(query, 10)
print(dis)
print(ind)
[[4621.75 4621.5464 4619.745 4619.381 4619.176 4618.0625 4617.1694617.057 4617.048 4616.6304][4637.3965 4637.289 4635.3677 4635.2446 4634.881 4633.6074 4633.0214632.7646 4632.5596 4632.373 ][4621.755 4621.47 4619.748 4619.562 4619.423 4618.0186 4616.9924616.962 4616.9014 4616.735 ][4623.608 4623.5596 4621.3965 4621.1577 4620.9062 4619.838 4618.97564618.913 4618.7695 4618.4775][4625.553 4625.064 4623.461 4623.1963 4622.957 4621.337 4620.73634620.717 4620.5645 4620.248 ][4628.489 4628.449 4626.4917 4626.4873 4625.6406 4624.615 4624.294623.999 4623.7524 4623.618 ][4637.746 4637.338 4635.3047 4635.126 4634.7476 4633.0137 4632.86334632.58 4632.3027 4632.233 ][4630.4717 4630.334 4628.2646 4627.9375 4627.7383 4626.8975 4625.81354625.7227 4625.445 4625.0913][4635.7725 4635.4893 4633.6904 4633.5674 4632.658 4631.4634 4631.43074631.101 4630.99 4630.3066][4625.6763 4625.558 4623.454 4623.3916 4623.324 4622.2827 4621.77834621.1147 4620.9043 4620.8545]][[1562 27 681 169 1262 942 1566 31 1207 252][ 27 1562 169 681 1262 942 1566 1392 31 252][1562 27 681 169 1262 942 1566 252 31 1392][1562 27 681 169 1262 942 252 1566 31 1207][1562 27 681 169 1262 942 1566 252 31 1513][1562 27 169 681 1262 942 252 31 1566 911][1562 27 169 681 1262 1566 942 252 31 1392][1562 27 681 169 1262 942 1566 31 252 1207][ 27 1562 169 681 1262 942 31 252 1566 1392][1562 27 1262 681 169 942 1566 31 1207 252]]
HNSW(Hierarchical Navigable Small World graph exploration)
基于图近似方法获取返回的近似结果
index = faiss.IndexHNSWFlat(d, 16)
index.add(data)
dis, ind = index.search(query, 10)
print(dis)
print(ind)
[[8.61838 8.832027 8.8484955 8.897978 8.9166355 8.919006 8.9373998.9597 8.984709 8.998905 ][9.038906 9.164592 9.200113 9.201885 9.220333 9.312859 9.3443419.34485 9.416972 9.421429 ][8.063819 8.459253 8.459894 8.498556 8.555407 8.631897 8.713688.735945 8.770473 8.792957 ][8.193895 8.211957 8.34701 8.446963 8.45486 8.473572 8.5047718.513636 8.530685 8.545483 ][8.369623 8.760081 8.831345 8.860057 8.862643 8.93695 8.9722818.996923 9.065968 9.070428 ][8.299071 8.432397 8.434382 8.539217 8.562357 8.6433935 8.69831858.753673 8.768753 8.780443 ][8.762621 8.796932 8.797066 8.813984 8.860753 8.867388 8.9118128.922768 8.928856 8.942961 ][8.377228 8.522776 8.711159 8.724562 8.7728 8.828223 8.8794698.888437 8.914921 8.924161 ][8.3429165 8.488056 8.662771 8.741288 8.7436075 8.770506 8.8572548.893715 8.933592 8.960606 ][8.522163 8.575702 8.850494 8.903692 8.917681 8.936615 8.9616668.977329 9.009894 9.031724 ]][[1269 48 1075 1028 916 239 897 1627 120 1567][ 259 1398 879 289 882 1927 13 70 1023 121][1401 1904 106 981 1623 1393 1632 539 1143 366][1259 112 351 804 1987 1377 250 1624 133 879][1666 94 1212 277 1723 581 106 472 807 884][ 574 1523 366 766 1046 91 154 911 902 685][ 944 1686 981 1391 849 280 1337 1263 91 1540][ 879 1025 390 269 1115 1831 610 11 191 1686][ 154 31 1237 289 769 1524 661 426 1008 1727][ 182 1299 1430 511 1339 1010 1173 1457 664 529]]
倒排表搜索(Inverted file with exact post-verification)
quantizer = faiss.IndexFlatL2(d) # 量化器
nlist = 50
index = faiss.IndexIVFFlat(quantizer, d, nlist, faiss.METRIC_L2)
index.train(data)
index.add(data)
index.nprobe = 30 # 选择nprobe个维诺空间进行索引
dis, ind = index.search(query, 10)
print(dis)
print(ind)
[[8.61838 8.782156 8.782816 8.832027 8.837635 8.8484955 8.8979788.9166355 8.919006 8.937399 ][9.033302 9.038906 9.091706 9.164592 9.200113 9.201885 9.2203339.279479 9.312859 9.344341 ][8.063819 8.211029 8.306456 8.373353 8.459253 8.459894 8.4985568.546466 8.555407 8.621424 ][8.193895 8.211957 8.34701 8.446963 8.45299 8.45486 8.4735728.504771 8.513636 8.530685 ][8.369623 8.549446 8.704066 8.736764 8.760081 8.777317 8.8313458.835485 8.858271 8.860057 ][8.299071 8.432397 8.434382 8.457373 8.539217 8.562357 8.5790338.618738 8.630859 8.6983185][8.615003 8.615164 8.72604 8.730944 8.762621 8.796932 8.7970668.797366 8.813984 8.834725 ][8.377228 8.522776 8.711159 8.724562 8.745737 8.763845 8.76868.7728 8.786858 8.828223 ][8.3429165 8.488056 8.655106 8.662771 8.701336 8.741288 8.74360758.770506 8.786265 8.8490505][8.522163 8.575702 8.684618 8.767246 8.782908 8.850494 8.8837328.903692 8.909395 8.917681 ]][[1269 1525 1723 1160 1694 48 1075 1028 544 916][1035 259 1279 1398 879 289 882 1420 1927 13][ 327 345 1401 389 1904 1992 1612 106 981 1179][1259 112 351 804 1412 1987 1377 250 1624 133][1666 854 1135 616 94 280 30 99 1212 3][ 574 1523 366 766 1046 91 456 649 46 154][1945 944 244 655 1686 981 256 1555 1280 1969][ 879 1025 390 269 1115 1662 1831 610 11 191][ 156 154 99 31 1237 289 769 1524 56 661][ 427 182 375 1826 610 1384 1299 750 2 1430]]
LSH(Locality-Sensitive Hashing (binary flat index))
nbits = 2 * d
index = faiss.IndexLSH(d, nbits)
index.train(data)
index.add(data)
dis, ind = index.search(query, 10)
print(dis)
print(ind)
[[ 8. 10. 10. 10. 10. 10. 10. 11. 11. 11.][ 7. 8. 9. 9. 9. 10. 10. 10. 10. 10.][ 7. 8. 8. 9. 9. 9. 9. 9. 9. 9.][ 9. 9. 10. 11. 12. 12. 12. 12. 12. 12.][ 6. 6. 6. 7. 7. 8. 8. 8. 8. 8.][ 8. 8. 8. 9. 9. 9. 9. 9. 10. 10.][ 6. 7. 8. 8. 9. 9. 9. 9. 9. 9.][ 9. 9. 9. 9. 9. 9. 9. 9. 9. 10.][ 7. 8. 8. 8. 8. 8. 8. 9. 9. 9.][ 9. 9. 9. 10. 10. 10. 10. 10. 10. 10.]][[1424 345 1544 760 1589 1043 668 492 148 666][1974 1436 1476 51 711 696 28 934 541 1125][1667 1356 1149 512 1592 1544 1677 309 1021 1018][ 708 107 606 243 18 612 598 615 269 250][1455 541 1142 843 1140 888 165 961 797 1003][1735 193 953 1071 1518 1109 449 263 1329 1216][1129 1231 1731 123 860 907 381 993 336 1071][1622 336 1970 845 70 1921 1973 980 331 42][1335 713 1589 395 263 1206 346 698 913 678][1395 279 1305 427 1707 1574 1710 226 1205 1160]]
SQ量化(Scalar quantizer (SQ) in flat mode)
index = faiss.IndexScalarQuantizer(d, 4)
index.train(data)
index.add(data)
dis, ind = index.search(query, 10)
print(dis)
print(ind)
[[8.623228 8.777794 8.785317 8.828827 8.835491 8.845296 8.8968968.914822 8.922382 8.934984 ][9.028503 9.037548 9.099254 9.152615 9.16542 9.196389 9.2004979.224977 9.274048 9.305386 ][8.064029 8.213011 8.310526 8.376434 8.4578285 8.462004 8.5009698.550645 8.556992 8.624526 ][8.196653 8.210537 8.3464365 8.444774 8.452023 8.454119 8.4745258.4966135 8.510042 8.525611 ][8.370451 8.547961 8.704324 8.733618 8.763927 8.776734 8.829518.835646 8.857151 8.859047 ][8.29591 8.432422 8.435947 8.454732 8.542397 8.565366 8.5796858.621871 8.632036 8.64478 ][8.609016 8.612934 8.726631 8.734137 8.758858 8.797329 8.7979718.798654 8.815296 8.838221 ][8.37895 8.521536 8.710902 8.726156 8.748387 8.75966 8.7682178.769184 8.792372 8.834644 ][8.340463 8.489507 8.659348 8.664953 8.702758 8.741514 8.7419418.768995 8.781276 8.852154 ][8.520282 8.5749855 8.68346 8.769207 8.782043 8.851276 8.8811148.906744 8.907756 8.924014 ]][[1269 1723 1525 1160 1694 48 1075 544 1028 916][1035 259 1279 1116 1398 289 879 882 1420 1927][ 327 345 1401 389 1992 1904 1612 106 981 1179][1259 112 351 804 1987 1412 1377 250 1624 133][1666 854 1135 616 94 280 30 99 3 1212][ 574 1523 366 766 1046 91 456 649 46 896][ 944 1945 244 655 1686 256 981 1555 1280 1969][ 879 1025 390 269 1115 1662 1831 610 11 191][ 156 154 99 31 1237 289 769 1524 56 661][ 427 182 375 1826 610 1384 1299 750 2 1430]]
PQ量化(Product quantizer (PQ) in flat mode)
M = 8 # 必须是d的因数
nbits = 6 # 只能是8,12,16
index = faiss.IndexPQ(d, M, nbits)
index.train(data)
index.add(data)
dis, ind = index.search(query, 10)
print(dis)
print(ind)
[[5.3148193 5.33667 5.390381 5.3969727 5.4020996 5.402466 5.40881355.420532 5.4210205 5.4370117][5.694214 5.71875 5.7408447 5.7418213 5.743042 5.7543945 5.76110845.764282 5.786255 5.791748 ][4.880615 4.9449463 4.9451904 5.0146484 5.022583 5.0406494 5.04443365.0650635 5.06604 5.0666504][4.8305664 4.852661 4.8569336 4.87146 4.8901367 4.8969727 4.90039064.9073486 4.9093018 4.911743 ][5.2233887 5.3170166 5.3239746 5.338623 5.347534 5.356201 5.35998545.362915 5.387085 5.40271 ][5.024658 5.0458984 5.0463867 5.069214 5.1254883 5.1533203 5.15576175.17395 5.1887207 5.188843 ][5.070923 5.1273193 5.144409 5.1882324 5.1896973 5.194702 5.208135.223633 5.223633 5.242798 ][5.173218 5.2506104 5.26355 5.3077393 5.3099365 5.3240967 5.3245855.3448486 5.3449707 5.3479004][5.1730957 5.246826 5.2974854 5.319092 5.3239746 5.3275146 5.34094245.3464355 5.352051 5.364624 ][5.204468 5.27124 5.272217 5.324463 5.335449 5.348755 5.35314945.355713 5.359619 5.3670654]][[1000 1775 1651 702 1963 1063 249 1995 689 1075][ 243 532 1923 52 304 1212 449 1264 1092 622][1904 981 735 492 458 1810 1945 839 875 616][1307 148 250 1773 576 187 864 394 1920 1550][1135 1429 151 773 250 502 1945 1408 694 1849][1427 1463 816 1314 1096 896 8 1366 1673 939][ 244 854 85 560 1154 1473 951 1626 218 885][ 278 1176 787 70 235 326 190 1843 892 1756][ 81 855 416 1545 145 1811 172 383 1856 90][ 902 1238 725 1141 1255 593 1507 596 1400 1434]]
倒排表乘积量化(IVFADC (coarse quantizer+PQ on residuals))
M = 8
nbits = 4
nlist = 50
quantizer = faiss.IndexFlatL2(d)
index = faiss.IndexIVFPQ(quantizer, d, nlist, M, nbits)
index.train(data)
index.add(data)
dis, ind = index.search(query, 10)
print(dis)
print(ind)
[[5.1813607 5.213015 5.227062 5.240297 5.3074746 5.3143606 5.32094535.323071 5.3241897 5.3336196][5.531564 5.5329485 5.562758 5.563456 5.5912466 5.6556826 5.6729315.68467 5.6997647 5.702039 ][4.8162827 4.822724 4.8304024 4.8753777 4.885644 4.8879986 4.88815454.893022 4.8931584 4.900308 ][4.816623 4.83104 4.8495483 4.8536286 4.876833 4.877784 4.8800994.884579 4.8872194 4.891768 ][5.0868177 5.118717 5.1225142 5.1229815 5.1336117 5.1365952 5.14251855.1445856 5.1706796 5.1717625][4.896156 4.923249 4.941252 4.9426517 4.951362 4.9712415 4.97380264.9810586 4.9901094 4.991113 ][4.98639 4.9903703 4.9991083 5.0107374 5.011694 5.0129166 5.0165045.020243 5.0209174 5.024062 ][5.175429 5.175681 5.1776314 5.189157 5.1944485 5.222612 5.22329765.226807 5.236521 5.2451673][5.044052 5.080878 5.1016216 5.109776 5.1117053 5.124481 5.12564665.1480865 5.151196 5.1520753][5.129094 5.1587934 5.1708508 5.171063 5.18175 5.182567 5.19424345.1995926 5.201419 5.2037187]][[1962 1880 311 1897 666 201 647 283 1588 171][ 569 148 162 39 753 1032 983 934 560 1715][ 851 380 1322 1803 1678 1486 1504 1847 1206 306][ 960 1741 636 510 1568 880 866 1134 615 381][1799 1166 572 1631 1244 343 1212 1859 756 1630][ 816 1753 749 1621 444 1399 658 771 369 913][1902 1238 913 1546 654 969 1187 350 979 1251][ 464 839 1705 772 77 490 1976 998 968 57][1445 505 426 300 1220 122 806 755 100 1343][1432 1263 1198 1537 1816 263 1 430 598 260]]
cell-probe方法
为了加速索引过程,经常采用划分子类空间(如k-means)的方法,虽然这样无法保证最后返回的结果是完全正确的。先划分子类空间,再在部分子空间中搜索的方法,就是cell-probe方法。
具体流程为:
- 数据集空间被划分为
n
个部分,在k-means
中,表现为n
个类; - 每个类中的向量保存在一个倒排表中,共有
n
个倒排表; - 查询时,选中
nprobe
个倒排表; - 将这几个倒排表中的向量与查询向量作对比。
在这种方法中,只需要排查数据库中的一部分向量,大约只有nprobe/n
的数据,因为每个倒排表的长度并不一致(每个类中的向量个数不一定相等)
cell-probe粗量化
在一些索引类型中,需要一个Flat index
作为粗量化器,如IndexIVFFlat
,在训练的时候会将类中心保存在Flat index
中,在add
和search
阶段,会首先判定将其落入哪个类空间。在search
阶段,nprobe
参数需要调整以权衡检索精度与检索速度。
实验表明,对高维数据,需要维持比较高的nprobe
数值才能保证精度。
与LSH的优劣
LSH也是一种cell-probe方法,与其相比,LSH有以下几点不足:
- LSH需要大量的哈希方程,会带来额外的内存开销;
- 哈希函数不适合输入数据;
参考
- https://yongyuan.name/blog/scalar-quantization.html
- https://github.com/liqima/faiss_note
faiss-7: 基础索引类型相关推荐
- 【Faiss】基础索引类型(六)
基础索引类型 数据准备 import numpy as np d = 512 #维数 n_data = 2000 np.random.seed(0) data = [] mu = 3 sigma = ...
- Faiss(二)基础索引
参考链接: Faiss入门及应用经验记录 - 知乎 Faiss indexes · facebookresearch/faiss Wiki · GitHub Faiss提供了多种索引,本篇介绍一些基础 ...
- mongodb安装_MongoDB索引策略和索引类型
mongodb安装 1. MongoDB索引策略和索引类型–简介 MongoDB是一个开放源代码,面向文档的跨平台数据库,它使用C ++开发,并且是最流行和使用最广泛的NoSQL类型数据库之一. 它可 ...
- typescript索引类型_TypeScript的索引类型与映射类型,以及常用工具泛型的实现
相信现在很多小伙伴都在使用 TypeScript(以下简称 TS),在 TS 中除了一些常用的基本类型外,还有一些稍微高级一点的类型,这些就是我本次文章要讲的内容:索引类型与映射类型,希望小伙伴们看过 ...
- Mysql-索引的基础和类型
一. 索引的基础 索引类似于书籍的目录,要想找到一本书的某个特定主题,需要先查找书的目录,定位对应的页码. 存储引擎使用类似的方式进行数据查询,先去索引当中找到对应的值,然后根据匹配的索引找到对应的 ...
- MongoDB索引策略和索引类型
1. MongoDB索引策略和索引类型–简介 MongoDB是一个开放源代码,面向文档的跨平台数据库,它使用C ++开发,并且是最流行和使用最广泛的NoSQL类型数据库之一. 它可在具有键-值对的类J ...
- postgreSQL源码分析——索引的建立与使用——各种索引类型的管理和操作(2)
2021SC@SDUSC 目录 上层操作函数 index_open index_beginscan() index_create() indexcmd.c 下层接口函数 IndexScanDescDa ...
- [No0000B5]C# 类型基础 值类型和引用类型 及其 对象判等 深入研究1
引言 本文之初的目的是讲述设计模式中的 Prototype(原型)模式,但是如果想较清楚地弄明白这个模式,需要了解对象克隆(Object Clone),Clone其实也就是对象复制.复制又分为了浅度复 ...
- [CLR via C#]4. 类型基础及类型、对象、栈和堆运行时的相互联系
原文:[CLR via C#]4. 类型基础及类型.对象.栈和堆运行时的相互联系 CLR要求所有类型最终都要从System.Object派生.也就是所,下面的两个定义是完全相同的, //隐式派生自Sy ...
最新文章
- 使用Python PIL库实现简单验证码的去噪处理
- 【译】JavaScript 工厂函数 vs 构造函数
- 如何将模糊的图片变得清晰
- js null加法的处理
- python计算样本方差_Python计算库numpy进行方差/标准方差/样本标准方差/协方差的计算...
- 七乐彩中奖规则表_【开奖】双色球第2020094期开奖结果出炉!你中奖了吗?
- 多行文本溢出显示省略号(…) text-overflow: ellipsis
- 【转】C++从零实现神经网络
- 调用http_【学习充电】直观讲解一下 RPC 调用和 HTTP 调用的区别!
- 计算机在生活中应用视频,计算机在腐蚀防护中的应用教学视频
- 浏览器cookie那些事儿
- iOS上架app store下载步骤
- Java面试——多线程面试题
- Securing DevOps 免积分下载
- python图像的手绘效果代码_Python项目1:实现将图片转化为手绘效果
- 百度地图调用笔记:javascript版本2
- Arduino与Proteus仿真实例-74HC573锁存器驱动仿真
- LOMO+XQDA(2015CVPR)
- win10辅助准星教程
- 部署KVM 虚拟化平台
热门文章
- 魅族android面试题,魅族前端面试题 - 尝试做
- 728-MySQL索引篇
- 超级简单的EOS代币转账教程(EETH)
- 三星s4开机显示无服务器,三星s4稳压电源充电,造成手机无法开机故障维修一例...
- 数字营销分析理论之归因模型指南
- 解决iPhone连接Mac反复断开重连
- ISP IAP(转自EETOP)
- 李礼辉:警惕全球性数字货币,超主权或将导向金融颠覆(附全文)
- Xcode 安装Command Line Tools
- php输出json到表格,Vue如何导出json数据到Excel电子表格方法