Skip to content

Latest commit

 

History

History
348 lines (241 loc) · 17.2 KB

20230330_01.md

File metadata and controls

348 lines (241 loc) · 17.2 KB

ChatGPT背后的数据库技术体验 - 向量近似搜索之 PostgreSQL+pase(hnsw,ivfflat,ivfpq)

作者

digoal

日期

2023-03-30

标签

PostgreSQL , PolarDB , 向量 , 相似 , ann , knn , lance , pase , pgvector , hnsw , ivfflat , ivfpq


背景

现实世界存在大量非结构化数据, 例如文本、语音、图片、视频、行为、喜好. 在现实场景中, 非结构化数据的搜索基本都是相似|近似|模糊搜索. 又比如在工作中, 岗位也都有岗位的职责范畴, 但是难免就有三不管地带、或者大家都想管的内卷地带. 这些场景都不是用精确查询能解决的, 必须用到相似|近似|模糊搜索.

那怎么实现相似|近似|模糊搜索呢? 首先要将非结构化数据变成特征向量. 下面是chatGPT的回答:

1、什么是特征向量?

特征向量(Feature Vector)是指在机器学习或模式识别中用来描述一个对象或事件的向量。它是由一组特征组成的向量,每个特征都是用来描述一个对象或事件的某个属性的数值。例如,在图像识别中,特征向量可以描述一张图片的颜色、纹理、形状等特征。

特征向量是机器学习算法的输入数据,通过学习特征向量中的规律,算法可以识别和分类不同的对象或事件。通常,特征向量需要经过处理和筛选,以保留最能表示对象或事件的特征。

特征向量可以用数学表示为一个向量,例如,对于一个含有n个特征的对象,可以用一个n维向量表示,每个维度对应一个特征的值。在机器学习中,特征向量的构建和选择是非常重要的,因为好的特征向量可以很大程度上影响机器学习算法的性能。

2、为什么特征向量适合近似搜索?

特征向量适合近似搜索的原因主要有以下几点:

  • 降维:特征向量可以通过降维来减少特征维度,从而减少计算量和存储空间,同时也可以降低噪声和冗余信息的影响。
  • 相似度度量:特征向量可以通过相似度度量来度量两个向量之间的相似度,从而进行近似搜索。常用的相似度度量包括欧几里得距离、余弦相似度等。
  • 高效索引:特征向量可以通过高效索引算法建立索引结构,从而快速地找到与目标向量相似的向量。例如,k-d树、LSH等。
  • 可解释性:特征向量可以用人类可理解的方式描述对象或事件的特征,从而可以帮助人类理解和解释算法的结果。

综上所述,特征向量在近似搜索中具有较好的效果和优势,因此被广泛应用于图像检索、文本分类、推荐系统等领域。

3、如何将非结构化数据变成特征向量? 有什么开源软件可以支持这个功能? 请列举将文本、语音、图片、视频转换为特征向量的例子.

如何将非结构化数据变成特征向量:

  • 文本数据:对于文本数据,可以使用词袋模型、TF-IDF、Word2Vec等方法将文本转换为特征向量。
  • 语音数据:对于语音数据,可以使用Mel-Frequency Cepstral Coefficients(MFCC)、Linear Predictive Coding(LPC)等方法将语音转换为特征向量。
  • 图片数据:对于图片数据,可以使用SIFT、HOG、SURF、CNN等方法将图片转换为特征向量。
  • 视频数据:对于视频数据,可以使用I3D、C3D等方法将视频转换为特征向量。

开源软件:

  • 对于文本数据,可以使用Python中的Scikit-learn、Gensim、NLTK等库。
  • 对于语音数据,可以使用Python中的Librosa、PyAudioAnalysis等库。
  • 对于图片数据,可以使用Python中的OpenCV、Scikit-image、Keras等库。
  • 对于视频数据,可以使用Python中的OpenCV、PyAV、TensorFlow等库。

例子:

  • 文本数据:使用Gensim将文本转换为Word2Vec特征向量。
  • 语音数据:使用Librosa将语音数据转换为MFCC特征向量。
  • 图片数据:使用OpenCV将图片数据转换为SIFT特征向量。
  • 视频数据:使用I3D将视频数据转换为特征向量。

向量数据库实例

向量数据库特别多, 本文以postgresql+pase向量索引为例.

pase是阿里云开源的向量索引插件, 支持hnsw, ivfflat算法. 这两种算法的详细介绍请参考:

《PostgreSQL 阿里云rds pg发布高维向量索引,支持图像识别、人脸识别 - pase 插件》

下面介绍一下pase插件的部署和测试:

1、使用这个环境进行测试,
《记录下 在 debian 宿主机中部署和使用 docker (常用docker命令、debian容器常用配置; debian容器部署duckdb和PostgreSQL例子)》

2、启动容器, 安装pg 11

docker exec -it -u root --privileged -w /root debian /bin/bash  
su - postgres  
curl https://ftp.postgresql.org/pub/source/v11.19/postgresql-11.19.tar.bz2 -o ./postgresql-11.19.tar.bz2  
tar -jxvf postgresql-11.19.tar.bz2  
cd postgresql-11.19  
  
env CC=clang CXX=clang++  ./configure --prefix=/home/postgres/pg11.19 --with-icu    
make world -j 8      
make install-world    
  
vi ~/.bashrc  
#  add by digoal      
alias rm='rm -i'      
alias cp='cp -i'      
alias ll='ls -larth'      
alias mv='mv -i'  
export PATH=/home/postgres/pg11.19/bin:$PATH      
export PGDATA=/home/postgres/pgdata11.19      
export PGUSER=postgres      
export PGHOST=$PGDATA      
export PGPORT=1922      
export PGDATABASE=postgres      
export LC_ALL=en_US.UTF-8  
  
. ~/.bashrc  

3、初始化pg 11实例

initdb -D $PGDATA -U postgres -E UTF8 --lc-collate=C --lc-ctype=en_US.UTF-8    
  
vi $PGDATA/postgresql.auto.conf    
listen_addresses = '0.0.0.0'		  
port = 1922				  
max_connections = 100			  
unix_socket_directories = '/tmp, .'	  
shared_buffers = 128MB			  
dynamic_shared_memory_type = posix	  
max_wal_size = 1GB  
min_wal_size = 80MB  
log_destination = 'csvlog'		  
logging_collector = on		  
log_directory = 'log'			  
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'	  
log_file_mode = 0600			  
log_truncate_on_rotation = on		  
log_rotation_age = 1d			  
log_rotation_size = 10MB		  
log_timezone = 'Etc/UTC'  
datestyle = 'iso, mdy'  
timezone = 'Etc/UTC'  
lc_messages = 'en_US.UTF-8'			  
lc_monetary = 'en_US.UTF-8'			  
lc_numeric = 'en_US.UTF-8'			  
lc_time = 'en_US.UTF-8'				  
default_text_search_config = 'pg_catalog.english'  
  
pg_ctl start  

4、下载部署pase 向量索引插件

cd ~   
git clone --depth 1 https://github.com/B-sudo/VecDB-Exp  
  
cd VecDB-Exp/postgresql-11.0/contrib/pase  
USE_PGXS=1 make   
USE_PGXS=1 make install  

5、使用pase插件例子

postgres@9b780f5ea2e8:~/VecDB-Exp/postgresql-11.0/contrib/pase$ psql  
psql (11.19)  
Type "help" for help.  
  
postgres=# create extension pase ;  
CREATE EXTENSION  
  
postgres=# \dx  
                 List of installed extensions  
  Name   | Version |   Schema   |         Description            
---------+---------+------------+------------------------------  
 pase    | 0.0.1   | public     | ant ai similarity search  
 plpgsql | 1.0     | pg_catalog | PL/pgSQL procedural language  
(2 rows)  
  
CREATE TABLE vectors_ivfflat_test ( id serial, vector float4[]);  
  
INSERT INTO vectors_ivfflat_test SELECT id, ARRAY[id  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1,1,1,1,1,1  
       ,1,1,1,1,1  
       ]::float4[] FROM generate_series(1, 50000) id;  
  
CREATE INDEX v_ivfflat_idx ON vectors_ivfflat_test  
       USING  
         pase_ivfflat(vector)  
  WITH  
    (clustering_type = 1, distance_type = 0, dimension = 256, clustering_params = "10,100");  
  
  
  
NOTICE:  vector dimension is huge, parameter (clustering_sample_ratio) should be set to ensure the clustering count lower than 307200  
NOTICE:  parse clustering parameters succeed, clustering_sample_ratio[10], k[100]  
NOTICE:  begin inner kmeans clustering  
NOTICE:  begin, ivfflat index building  
NOTICE:  ivfflat index build done, build tuple number[50000], totalTimeCost[1.402648s], centroidBuildTimeCost[0.722759s], indexBuildTimeCost[0.679889s]  
CREATE INDEX  
  
  
  
  
  
  
SELECT vector <#> '31111,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1'::pase as distance  
    FROM vectors_ivfflat_test  
    ORDER BY  
    vector <#> '31111,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1'::pase  
     ASC LIMIT 10;  
  
  
  
 Limit  (cost=0.00..11.68 rows=10 width=4)  
   Output: ((vector <#> '31111,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1  
,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1  
,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1::'::pase))  
   ->  Index Scan using v_ivfflat_idx on public.vectors_ivfflat_test  (cost=0.00..58392.00 rows=50000 width=4)  
         Output: (vector <#> '31111,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1::'::pase)  
         Order By: (vectors_ivfflat_test.vector <#> '31111,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1  
,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1  
,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1::'::pase)  
(5 rows)  
  
  
 distance   
----------  
        0  
        1  
        1  
        4  
        4  
        9  
        9  
       16  
       16  
       25  
(10 rows)  

更多pase使用信息请参考: https://github.com/B-sudo/VecDB-Exp

例子参考: https://github.com/B-sudo/VecDB-Exp/blob/master/postgresql-11.0/contrib/pase/sql/pase.sql

包括算法的选择, 算法参数的调整等. 例如图层级别、采样比例、桶的个数、搜索时选择最近的几个桶等等.

Code of PASE is in the directory postgresql-11.0/contrib/pase.

  • ivfflat: PASE index IVF_FLAT implementation
  • ivfpq: PASE index IVF_PQ implementation
  • hnsw: PASE index HNSW implementation
  • sql: Sample SQL file for PASE
  • type: Data types used in PASE
  • utils: Util functions used in PASE

We implemented index IVF_PQ in PASE and the code is in postgresql-11.0/contrib/pase/ivfpq.

参考

https://zhuanlan.zhihu.com/p/415320221

https://www.showmeai.tech/article-detail/185

https://madlib.apache.org/docs/latest/group__grp__kmeans.html

https://milvus.io/docs/install_embedded_milvus.md

https://github.com/jina-ai/executor-hnsw-postgres

https://github.com/forrest-2007/PASE

https://dl.acm.org/doi/abs/10.1145/3318464.3386131

https://dl.acm.org/doi/pdf/10.1145/3318464.3386131

https://github.com/B-sudo/VecDB-Exp

https://github.com/alipay/PASE

《如何用 PolarDB 在不确定世界寻找确定答案 (例如图像相似) - vector|pase》

《PostgreSQL 开源 高维向量相似搜索插件 vector - 关联阿里云rds pg pase, cube, 人脸识别》

《PostgreSQL 在资源搜索中的设计 - pase, smlar, pg_trgm - 标签+权重相似排序 - 标签的命中率排序》

《PostgreSQL 向量相似推荐设计 - pase》

《社交、电商、游戏等 推荐系统 (相似推荐) - 阿里云pase smlar索引方案对比》

《PostgreSQL 阿里云rds pg发布高维向量索引,支持图像识别、人脸识别 - pase 插件》

《PostgreSQL + FDW + vector 插件加速向量检索 - 在不确定世界寻找确定答案 (例如图像相似)》

《DuckDB 存储生态: lance(向量存储引擎): Modern columnar data format for ML/超越parquet》

《一种新的向量检索索引 DiskANN: Fast Accurate Billion-point Nearest Neighbor Search on a Single Node》

《为什么向量数据要归一化?》

《《开慧社》第二期《我朋友的创业故事》- Zilliz 向量数据库创始人 星爵 访谈》

《PostgreSQL 应用开发解决方案最佳实践系列课程 - 3. 人脸识别和向量相似搜索》

《PostgreSQL+MySQL 联合解决方案 - 第11课视频 - 多维向量相似搜索 - 图像识别、相似人群圈选等》

《画像系统标准化设计 - PostgreSQL roaringbitmap, varbitx , 正向关系, 反向关系, 圈选, 相似扩选(向量相似扩选)》

《阿里云PostgreSQL 向量搜索、相似搜索、图像搜索 插件 palaemon - ivfflat , hnsw , nsg , ssg》

《PostgreSQL 多维、图像 欧式距离、向量距离、向量相似 查询优化 - cube,imgsmlr - 压缩、分段、异步并行》

《PostgreSQL 相似人群圈选,人群扩选,向量相似 使用实践 - cube》

《HTAP数据库 PostgreSQL 场景与性能测试之 16 - (OLTP) 文本特征向量 - 相似特征(海明...)查询》

digoal's wechat