天天看点

对盗图、盗文、盗墓深恶痛绝吗?PostgreSQL结合余弦、线性相关算法 在文本、图片、数组相似 等领域的应用 - 2 smlar插件详解

postgresql , 文本分析 , cosine , smlar , 相似性 , simlar , tf , idf , tf-idf , tag

以2个例子作为开始,

在数据库中有两条这样的记录

然后使用这样的查询条件进行查询

很显然,两条记录都会被匹配到,但是哪条记录应该排在前面呢?

在搜索引擎中搜索"狗|吉娃娃狗"

哪个会排在前面呢?试试就知道了,翻到第二页,以防被广告冲昏头脑

对盗图、盗文、盗墓深恶痛绝吗?PostgreSQL结合余弦、线性相关算法 在文本、图片、数组相似 等领域的应用 - 2 smlar插件详解

很显然吉娃娃被排在了前面,为什么呢?

其实都是tf-idf算法起到的作用,因为在全局文本中,狗比吉娃娃出现的次数多,所以根据idf的算法 ( log(总文本数/包含此词的文本数) ) 狗的idf比吉娃娃的低。

那么当tf相同时,很显然tf*idf取决于idf的大小。

关于tf与idf的概念,请参考

<a href="https://github.com/digoal/blog/blob/master/201701/20170116_02.md">《文本(关键词)分析 - tf(term frequency 词频) idf(inverse document frequency 逆向文本频率)》</a>

那么作为支持全文检索的postgresql数据库,默认支持tf-idf吗?

我们在ts_rank, ts_rank_cd的代码中可以了解到,postgresql这两个函数并不关心idf。

其实在网上也有人问过这样的问题

<a href="http://stackoverflow.com/questions/18296444/does-postgresql-use-tf-idf">http://stackoverflow.com/questions/18296444/does-postgresql-use-tf-idf</a>

postgresql内置的rank计算方法并不关心idf,而仅仅计算当前文本的词频。

目前postgresql通过ts_rank与ts_rank_cd计算tsquery与tsvector的相关性,算法详见

如何让postgresql计算rank时关心idf?详见此文

<a href="https://github.com/digoal/blog/blob/master/201612/20161222_02.md">《从相似度算法谈起 - effective similarity search in postgresql》</a>

smlar插件支持多种相似度计算公式(算法),cosine(default), tfidf, overlap。同时还提供了自定义公式计算相似度的函数。

1. 计算数组的相似度

2. 计算自定义复合数组(元素,权重)的数组的相似度,可以计算所有元素,同时也允许只计算重叠元素的部分(当权重不同时,相似度不同,例如cosine算法)。

或者我们把它理解为包含tfidf的加权数组,比如 [('中国', 0.1), ('日本', 0.1), ('海盗', 0.9)]

在文本相似度分析中很有用。

例子

注意

3. 通过自定义公式,公式中包含3个变量n.i, n.a, n.b,计算两个数组的相似性,你可以自定义算法。

1. 判断两个数组是否相似,(当相似值大于limit值时, limit值通过smlar.threshold参数设置)

1. 将tsvector类型转换为text array类型

2. 对数组内的元素排序并去除重复元素

3. 判断数组内是否包含某元素,包含时返回1.0, 不包含时返回0。

4. 类似三目操作符,判断数组内是否包含某元素,包含时返回第三个参数的值,不包含时返回第四个参数值。

1. 相似度limit值,当相似性低于这个值时,%操作符(计算两个数组是否相似) 将返回false。

2. 是否持久化idf表

3. 默认的相似性计算公式

源码,其中tfidf计算需要用到统计idf的表。

算法详见

4. 当相似性计算公式为tfidf时,需要设置这个参数,并且需要一张统计信息表,记录每个词的idf,以及总共有多少文本。

5. 当相似性计算公式为tfidf时的配置。

tf(词频)计算方法设置:出现次数、1+log(出现次数)、常数1

注意 :

gin index supports only smlar.tf_method = \"const\""

6. 当相似性计算公式为tfidf时的配置。

idf是否+1后再取log

smlar插件的核心,实际上是计算两个数组(任意类型的数组)的相似性,当然为了提高速度,它也支持索引。

不同类型对应的ops如下,在创建索引是需要使用它们

默认的cosine算法的例子参考

接下来看看如何使用tfidf

1. 安装smlar插件

2. 创建测试表

4. 创建统计表, 记录每个词在多少篇文本中出现过,以及总的文本数。

对于日常的使用,我们可以从词库中导出词组与idf,并生成文本总数,与词出现的次数,导入这张表

比如从scws, jieba分词等词库,导出并导入该表

5. 使用本地数据,生成idf,(实际生产时,可以忽略,建议使用从词库导入的idf)

6. 插入文本数

7. 将文本转换为text数组的函数

注意tsvector转换为数组时,会丢失重复值

8. 创建表达式索引

9. 参数设置,使用tfidf公式计算数组相似度

10. 查询

当tfidf similarity &gt;= smlar.threshold时,返回。

我们可以把相似度调高,从而排除更多的记录,提高查询效率

basic steps for clustering documents can vary a bit depending on your

precise goals, but one example would be:

1. often there is an initial first level of processing to handle

tokenization, word stemming, filter stopwords etc.

there is no right or wrong way of handling this step and there is a fair

amount of art to doing it well.

2. build feature vectors for each document.

there are a variety of methods for handling this, one common example

for which you need the following metrics:

a) word count for each document

b) how many documents word occur across all documents

c) documents count

having produced a feature vectors for your documents you can then call

the kmeans function in madlib to perform the actual clustering (

given a tf-idf

feature vector the most common distance function is cosine similarity,

though other distance functions may make sense depending on your use case.

<a href="http://madlib.incubator.apache.org/docs/latest/group__grp__svec.html">http://madlib.incubator.apache.org/docs/latest/group__grp__svec.html</a>

rum也在支持tfidf了。

<a href="http://www.sigaev.ru/">http://www.sigaev.ru/</a>

<a href="http://www.sigaev.ru/git/gitweb.cgi?p=smlar.git;a=summary">http://www.sigaev.ru/git/gitweb.cgi?p=smlar.git;a=summary</a>

<a href="http://www.sigaev.ru/git/gitweb.cgi?p=smlar.git;a=blob;f=readme;h=8fa81c51d749cc714e52257a15edf547f0b26edf;hb=8d02df18c0bbfd6ccba94a9582499ec8746047e5">http://www.sigaev.ru/git/gitweb.cgi?p=smlar.git;a=blob;f=readme;h=8fa81c51d749cc714e52257a15edf547f0b26edf;hb=8d02df18c0bbfd6ccba94a9582499ec8746047e5</a>

<a href="http://www.pgcon.org/2012/schedule/events/443.en.html">http://www.pgcon.org/2012/schedule/events/443.en.html</a>

<a href="http://www.pgcon.org/2012/schedule/attachments/252_smlar-2012.pdf">http://www.pgcon.org/2012/schedule/attachments/252_smlar-2012.pdf</a>

<a href="http://railsware.com/blog/2012/05/10/effective-similarity-search-in-postgresql/">http://railsware.com/blog/2012/05/10/effective-similarity-search-in-postgresql/</a>

继续阅读