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 - 标签+权重相似排序 - 标签的命中率排序》
《社交、电商、游戏等 推荐系统 (相似推荐) - 阿里云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) 文本特征向量 - 相似特征(海明...)查询》