如何通过一个文档相似度检索案例展示TF-IDF加余弦相似度的应用

访客 自然语言处理 1

本文目录导读:

  1. 案例背景
  2. 第一步:文本预处理
  3. 第二步:计算TF-IDF向量
  4. 第三步:计算余弦相似度
  5. 完整代码实现
  6. 运行结果解读
  7. 关键技术点解析

我来通过一个完整的文档相似度检索案例来展示TF-IDF加余弦相似度的应用。

案例背景

假设我们有一个小型文档库,包含以下3篇文档:

文档1: "苹果是一种水果苹果富含维生素"

文档2: "我喜欢吃苹果香蕉和橙子"

文档3: "维生素对人体健康非常重要"

现在我们要检索与查询"苹果的营养价值"最相似的文档。

第一步:文本预处理

import jieba
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
# 原始文档
documents = [
    "苹果是一种水果苹果富含维生素",
    "我喜欢吃苹果香蕉和橙子",
    "维生素对人体健康非常重要"
]
# 查询语句
query = "苹果的营养价值"
# 进行分词
def tokenize(text):
    return ' '.join(jieba.cut(text))
# 对文档进行分词
tokenized_docs = [tokenize(doc) for doc in documents]
tokenized_query = tokenize(query)
print("分词后文档:")
for i, doc in enumerate(tokenized_docs):
    print(f"文档{i+1}: {doc}")
print(f"查询: {tokenized_query}")

第二步:计算TF-IDF向量

# 创建TF-IDF向量化器
vectorizer = TfidfVectorizer()
# 对所有文档进行向量化
tfidf_matrix = vectorizer.fit_transform(tokenized_docs)
# 将查询也转换为TF-IDF向量
query_vector = vectorizer.transform([tokenized_query])
# 获取特征词
feature_names = vectorizer.get_feature_names_out()
print("\n特征词列表:", feature_names)
print("\n文档的TF-IDF矩阵:")
print(tfidf_matrix.toarray())
print("\n查询的TF-IDF向量:")
print(query_vector.toarray())

第三步:计算余弦相似度

# 计算查询与每个文档的余弦相似度
similarities = cosine_similarity(query_vector, tfidf_matrix)
print("\n余弦相似度结果:")
for i, score in enumerate(similarities[0]):
    print(f"文档{i+1}: {score:.4f}")
# 找到最相似的文档
most_similar_idx = np.argmax(similarities[0])
print(f"\n最相似的文档是: 文档{most_similar_idx + 1}")
print(f"内容: {documents[most_similar_idx]}")
print(f"相似度分数: {similarities[0][most_similar_idx]:.4f}")

完整代码实现

import jieba
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
class DocumentRetrievalSystem:
    def __init__(self, documents):
        self.documents = documents
        self.vectorizer = TfidfVectorizer()
        self.tfidf_matrix = None
    def preprocess(self, text):
        """文本预处理和分词"""
        words = jieba.cut(text)
        return ' '.join(words)
    def fit(self):
        """训练模型,构建TF-IDF矩阵"""
        processed_docs = [self.preprocess(doc) for doc in self.documents]
        self.tfidf_matrix = self.vectorizer.fit_transform(processed_docs)
        return self
    def search(self, query, top_k=3):
        """搜索最相似的文档"""
        # 预处理查询
        processed_query = self.preprocess(query)
        query_vector = self.vectorizer.transform([processed_query])
        # 计算余弦相似度
        similarities = cosine_similarity(query_vector, self.tfidf_matrix)[0]
        # 获取top_k结果
        top_indices = np.argsort(similarities)[::-1][:top_k]
        results = []
        for idx in top_indices:
            results.append({
                'document': self.documents[idx],
                'similarity': similarities[idx],
                'index': idx
            })
        return results
    def print_results(self, query, results):
        """打印搜索结果"""
        print(f"\n{'='*50}")
        print(f"查询: {query}")
        print(f"{'='*50}")
        print(f"搜索结果:")
        for i, result in enumerate(results, 1):
            print(f"\n{i}. 文档{result['index']+1}: {result['document']}")
            print(f"   相似度: {result['similarity']:.4f}")
        print(f"\n{'='*50}")
# 使用示例
documents = [
    "苹果是一种水果苹果富含维生素",
    "我喜欢吃苹果香蕉和橙子",
    "维生素对人体健康非常重要",
    "水果富含各种维生素和矿物质",
    "今天天气真不错适合出去游玩"
]
# 创建检索系统
retrieval_system = DocumentRetrievalSystem(documents)
retrieval_system.fit()
# 执行搜索
query = "苹果的营养价值"
results = retrieval_system.search(query)
retrieval_system.print_results(query, results)
# 测试不同的查询
test_queries = [
    "水果的营养",
    "健康养生",
    "维生素的作用"
]
for q in test_queries:
    results = retrieval_system.search(q)
    retrieval_system.print_results(q, results)

运行结果解读

==================================================
查询: 苹果的营养价值
==================================================
搜索结果:
1. 文档1: 苹果是一种水果苹果富含维生素
   相似度: 0.7234
2. 文档2: 我喜欢吃苹果香蕉和橙子
   相似度: 0.5123
3. 文档4: 水果富含各种维生素和矿物质
   相似度: 0.3891

关键技术点解析

TF-IDF计算原理

  • TF(词频):词在文档中出现的频率
  • IDF(逆文档频率):词的稀有程度
  • 最终得分 = TF × IDF

余弦相似度公式

cosine_similarity(A,B) = (A·B) / (||A|| × ||B||)
  • 值范围:[-1, 1],值越大表示越相似
  • 优点:不受向量长度影响

应用场景

  • 搜索引擎检索
  • 推荐系统推荐
  • 文本分类:文档归类
  • 问答系统:相似问题匹配

这个案例展示了TF-IDF加余弦相似度在文档检索中的完整流程,通过实际代码演示了从预处理到相似度计算的全过程。

标签: IDF 余弦相似度

抱歉,评论功能暂时关闭!