你还在用关键词匹配?Python 玩转文本聚类 + 相似度搜索,效果直接碾压
说句实话,现在很多系统里的“搜索”和“推荐”,还停留在一个很原始的阶段:
👉 关键词匹配(LIKE / contains)
用户搜:“机器学习入门”
结果返回:“机器维修指南”
你说离谱不离谱。
问题的本质是:系统不理解“语义”。
今天这篇,我们就用 Python,一步步把“文本聚类 + 相似度搜索”这件事讲清楚,而且是能落地的那种。
一、先把问题说清楚:我们到底在做什么?
其实就两件事:
1️⃣ 文本聚类(Clustering)
👉 把“意思相近”的文本自动分到一类
比如:
- “Python入门教程”
- “Python新手学习路径”
- “零基础学Python”
👉 应该归为一类
2️⃣ 相似度搜索(Similarity Search)
👉 给你一段话,找到“最像它”的文本
比如输入:
“如何快速学习Python?”
系统应该返回:
- Python入门教程
- Python学习路线
👉 本质一句话总结:
把“文本”变成“向量”,再用数学解决语义问题。
二、核心思路:文本 → 向量(Embedding)
这是整个技术的灵魂。
方法1:TF-IDF(传统但好用)
from sklearn.feature_extraction.text import TfidfVectorizer
texts = [
"Python入门教程",
"机器学习基础",
"Python学习路径",
"深度学习实战"
]
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(texts)
print(X.shape) # (4, N)
👉 每一段文本 → 一个向量
方法2:Sentence-BERT(推荐)
如果你追求效果,建议直接上:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
texts = [
"Python入门教程",
"机器学习基础",
"Python学习路径",
"深度学习实战"
]
embeddings = model.encode(texts)
print(embeddings.shape)
👉 优点:
- 能理解语义
- 效果远强于 TF-IDF
三、文本聚类:让数据“自动分组”
我们直接上最常用的 K-Means。
示例:K-Means 聚类
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=2)
kmeans.fit(embeddings)
labels = kmeans.labels_
for text, label in zip(texts, labels):
print(f"{text} -> 类别 {label}")
👉 输出可能是:
Python入门教程 -> 类别 0
Python学习路径 -> 类别 0
机器学习基础 -> 类别 1
深度学习实战 -> 类别 1
👉 这就实现了:
系统自动帮你“归类内容”
四、相似度搜索:核心是“向量距离”
最常用的是:
👉 余弦相似度(Cosine Similarity)
示例:计算相似度
from sklearn.metrics.pairwise import cosine_similarity
query = "如何学习Python"
query_vec = model.encode([query])
similarities = cosine_similarity(query_vec, embeddings)
for text, score in zip(texts, similarities[0]):
print(f"{text} 相似度: {score:.4f}")
👉 输出类似:
Python入门教程 相似度: 0.82
Python学习路径 相似度: 0.85
机器学习基础 相似度: 0.30
👉 你就可以做:
import numpy as np
top_k = np.argsort(similarities[0])[::-1][:2]
for idx in top_k:
print(texts[idx])
👉 这就是一个最基础的“语义搜索引擎”。
五、进阶:大规模相似度搜索(FAISS)
当数据量上万、百万时,暴力计算就不行了。
👉 这时候要用向量数据库。
示例:使用 FAISS
import faiss
import numpy as np
dim = embeddings.shape[1]
index = faiss.IndexFlatL2(dim)
index.add(np.array(embeddings))
query_vec = model.encode(["Python学习"])
D, I = index.search(np.array(query_vec), k=2)
print(I)
👉 优势:
- 查询速度极快(毫秒级)
- 支持百万级数据
六、实际应用场景(非常重要)
说几个你可以直接落地的👇
1️⃣ 搜索引擎升级
👉 从关键词 → 语义搜索
2️⃣ 内容推荐系统
👉 推荐“相似文章”
3️⃣ 去重 / 聚合
👉 自动识别“重复内容”
4️⃣ 客服问答系统
👉 找“最相似问题”
七、一个很多人忽略的问题:效果 > 技术
很多人会问:
👉 “我该用 TF-IDF 还是 BERT?”
我给你一个很真实的答案:
✔ 如果你是:
- 小项目
- 数据少
- 对精度要求不高
👉 用 TF-IDF 就够了
✔ 如果你是:
- 搜索 / 推荐系统
- 用户体验重要
- 数据复杂
👉 直接上 Sentence-BERT
👉 记住一句话:
不要用“最牛的技术”,要用“最合适的技术”。
八、我的一点个人经验(很重要)
我做过不少文本类系统,踩过几个坑:
❌ 误区1:只关注模型
👉 实际上:
- 数据清洗更重要
- 分词质量更关键
❌ 误区2:忽略向量归一化
from sklearn.preprocessing import normalize
embeddings = normalize(embeddings)
👉 会显著提升相似度效果
❌ 误区3:不做评估
👉 一定要:
- 人工标注样本
- 对比效果
九、总结一下(给你一条清晰路线)
文本 → 向量化(TF-IDF / BERT)
→ 聚类(KMeans)
→ 相似度计算(Cosine)
→ 向量索引(FAISS)
最后一句话
很多人以为:
👉 “AI 很复杂”
但其实:
很多“智能系统”的本质,只是把问题从“字符串”变成“向量”。
一旦你理解了这一点,
文本搜索、推荐、聚类——全都通了。