企业宣传,产品推广,广告招商,广告投放联系seowdb

实用于TTS语音处置名目标召回模型 和语义召回相比有什么优劣 词袋模型终究是个啥

在人工自动的泛滥运行中,关于文档的准确召回是一个宽泛经常使用的需求。例如,在基于阅读了解的问答系统(RAG)中,咱们经常经过嵌入模型生成向量来启动语义方面的召回,这种方法曾经证实了其效果良好。但是,这并不象征着该方法实用于一切场景。

让咱们思考一个触及语音处置的名目,用户或许会说出须要查问的内容,系统须要迅速召回与用户语音输入相关的文档。在这种状况下,系统的照应期间变得至关关键,任何提前都或许影响用户体验。关于这类需求,词袋模型或许成为一种更无利的选用,由于它无需处置复杂的语义相关,从而可以提供更极速的照应。所以,选用何种模型取决于详细的运行情形和性能要求。

什么是词袋模型

词袋模型是一种文本处置方法,先经过构建一个有序词表(字典),蕴含训练样本中 一切的不重复词汇 。而后,依据此词表遍历每个样本,假设某词在样本中产生则产生次数加1,否则次数设置为0。这样,每个样本都可以向量化成一个长度等于词表长度的向量。这么说或许有一点形象,让咱们来看一个例子,比如有两个文本:

首先,构建词汇表 ,这两个句子构成的词表(不去停用词)为:

[‘also’, ‘football’, ‘games’, ‘john’, ‘likes’, ‘mary’, ‘movies’, ‘to’, ‘too’, ‘watch’]

而后,关于每个文本,统计词汇表中每个单词的产生次数或许频率:

BOW词向量

词袋模型处置流程

词袋模型的处置流程可以总结为以下3步:

可以看出在经过向量化后,每个样本的特色维度长度等于词表长度。这种方法能笼罩一切样本中的词汇,但或许造成维度劫难,由于一个通常大小的中文数据集或许蕴含数万个词汇,象征着向量的维度也相应大。因此,在分词后,咱们通常统计每个词在数据集中的产生次数,并仅选用产生频率最高的前K个词作为最终词表。最后,会移除有意义的停用词,如“的”,“啊”,“了”等。

代码成功

手动撸代码

文本分词

向量化的第一步是分词。咱们将引见一个罕用的开源分词工具,jieba。在经常使用jieba之前,须要先启动装置,可以进入相应的虚构环境并经常使用命令​ ​pip install jieba​ ​成功装置。

import jieba, recut_all = Falsedef cutWords(s, cut_all=False):cut_words = []# 将一切字母、数字、冒号、逗号、句号等过滤掉s = re.sub("[A-Za-z0-9\:\·\—\,\。\“ \”]", "", s)seg_list = jieba.cut(s, cut_all=cut_all)cut_words.append("/".join(seg_list))

cut_all 参数可以指定分词形式,当​ ​cut_all = False​ ​​时,示意个别分词形式,设置为​​后,便可以开启全分词形式。

构建词表

分词后通常还会启动词频统计,以便选取产生频率最高的前K个词来结构词表。对词频启动统计须要经常使用另外一个包collection中的​​计数器。

import refrom collections import Counterimport jiebadef wordsCount(s):# 初始化空字符串用于存储分词结果cut_words = ""# 经常使用正则表白式移除非中文字符s = re.sub("[A-Za-z0-9\:\·\—\,\。\“ \”]", "", s)# 经常使用jieba启动分词,并衔接结果seg_list = jieba.cut(s, cut_all=False)cut_words += (" ".join(seg_list))# 将分词结果宰割成列表all_words = cut_words.split()# 初始化计数器c = Counter()# 遍历一切单词,长度大于1且不是换行符则启动计数for x in all_words:if len(x) > 1 and x != '\r\n':c[x] += 1# 创立一个词汇列表vocab = []print('\n词频统计结果:')# 打印并搜集产生频率最高的前5个词for (k, v) in c.most_common(5):print("%s:%d" % (k, v))vocab.append(k)# 打印词汇列表print("词表:", vocab)

词频统计

def vectorization_with_freq(s):# 此处接文本分词和词频统计代码,须要生成词表vocab和文本x_text# 初始化空列表用于存储向量化结果x_vec = []# 遍历文本中的每项for item in x_text:# 对词表中的每个词创立一个字典,初始化频率为0tmp = dict(zip(vocab, [0] * len(vocab)))# 遍历此项中的每个词for w in item:# 假设词在词表中,则频率加1if w in vocab:tmp[w] += 1# 将该项的向量减少到向量化结果列表x_vec.append(list(tmp.values()))# 打印词表、文本和向量化结果print("词表:", vocab)print("文本:", x_text)print(x_vec)

这段Python代码定义了一个函数​ ​vectorization_with_freq(s)​ ​​,它接受一个字符串​​作为输入,而后经常使用词频方法对其启意向量化处置。

sklearn成功

在通常中,咱们可以间接经常使用sklearn库,它曾经成功了上述配置,无需手动编写复杂的代码。

from sklearn.feature_extraction.text import CountVectorizercorpus = ["John likes to watch movies, Mary likes movies too","John also likes to watch football games",]bag_of_words = CountVectorizer(ngram_range=(1, 2), token_pattern="(?u)\\b\\w+\\b", binary=True).fit(corpus)vectors = bag_of_words.transform(corpus)print(vectors)""" (0, 5)1(0, 7)1(0, 8)1(0, 9)1(0, 10)1(0, 11)1(0, 12)1(0, 13)1(0, 14)1(0, 15)1(0, 16)1(0, 17)1(0, 18)1(0, 19)1(0, 21)1(1, 0)1(1, 1)1(1, 2)1(1, 3)1(1, 4)1(1, 5)1(1, 6)1(1, 8)1(1, 10)1(1, 16)1(1, 17)1(1, 19)1(1, 20)1"""

​CountVectorizer​ ​是scikit-learn库中的一个类,用于将文本转换为词项频率向量。上方解释你提到的这些参数。

​CountVectorizer.fit()​ ​是scikit-learn库中的一个方法,用于学习输入文本汇合(通常是一组文档)中一切单词的词汇表。这个环节也被称为“拟合”数据。

例如,假设咱们有三个文档:["The sky is blue", "The sun is bright", "The sun in the sky is bright"],​​函数会生成一个词汇表,蕴含一切不重复的单词:['The', 'sky', 'is', 'blue', 'sun', 'bright', 'in']。

这个词汇表随后可以��于将新的(或相反的)文档转换成向量,其中每个元素示意相应单词在文档中产生的频次。这是经过​ ​transform()​ ​​函数成功的,也经常和​​​方法一同经常使用,如​ ​fit_transform()​ ​。

输入

​CountVectorizer​ ​​的输入是一个稠密矩阵,其中每一行示意corpus中的一个文档,每一列对应于​ ​CountVectorizer​ ​拟合后获取的词汇表中的一个单词。在你的例子中,你有两个文档,所以你有两行。

每个元组​​​的值代表了词汇表中第​​​个单词在第​​​个文档中产生的频率。由于你设置​ ​binary=True​ ​, 所以这个频率只能是0或1,示意该单词在相应的文档中能否产生。

例如,在你给出的输入中,​​示意词汇表中的第5个单词在第一个文档("John likes to watch movies, Mary likes movies too")中产生了(至少一次性)。

相似地,​​示意词汇表中的第0个单词在第二个文档("John also likes to watch football games")中产生了。

留意,此处的索引是从0开局的,而且或许看不到某些索引,这是由于对应的词在相应的文档中没有产生,频率为零,而这种消息在稠密矩阵中通常会被省略,以节俭存储空间。

运行

在基于回答活成的阅读了解系统(RAG)中,文档召回是**的一步。这个环节关键依赖于检索和标定与用户查问相关性最高的文档。传统的RAG运行关键经过语义和关键字婚配来口头此操作,这通常须要经常使用embedding模型。详细来说,咱们会将文本输入到模型中,获取每个文档或查问的嵌入向量示意,而后计算它们之间的相似度。

除了上述方法外,咱们还可以经常使用基于词袋模型的召回战略。词袋模型将文档转换为一个向量,其中每个元素对应于特定单词或短语在文档中产生的频率。经过比拟这些向量,咱们可以确定文档之间的相似度。例如,咱们可以经过计算余弦相似度来权衡两个向量的相似水平,这种方法准许咱们找到与给定查问最相关的前K个文档。

import numpy as npfrom nltk.stem import PorterStemmerfrom sklearn.feature_extraction.text import CountVectorizerfrom sklearn.metrics.pairwise import check_pairwise_arrays, normalize, safe_sparse_dotstemmer = PorterStemmer()class Vectorizer:@staticmethoddef stem(text):# 词干化words = text.split()stemmed_words = [stemmer.stem(word) for word in words]sentence = " ".join(stemmed_words)sentence = sentencereturn sentencedef __init__(self, corpus):self.bag_of_words = CountVectorizer(ngram_range=(1, 2), token_pattern="(?u)\\b\\w+\\b", binary=True).fit(corpus)self.vectors = self.bag_of_words.transform(corpus)self.corpus = corpus@staticmethoddef cosine_similarity(X, Y=None, dense_output=True):X, Y = check_pairwise_arrays(X, Y)X_normalized = normalize(X, copy=True)if X is Y:Y_normalized = X_normalizedelse:Y_normalized = normalize(Y, copy=True)return safe_sparse_dot(X_normalized,Y_normalized.T,dense_output=dense_output)def get_relevent_docs(self, query, top_k=3, theshold=0):stem_query = self.stem(query)query_vectors = self.bag_of_words.transform([stem_query])cos_sim = self.cosine_similarity(self.vectors, query_vectors)indices = np.argpartition(cos_sim[:, 0], -top_k)[-top_k:]result = []for i in range(len(indices) - 1, -1, -1):idx = indices[i]score = cos_sim[idx, 0]if score > theshold:result.append([score, idx])result.sort(key=lambda x: x[0], reverse=True)# 相似度降序排序后前往return result

两种召回打算对比

基于语义+关键字模型的召回

此模型联合了关键字搜查和语义搜查。通常,该模型经常使用词嵌入(如Word2Vec,GloVe,BERT等)来示意文档和查问。

基于词袋模型的召回

基于词袋模型的搜查是一种经常出现的关键字搜查方法,其中文档和查问被示意为单词的汇合或多集,疏忽了任何语义和语法结构。

选用哪种模型取决于详细状况。假设查问关键基于准确的关键字婚配,词袋模型或许更适宜;而假设语义了解更关键,则应该思考经常使用基于语义+关键字的模型。在通常中,这两种方法往往联合在一同经常使用,例如,先经常使用词袋模型启动粗略搜查,而后经常使用基于语义+关键字模型启动准确搜查。

原文链接:​ ​​ ​

© 版权声明
评论 抢沙发
加载中~
每日一言
不怕万人阻挡,只怕自己投降
Not afraid of people blocking, I'm afraid their surrender