字节青训营项目:搜索引擎
技术栈
主要技术栈:Java+MySQL+Spring+SpringBoot+Vue
算法:Jieba分词、TFIDF词频权重计算
工具:布隆过滤器
不太建议使用微服务,因为搜索引擎作为中间件来讲,拆得越细,他性能会越差。我们对于这种服务的想法还是说让他尽可能的快。因为每个服务都有他的目标,像这种类似于搜索的这种服务的话,它其实性能的要求是远高于它架构的合理性的要求的。
流程思路
- 使用jieba分词对所有的文本进行分词,并将分词放进表segmentation ,这个过程中需要使用布隆过滤器保证分词表的唯一性,之前是用简单的查询判断表里有没有某个分词,比较慢,用map感觉又会比较占空间
- 随后为分词表 和 data 表(文本表)建立倒排索引,即建立一个关系表,将 文本 ID 跟 分词 ID 绑定起来,同时需要计算tfidf值,这是一个词频统计的权重,代表着一个词在某个文本中的区别能力。这样就可以根据分词去查询和哪些文本相关,查询结果根据tfidf值排序,实现基本的搜索引擎功能。
- 这个过程中,随着数据量的增大,这个关系表会越来越大,当文本数据有100 多万的时候,关系表达到了2000多万,通过分词查询速度会很慢,就采用了分表,分表的基本思路是将分词 id 取模,平均分到100张表里,这样单表的数据在20w左右,搜索的过程就更新为先去分词表里查分词的id,再去某个关系表查结果
- 可能提问:如果加了新的文本数据,流程还是先分词,旧分词可以定位到具体的关系表,添加行数据。新分词的话要先添加进分词表,再根据id取模结果,去对应关系表中添加数据
- 额外功能:搜索词过滤,用正则的方式得到要过滤的词,还是先查询所有结果,然后把过滤词的结果从所有结果中去掉,本质还是sql的逻辑
- 额外功能:相关搜索,这个实现起来很简单,就是用sql的like符号去查和输入词相关的词,没有用权重计算
- 额外功能:搜索关键词下拉联想,使用字典树。
- 额外功能:以图搜图,把所有图片都编码成512维的向量,然后把输入的图片也编码成这个向量,然后去计算输入图片和所有图片里的预先相似度,然后返回相似度较高的图片, 这是在Python 里实现的,Python 和 Java 之间做了一个 socket 的通信
改进:将数据放到redis中,像现在市面上大部分搜索引擎,比如ES,都是将数据放到内存里,对内存压力太大的话也可以进行横向拆分
TFIDF算法
TF-IDF算法介绍:
TF-IDF(term frequency–inverse document frequency)是一种用于计算词频的常用加权技术,主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
比如“我喜爱篮球”,我,喜爱会在其他文章(语句)中经常出现,但篮球偶尔出现,那么能给这条语句分类的关键词应该是“篮球”
TFIDF实际上是:TF * IDF,TF词频(Term Frequency),IDF反文档频率(Inverse Document Frequency)。
$$
TF = \frac{一个词在文章中出现的次数 }{文章总词数}
$$
$$
IDF = log\frac{总文章数}{一个词在多少篇文章中出现过}
$$
案例:假如一篇文件的总词语数是100个,而词语“母牛”出现了3次,那么“母牛”一词在该文件中的词频就是3/100=0.03。一个计算文件频率 (DF) 的方法是测定有多少份文件出现过“母牛”一词,然后除以文件集里包含的文件总数。所以,如果“母牛”一词在1,000份文件出现过,而文件总数是10,000,000份的话,其逆向文件频率就是 lg(10,000,000 / 1,000)=4。最后的TF-IDF的分数为0.03 * 4=0.12。
在本项目中,idf值本来需要根据语料库按照公式进行计算,不过jieba分词已经提供了一份很好的 idf 字典,所以默认直接使用jieba分词的 idf 字典
前端-Vue
运行前端项目,在工作目录打开cmd
1 |
|