Python bm25短文本分类,相似度识别,BM25算法相似度匹配,疾病相似度匹配gensim实现,bm25算法原理和实现实例

一、bm25的应用和基础

参考:BM25算法 原理简介_小白的进阶的博客-CSDN博客_bm25

医学领域,BM25算法的应用,文档分类相似度识别以及疾病、手术等实体的相似度匹配。文档的处理相对简单,可以直接调用相关算法包,实体单词的相似度匹配需要对文本做相关的处理。对比研究,在文档中,表示特征的主要是单词,而在实体名词(疾病、手术、药品名称)中,表示特征的是字或者由n-gram切分的元素,当用字表示特征时,文本的语义会丢失,所以我建议用字和n-gram(n>=2)分词元素作为特征。

BM25算法相关性分数的构成:

分为两个类别,一个是计算文档与文档的相似度,另一个是计算词与词的相似度,如果计算的是词(或称为短文本)与词之间的相似度,那么就要用n-gram切词,进而以每个元素为单位进行计算。

以文档相似度为例:

相关性分数公式如下:

里面包含三部分计算:

(1)元素的权重,计算tf-idf,文档的元素就是词,短文本的元素为字或n-gram元素:

其中N表示索引中全部文档数,df_{i}为包含了q_{i}的文档的个数。依据IDF的作用,对于某个q_{i},包含q_{i}的文档数越多,说明q_{i}重要性越小,或者区分度越低,IDF越小,因此IDF可以用来刻画q_{i}与文档的相似性。

 (2)单词和文档的相关性

 其中,是单词t在文档d中的词频,是文档d的长度,是所有文档的平均长度,变量是一个正的参数,用来标准化文章词频的范围,当=0,就是一个二元模型(binary model)(没有词频),一个更大的值对应使用更原始的词频信息。b是另一个可调参数(0<b<1),他是用决定使用文档长度来表示信息量的范围:当b为1,是完全使用文档长度来权衡词的权重,当b为0表示不使用文档长度。

(3)单词和查询的相关性: 

 

 这里tf_{tq}表示单词t在query中的词频,k_{3}是一个可调正参数,来矫正query中的词频范围。

最终相似度公式

二、相似度分类实例(疾病相似度分类)

现在bm25实现的开源包有很多,在这里我是用gensim实现。

gensim包的下载配置:清华镜像源

pip install --upgrade -i https://pypi.tuna.tsinghua.edu.cn/simple gensim

基本使用方法,以短文本分类为实例

corpus为标准的单词分类集合,主要包含了每类疾病的标准分类特征,corpus_dic为每个特征集合对应的分类标签,key为分类标签,value为特征。test_word为测试文本

处理过程:用测试集的特征和标准特征计算相关性,对测试样本的每个元素的相关性分数求和,即为总的相关性分数:

from gensim.summarization import bm25
import jieba

def gensim_bm25_word_classification(test_word):
    corpus = [
        ['高','血','压','高血','血压'],
        ['糖','尿','病'],
        ['精','神','病']
        ]
    corpus_dic = {
        '高血压':['高','血','压','高血','血压'],
        '糖尿病':['糖','尿','病'],
        '精神病':['精','神','病']
    }
    bm25Model = bm25.BM25(corpus)
    #将str转为list
    test_word = list(test_word)

    scores = bm25Model.get_scores(test_word)
    print('测试短文本:', test_word)
    for i, j in zip(scores, corpus):
        for m in corpus_dic.keys():
            if j == corpus_dic[m]:
                word_name = m
        print('分值:{},原词:{}'.format(i, word_name))

 测试:高血压1级

if __name__ == '__main__':
    test_word = '高血压1级'
    gensim_bm25_word_classification(test_word)

分类结果打印:

 高血压类的相关性分数为1.31,远高于其他分类,故分类结果为:高血压。

二、文本分类

需要jieba分词和stopword停用词设置,非常简单。

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
BM25算法是一种用于评估搜索词和文档之间相关性的算法,它是一种基于概率检索模型提出算法。其实现原理如下: 1. 对查询进行分词,得到单词 $q_i$。 2. 对于每个文档 $D$,计算BM25分数,该分数由3部分组成: a. query中每个单词和文档D之的相关性 b. 单词和query之间的相关性 c. 每个单词的权重 3. 计算每个单词的权重,使用公式 $w_i = \frac{(k_1 + 1) * f_i}{k_1 * ((1 - b) + b * \frac{L_D}{L_{ave}}) + f_i}$,其中 $f_i$ 是单词在文档中出现的频率,$L_D$ 是文档的长度,$L_{ave}$ 是所有文档的平均长度,$k_1$ 和 $b$ 是调节参数。 4. 计算每个单词和查询之间的相关性,使用公式 $IDF_i = \log{\frac{N - n_i + 0.5}{n_i + 0.5}}$,其中 $N$ 是文档总数,$n_i$ 是包含单词 $i$ 的文档数。 5. 计算每个单词和文档之间的相关性,使用公式 $score(D, Q) = \sum_{i=1}^{n} IDF_i * \frac{(k_1 + 1) * f_i}{k_1 * ((1 - b) + b * \frac{L_D}{L_{ave}}) + f_i}$,其中 $n$ 是查询中单词的数量。 6. 对于每个文档,按照相关性分数进行排序,返回排名前 $k$ 的文档。 ```python # 以下是一个使用Python实现BM25算法的示例 import numpy as np class BM25_Model(object): def __init__(self, k1=1.5, b=0.75): self.k1 = k1 self.b = b def fit(self, docs): self.N = len(docs) self.avgdl = sum([len(doc) for doc in docs]) / self.N self.docs = docs self.f = [] self.df = {} self.idf = {} self.doc_len = [] for doc in docs: tmp = {} self.doc_len.append(len(doc)) for word in doc: if word not in tmp: tmp[word] = 0 tmp[word] += 1 self.f.append(tmp) for k in tmp.keys(): if k not in self.df: self.df[k] = 0 self.df[k] += 1 for k, v in self.df.items(): self.idf[k] = np.log((self.N - v + 0.5) / (v + 0.5)) def get_score(self, query): score = np.zeros(self.N) for q in query: if q not in self.f[0]: continue idf = self.idf[q] for i in range(self.N): f = self.f[i].get(q, 0) score[i] += idf * (f * (self.k1 + 1) / (f + self.k1 * (1 - self.b + self.b * self.doc_len[i] / self.avgdl))) return score # 示例 docs = [['hello', 'world'], ['hello', 'python'], ['python', 'world']] bm25 = BM25_Model() bm25.fit(docs) query = ['hello'] score = bm25.get_score(query) print(score) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

医学小达人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值