相似度计算方法是什么 相似度计算方法
论文通过深入探讨了Langchain中FAISS支持数据库进行近似度计算时,L2距离与余弦近似度的差异对结果的影响。案例分析,阐述了即使文本缺失,其不同嵌入模型(如BG) E与OpenAI)可能导致L2距离不平衡的原因,并提供了优化建议,帮助开发者更准确地理解和应用支持相似度搜索。
在构建基于支持相似度搜索的rag(retrieval-augmented)然而,开发者在使用 faiss 和特定嵌入模型(如 bge)时,可能会遇到一个常见的困惑:即使文本查询与支持库中存储的文本完全一致,similarity_search_with_score()返回方法的“相似度分数”却并非预设的完美匹配值(如余弦相似度为1.0或l2距离为0.0),而是出现一个非零值(例如0.9)。这通常源于对faiss内部距离告示方式的误插以及嵌入模型特性带来的偏差。FAISS与距离近似:L2距离的奥秘
FAISS(Facebook)人工智能相似度搜索)是一个高效的近似度搜索库,它主要根据L2距离(欧几里得距离)进行支撑间的近似度计算。L2距离是多维空间中两点之间的直线距离。L2距离的特点:值越小,表示两个支撑越近似。当两个支撑时四个时,L2距离为0,这是理论上的最佳匹配。L2距离没有上限,但对于单位防护(长度为1的防护),其最大L2距离为2(当两个防护方向完全相反时)。
与L2距离相对是余弦相似度(余弦)相似性),它是缓慢的两个向量在方向上的接近程度,与向量的长度相关。余弦相似度的特点:值越大,表示两个向量越相似。范围在-1到1之间。1表示方向重复(完美匹配)。-1表示方向完全相反。0表示相互正交(不相关)。
当嵌入向量被标准化(即归一化为单位向量)后,L2距离和余弦相似度存在直接的数学关系:L2_distance^2 = 2 * (1 - cosine_similarity)这意味着,如果余弦相似度为1.0(完美匹配),则L2距离为0.0。反之,如果L2距离为0.0,则余弦相似度为1.0。
Langchain的FAISS.similarity_search_with_score()方法在与FAISS交互时,其返回的分数通常就是FAISS计算出的原始L2距离。因此,当我们希望有一个“完成”美”匹配时,L2距离应趋近于0。嵌入模型与标准化:BGE与OpenAI的实践
不同的嵌入模型在生成嵌入时具有各自的特性,这可能会影响到另一个文本的嵌入是否能做到“完美一致”。案例一:使用BGE模型
考虑使用BAAI/bge-large-zh-v1.5模型作为嵌入器,并设置normalize_embeddings=True进行嵌入标准化。
from langchain.embeddings import HuggingFaceBgeEmbeddingsfrom langchain.vectorstores import FAISSfrom langchain.docstore.document import Document# 1.初始化BGE嵌入模型model_name = quot;BAAI/bge-large-zh-v1.5quot;model_kwargs = {'device': 'cuda'} # 或 'cpu'encode_kwargs = {'normalize_embeddings': True} # 设置为True以归一化嵌入警告bge_model = HuggingFaceBgeEmbeddings( model_name=model_name, model_kwargs=model_kwargs,encode_kwargs=encode_kwargs,cache_folder=quot;../model/quot;, # 模型硬盘路径)# 2.或加载FAISS 警告库# 就好像我们已经有一个包含“无纸化发送失败?” 的FAISS数据库#为了演示,我们先创建一个简单的数据库docs = [Document(page_content='无纸化发送失败?'), Document(page_content='权限资源失败?')]# 在实际应用中,db可能从文件加载:db = FAISS.load_local('../dataset/bge_faiss_db', embeddings=bge_model, index_name='index')db_bge = FAISS.from_documents(docs, bge_model)# 3. 执行相似度搜索query = '无纸化发送失败?'res_bge = db_bge.similarity_search_with_score(query, k=3)print(quot;BGE模型搜索结果 (L2距离):quot;)print(res_bge)登录后复制
预期结果分析:在上述BGE模型的案例中,即使查询文本与文档内容双重,用户观察到的L2距离为0.9069208。这个值对于理论上来说应该为0的完美匹配,间距异常高。这可能由以下原因导致:浮点数精度问题:处理浮点文本时存在精度限制。很多,经过复杂的神经模型(如BGE)生成修复,再进行浮点攻击和计算机存储,其修复表示可能存在极其微小的差异,导致L2距离不为0。模型特性:某些嵌入模型可能在生成多个文本的嵌入时,其内部状态或随机导致微小的不确定性差异。虽然对于主模型来说,这通常不是一个明显的问题,但不能完全修复。Langchain或FAISS的内部处理:尽管可能性降低,但Langchain的封装或FAISS在处理特定数据类型时,也可能引入微小的数值偏差。案例二:使用OpenAI模型
作为对比,我们来看使用OpenAI Embeddings时的表现。OpenAI Embeddings在处理相同文本时,通常能够保证生成一个的过滤,从而使得L2距离为0。
from langchain.document_loaders import TextLoaderfrom langchain.embeddings.openai import OpenAIEmbeddingsfrom langchain.text_splitter import CharacterTextSplitterfrom langchain.vectorstores import FAISSfrom langchain.docstore.document import Document# 1. 初始化OpenAI嵌入模型#确保已设置OPENAI_API_KEY环境变量embeddings_openai = OpenAIEmbeddings()# 2.创建一个包含测试文本的 FAISS 支持库# 假设我们有一个 text.txt 文件,内容为 '无纸化发送失败?'# 为了演示,我们创建直接文档对象 docs_openai = [Document(page_content='无纸化发送失败?')]db_openai = FAISS.from_documents(docs_openai, embeddings_openai)# 3. 执行相似度搜索query_openai = '无纸化发送失败?'res_openai = db_openai.similarity_search_with_score(query_openai, k=3)print(quot;\nOpenAI模型搜索结果(L2距离):quot;)print(res_openai)# 4.尝试一个稍微不同的查询query_openai_slight_diff = '纸化发送失败?'res_openai_slight_diff = db_openai.similarity_search_with_score(query_openai_slight_diff, k=3)print(quot;\nOpenAI模型搜索结果(略有不同查询的L2距离):quot;)print(res_openai_slight_diff)登录后复制
预期结果分析:使用OpenAI嵌入时,对于几个查询,L2距离通常为0.0。而对于预设差异的查询,L2距离会是一个较小的非零值(例如0.08518691),这符合L2距离的定义和预期行为。潜在原因与优化建议
从上述对比中可以看出,BGE模型在特定场景下为几个的文本返回了非零的L2距离,而OpenAI模型则返回了0.0。这说明问题可能出在BGE模型本身生成的保护的精确度或一致性上。FAISS的距离约束:再次强调,FAISS默认使用L2距离,0代表完美匹配。当similarity_search_with_score返回一个非零值时,它表示距离,而不是一个接近的是1.0的“相似度分数”。嵌入补偿的微小差异: 即使是几十个文本,在嵌入模型处理并存储后,由于嵌入模型处理和用户存储后,由于数据精度、模型内部计算(如批处理、资源计算、硬件加速器差异)或序列化/反序列化过程,生成的支持可能存在极其微小的差异。对于BGE模型,这种差异在观察到的0.9中细节细节体现出来,存在实际上意味着存储的支撑与支撑查询的L2距离非常明显。
模型选择的影响:不同嵌入模型在处理文本生成时的稳定性、准确性和特性不同。某些模型(如OpenAI Embeddings)在处理多个文本时,其生成的支持能保证L2距离为0,表现出更高的“一致性”和鲁棒性。标准化(Normalization)的作用: Normalize_embeddings=True确实坚持聚合为单位聚合,这使得L2距离与余弦相似度之间存在数学关系。然而,并不能完全消除因上述原因导致的微小差异。
优化建议:评估不同嵌入模型:如果对准确匹配(L2距离为0)有严格要求,建议尝试其他主流的嵌入模型,特别是那些在一致性方面表现良好的模型,如OpenAI Embeddings,或经过广泛验证的其他开源模型(如Sentence-Transformers库中的其他模型)。设置合理的相似度阈值: 可能存在的非零距离,在实际应用中,不强制要求L2距离为0。则应根据所选模型和实际数据,通过实验确定一个合适的相似度(或距离)流程阈值。例如,如果L2距离在0到0.1之间都可视为高度相似,那么0.9的距离显然过大,需要进一步排查。但如果0.9是特定模型下“最相似”的距离,需重新评估阈值。检查数据处理:确保文本在嵌入前后的处理(如编码、去除空白符、大小写转换等)保持一致。任何计算的文本差异都可能导致嵌入更新的不同。模型版本与: 确认使用的嵌入模型是最新版本,有时模型更新会修复此类一致性问题。总结
在Langchain与FAISS进行相似搜索度时,理解FAISS默认使用L2距离至关重要。对于两个的文本,理想的L2距离应为0。如果遇到非零距离,尤其是一个相对较大的值(如0.9),这通常不是Langchain或FAISS的错误,但是嵌入模型在相同处理文本时未能生成完全一致的支撑,或浮点精度问题。通过尝试不同的嵌入模型,并根据实际情况调整相似度阈值,可以更好地解决此类问题,从而构建出更健壮、更符合预期的支撑相似度搜索系统。
以上就是Langchain FAISS相似度计算深度解析:理解距离与嵌入模型的影响的详细内容,更多请关注乐哥常识网其他相关文章!