1. 什么是 Sentence Transformers? #
Sentence Transformers 是一个 Python 库,可以将句子、段落甚至整个文档转换成固定长度的数字向量(Embedding)。这些向量能够捕捉文本的语义信息,相似的文本会产生相似的向量,所以通过比较向量就能找到语义相似的内容。
为什么要用 Sentence Transformers?
想象一下,你想在一个包含数千篇文档的知识库中找到"如何学习编程?"相关的文档。传统的关键词搜索可能会找不到,因为文档中可能用的是"如何入门编程"或"编程学习指南"等不同的表述。但 Sentence Transformers 能理解这些不同的表达方式在语义上是相似的,从而找到相关内容。
主要应用场景:
- 语义搜索:根据意思搜索,而不仅仅是关键词匹配
- 相似度计算:判断两段文本是否相似
- 文档聚类:将相似的文档分组
- 智能推荐:推荐相似的内容
- 问答系统:找到与问题最相关的答案
前置知识补充:
- 嵌入(Embedding):将文本转换成数字向量的过程。向量是一串数字,比如
[0.1, 0.5, -0.3, 0.8, ...]。相似的文本会有相似的向量。- 余弦相似度:衡量两个向量相似程度的指标,范围通常是 -1 到 1,值越接近 1 表示越相似。
- Transformer:一种深度学习模型架构,Sentence Transformers 基于此构建。不需要深入了解原理,只需要知道它能很好地理解文本语义即可。
2. 环境准备 #
在学习 Sentence Transformers 之前,需要确保你的 Python 环境已经准备好。Sentence Transformers 支持 Python 3.8 及以上版本,并且会自动安装 PyTorch 作为底层框架。
2.1 检查 Python 版本 #
在安装之前,先检查一下你的 Python 版本是否符合要求。
# Windows PowerShell:查看 Python 版本
python --version# macOS 终端:查看 Python 版本
python3 --version2.2 安装 Sentence Transformers #
Sentence Transformers 依赖 PyTorch,安装时会自动安装 PyTorch(CPU 版本)。如果需要 GPU 支持,需要先单独安装支持 GPU 的 PyTorch。
# 说明:Windows PowerShell 安装 Sentence Transformers
# 先升级 pip 到最新版本,确保能正常安装依赖
python -m pip install --upgrade pip
# 安装 Sentence Transformers(会自动安装 PyTorch CPU 版)
python -m pip install sentence-transformers# 说明:macOS / Linux 终端安装 Sentence Transformers
# 先升级 pip 到最新版本
python3 -m pip install --upgrade pip
# 安装 Sentence Transformers(会自动安装 PyTorch CPU 版)
python3 -m pip install sentence-transformers网络加速提示:如果从 PyPI 下载较慢,可以使用国内镜像:
- Windows:
python -m pip install sentence-transformers -i https://pypi.tuna.tsinghua.edu.cn/simple- macOS:
python3 -m pip install sentence-transformers -i https://pypi.tuna.tsinghua.edu.cn/simple
2.3 验证安装 #
安装完成后,验证一下是否安装成功。
# -*- coding: utf-8 -*-
# 说明:验证 Sentence Transformers 是否安装成功
# 说明:导入 SentenceTransformer 类
from sentence_transformers import SentenceTransformer
# 说明:尝试加载一个轻量级模型进行测试
# "all-MiniLM-L6-v2" 是一个小型的通用模型,适合快速测试
# 首次运行时会自动下载模型(可能需要一些时间)
print("正在加载模型进行测试...")
model = SentenceTransformer("all-MiniLM-L6-v2")
# 说明:对一个简单的句子进行编码测试
sentence = "这是一个测试句子"
embedding = model.encode(sentence)
# 说明:检查嵌入向量的形状
print(f"安装成功!嵌入向量维度:{embedding.shape}")
print(f"前 5 个维度值:{embedding[:5]}")
# 说明:如果没有报错并输出了维度信息,说明安装成功3. 核心概念 #
在使用 Sentence Transformers 之前,理解几个核心概念会让后续学习更顺利。
3.1 模型(Model) #
模型是用来将文本转换为向量的工具。Sentence Transformers 提供了多种预训练模型:
- 通用模型:如
all-MiniLM-L6-v2,适用于大多数场景 - 多语言模型:支持多种语言
- 专业领域模型:针对特定领域优化
3.2 编码(Encoding) #
编码是将文本转换为向量的过程。输入文本(字符串),输出向量(数字数组)。
3.3 相似度(Similarity) #
通过比较向量之间的距离或相似度,可以判断文本的相似程度。常用的方法是余弦相似度。
3.4 嵌入向量(Embedding) #
嵌入向量是文本的数字表示,通常是一个固定长度的数组。向量的每个维度代表文本的某个特征。
4. 快速体验:加载模型与编码句子 #
让我们通过一个最简单的例子来快速体验 Sentence Transformers 的强大功能。
# -*- coding: utf-8 -*-
# 说明:快速体验 Sentence Transformers 的基本用法
# 说明:导入 SentenceTransformer 类
from sentence_transformers import SentenceTransformer
# 说明:加载一个预训练的模型
# "all-MiniLM-L6-v2" 是一个轻量级的通用模型,具有以下特点:
# - 向量维度:384
# - 速度快,适合学习和测试
# - 支持多种语言(包括中文)
# 首次加载时会自动下载模型(可能需要几分钟)
print("正在加载模型 'all-MiniLM-L6-v2'...")
model = SentenceTransformer("all-MiniLM-L6-v2")
print("模型加载完成!")
# 说明:准备一个示例句子
# 这可以是任何文本,比如一句话、一段话等
sentence = "自然语言处理可以帮助我们理解文本含义"
# 说明:对句子进行编码,将文本转换为向量
# encode() 方法接受字符串或字符串列表
# 返回的是 numpy 数组(numpy.ndarray)
embedding = model.encode(sentence)
# 说明:查看嵌入向量的信息
# shape 属性显示向量的维度(这里应该是 (384,) 表示 384 维向量)
print(f"\n嵌入向量维度:{embedding.shape}")
# 说明:打印向量的前 5 个数值
# 向量中的每个数值都是浮点数,通常在 -1 到 1 之间
print(f"前 5 个维度值:{embedding[:5]}")
# 说明:打印向量的类型
print(f"向量类型:{type(embedding)}")
# 说明:查看向量中数值的范围
import numpy as np
print(f"向量数值范围:[{np.min(embedding):.4f}, {np.max(embedding):.4f}]")运行上面的代码,你会看到:
- 模型下载和加载过程(首次运行)
- 嵌入向量的维度信息(应该是 384)
- 向量的前几个数值
5. 批量编码:处理多个句子 #
在实际应用中,我们通常需要同时处理多条文本。Sentence Transformers 支持批量编码,可以一次性处理多个句子,效率更高。
5.1 批量编码示例 #
# -*- coding: utf-8 -*-
# 说明:演示如何批量编码多个句子
# 说明:导入 SentenceTransformer 类
from sentence_transformers import SentenceTransformer
# 说明:加载模型
# 可以重用同一个模型对象,不需要重复加载
model = SentenceTransformer("all-MiniLM-L6-v2")
# 说明:准备多条句子
# 这是一个字符串列表,每个元素是一个句子
# 在实际场景中,这些句子可能来自文件、数据库或用户输入
sentences = [
"深度学习是人工智能的重要分支",
"我喜欢在周末读技术博客",
"今天的天气非常适合散步",
"Python 是数据科学常用语言"
]
# 说明:批量编码所有句子
# encode() 方法可以接受字符串列表
# 返回的是一个二维 numpy 数组:
# - 行数 = 句子数量(这里是 4)
# - 列数 = 向量维度(这里是 384)
embeddings = model.encode(sentences)
# 说明:查看嵌入矩阵的形状
# shape 返回 (行数, 列数),即 (句子数, 向量维度)
print(f"嵌入矩阵形状:{embeddings.shape}")
print(f"句子数量:{embeddings.shape[0]}")
print(f"向量维度:{embeddings.shape[1]}")
# 说明:访问第一条句子的向量
print(f"\n第一条句子的向量(前 5 维):{embeddings[0][:5]}")
# 说明:遍历所有句子的向量
print("\n所有句子的向量:")
for i, sentence in enumerate(sentences):
print(f"{i+1}. '{sentence}' -> 向量维度:{embeddings[i].shape}")5.2 编码选项 #
encode() 方法支持多种参数,可以优化编码过程。
# -*- coding: utf-8 -*-
# 说明:演示 encode() 方法的常用参数
# 说明:导入 SentenceTransformer
from sentence_transformers import SentenceTransformer
# 说明:加载模型
model = SentenceTransformer("all-MiniLM-L6-v2")
# 说明:准备测试句子
sentences = [
"这是一个测试句子",
"这是另一个测试句子"
]
# 说明:选项1:转换为张量(Tensor)格式
# convert_to_tensor=True 将结果转换为 PyTorch 张量
# 使用张量可以提高后续计算的性能
embeddings_tensor = model.encode(sentences, convert_to_tensor=True)
print(f"张量格式:{type(embeddings_tensor)}")
print(f"张量形状:{embeddings_tensor.shape}")
# 说明:选项2:显示进度条
# show_progress_bar=True 在处理大量数据时显示进度
# 这对于处理成千上万条文本很有用
embeddings_with_progress = model.encode(
sentences,
show_progress_bar=True
)
# 说明:选项3:批量大小控制
# batch_size 控制每次处理多少条文本
# 较大的 batch_size 可以提高速度,但需要更多内存
# 默认值通常是 32,可以根据你的硬件调整
embeddings_batch = model.encode(
sentences,
batch_size=16, # 每次处理 16 条
show_progress_bar=True
)
# 说明:选项4:转换为 numpy 数组(默认行为)
# convert_to_numpy=True 是默认值,返回 numpy 数组
embeddings_numpy = model.encode(
sentences,
convert_to_numpy=True # 显式指定(默认值)
)
print(f"\nNumPy 格式:{type(embeddings_numpy)}")6. 相似度计算:找出相似的文本 #
得到文本的向量表示后,我们可以通过计算向量之间的相似度来判断文本的相似程度。
6.1 余弦相似度 #
余弦相似度是最常用的相似度计算方法,值域通常在 -1 到 1 之间,值越接近 1 表示越相似。
# -*- coding: utf-8 -*-
# 说明:演示如何计算文本之间的相似度
# 说明:导入 SentenceTransformer 和 util 工具
# util 模块提供了相似度计算的便捷函数
from sentence_transformers import SentenceTransformer, util
# 说明:加载模型
model = SentenceTransformer("all-MiniLM-L6-v2")
# 说明:准备示例句子
# 这些句子中有相似的(关于机器学习),也有不相关的(关于披萨)
sentences = [
"我爱机器学习",
"机器学习非常有趣",
"我今天吃了披萨"
]
# 说明:编码所有句子
# convert_to_tensor=True 转换为张量格式,计算相似度时更快
embeddings = model.encode(sentences, convert_to_tensor=True)
# 说明:计算所有句子之间的余弦相似度矩阵
# cos_sim() 函数计算两个向量或向量组之间的余弦相似度
# 返回一个相似度矩阵,矩阵中的每个元素表示对应句子对的相似度
similarity_matrix = util.cos_sim(embeddings, embeddings)
# 说明:打印相似度矩阵
# 矩阵是对称的,对角线上的值都是 1(句子与自己的相似度)
print("相似度矩阵:")
print(similarity_matrix)
# 说明:逐对显示句子之间的相似度
print("\n句子之间的相似度:")
for i in range(len(sentences)):
for j in range(i + 1, len(sentences)):
# 说明:从张量中提取标量值
# .item() 方法将张量中的单个值转换为 Python 的数值类型
score = similarity_matrix[i][j].item()
print(f"'{sentences[i]}' vs '{sentences[j]}' -> 相似度:{score:.4f}")6.2 找到最相似的句子 #
在多个句子中,找到与给定句子最相似的一个或多个句子。
# -*- coding: utf-8 -*-
# 说明:演示如何找到最相似的句子
# 说明:导入必要的库
from sentence_transformers import SentenceTransformer, util
import numpy as np
# 说明:加载模型
model = SentenceTransformer("all-MiniLM-L6-v2")
# 说明:准备候选句子库
candidate_sentences = [
"机器学习是人工智能的重要分支",
"我喜欢在周末读技术博客",
"深度学习依靠神经网络",
"Python 是数据科学常用语言",
"今天的天气非常适合散步"
]
# 说明:准备查询句子
query = "人工智能和机器学习"
# 说明:编码查询句子和所有候选句子
query_embedding = model.encode(query, convert_to_tensor=True)
candidate_embeddings = model.encode(candidate_sentences, convert_to_tensor=True)
# 说明:计算查询句子与所有候选句子的相似度
# cos_sim() 的第一个参数是查询向量,第二个参数是候选向量列表
# 返回的结果中 [0] 表示第一个查询的结果(因为我们只有一个查询)
similarities = util.cos_sim(query_embedding, candidate_embeddings)[0]
# 说明:找到相似度最高的句子
# 使用 argmax 找到相似度最大的索引
best_match_idx = np.argmax(similarities.cpu().numpy())
best_score = similarities[best_match_idx].item()
print(f"查询:'{query}'")
print(f"\n最相似的句子:")
print(f" - {candidate_sentences[best_match_idx]}")
print(f" - 相似度:{best_score:.4f}")
# 说明:找到相似度最高的前 3 个句子
top_k = 3
# 说明:使用 argsort 对相似度进行排序,取最大的 k 个
top_indices = np.argsort(-similarities.cpu().numpy())[:top_k]
print(f"\n相似度最高的前 {top_k} 个句子:")
for idx, rank in enumerate(top_indices, 1):
score = similarities[rank].item()
print(f"{idx}. '{candidate_sentences[rank]}' (相似度:{score:.4f})")余弦相似度说明:余弦相似度衡量的是两个向量在方向上的相似程度,而不是距离。值域范围是 -1 到 1:
- 1:完全相同或语义完全一致
- 接近 1:非常相似
- 0:不相关
- -1:完全相反
7. 语义搜索:构建一个简单的搜索系统 #
语义搜索可以根据意思搜索,而不仅仅是关键词匹配。下面我们构建一个简单的语义搜索系统。
7.1 基本语义搜索 #
# -*- coding: utf-8 -*-
# 说明:演示如何构建一个简单的语义搜索系统
# 说明:导入必要的库
from sentence_transformers import SentenceTransformer, util
import numpy as np
# 说明:加载模型
model = SentenceTransformer("all-MiniLM-L6-v2")
# 说明:准备语料库(待搜索的文档集合)
# 在实际应用中,这些可能来自数据库、文件或 API
corpus = [
"猫咪在沙发上睡觉",
"狗狗在草地上奔跑",
"程序员正在调试代码",
"美食博主在分享菜谱",
"学生正在准备考试"
]
# 说明:准备查询文本(用户的问题)
query = "写代码的人在干什么"
# 说明:编码语料库和查询
# 使用 convert_to_tensor=True 可以提高后续计算速度
corpus_embeddings = model.encode(corpus, convert_to_tensor=True)
query_embedding = model.encode(query, convert_to_tensor=True)
# 说明:计算查询与语料库中每个文档的余弦相似度
# cos_sim() 返回一个张量,[0] 表示第一个查询的结果
cos_scores = util.cos_sim(query_embedding, corpus_embeddings)[0]
# 说明:找到相似度最高的前 top_k 个结果
top_k = min(3, len(corpus)) # 确保不超过语料库的大小
# 说明:使用 argpartition 高效地找到前 top_k 个最大的值
# argpartition 比完整排序更快,因为我们只需要前 k 个
top_results = np.argpartition(-cos_scores.cpu().numpy(), range(top_k))[:top_k]
# 说明:对结果按相似度降序排序
# 先按相似度排序,然后取前 top_k 个
top_results_sorted = sorted(top_results, key=lambda x: cos_scores[x].item(), reverse=True)
# 说明:打印搜索结果
print(f"查询:'{query}'\n")
print(f"找到 {len(top_results_sorted)} 个最相关的结果:\n")
for idx, result_idx in enumerate(top_results_sorted, 1):
score = cos_scores[result_idx].item()
print(f"{idx}. {corpus[result_idx]}")
print(f" 相似度:{score:.4f}\n")7.2 改进版语义搜索 #
下面是一个更完善的语义搜索示例,包含更好的结果展示和错误处理。
# -*- coding: utf-8 -*-
# 说明:改进版语义搜索,包含更好的结果展示
# 说明:导入必要的库
from sentence_transformers import SentenceTransformer, util
import numpy as np
# 说明:定义语义搜索函数
def semantic_search(query: str, corpus: list, model, top_k: int = 3):
"""
执行语义搜索
参数:
query (str): 查询文本
corpus (list): 待搜索的文档列表
model: SentenceTransformer 模型
top_k (int): 返回最相关的结果数量
返回:
list: 包含 (文档, 相似度分数) 的列表
"""
# 说明:检查输入是否为空
if not query or not corpus:
print("错误:查询文本和语料库不能为空")
return []
# 说明:编码查询和语料库
query_embedding = model.encode(query, convert_to_tensor=True)
corpus_embeddings = model.encode(corpus, convert_to_tensor=True)
# 说明:计算相似度
cos_scores = util.cos_sim(query_embedding, corpus_embeddings)[0]
# 说明:找到前 top_k 个最相似的结果
top_k = min(top_k, len(corpus))
top_indices = np.argsort(-cos_scores.cpu().numpy())[:top_k]
# 说明:构造结果列表
results = []
for idx in top_indices:
score = cos_scores[idx].item()
results.append({
"document": corpus[idx],
"score": score,
"rank": len(results) + 1
})
return results
# 说明:主程序入口
if __name__ == "__main__":
# 说明:加载模型
print("正在加载模型...")
model = SentenceTransformer("all-MiniLM-L6-v2")
print("模型加载完成!\n")
# 说明:准备语料库
corpus = [
"猫咪在沙发上睡觉",
"狗狗在草地上奔跑",
"程序员正在调试代码",
"美食博主在分享菜谱",
"学生正在准备考试"
]
# 说明:执行搜索
query = "写代码的人在干什么"
results = semantic_search(query, corpus, model, top_k=3)
# 说明:显示结果
print(f"查询:'{query}'\n")
print("搜索结果:")
print("-" * 60)
for result in results:
print(f"排名 {result['rank']}: {result['document']}")
print(f"相似度:{result['score']:.4f}")
print("-" * 60)8. 性能优化:批量处理与设备选择 #
当需要处理大量文本时,可以使用批处理和 GPU 加速来提高效率。
8.1 批量编码优化 #
# -*- coding: utf-8 -*-
# 说明:演示如何使用批量处理提高编码效率
# 说明:导入必要的库
import time
from sentence_transformers import SentenceTransformer
# 说明:加载模型
model = SentenceTransformer("all-MiniLM-L6-v2")
# 说明:生成大量测试文本
# 在实际场景中,这些文本可能来自文件或数据库
texts = [f"这是第 {i} 条示例文本,用于测试批量编码性能" for i in range(100)]
# 说明:方法1:使用默认批量大小(通常是 32)
print("方法1:使用默认批量大小")
start_time = time.time()
embeddings_default = model.encode(
texts,
show_progress_bar=True # 显示进度条
)
time_default = time.time() - start_time
print(f"耗时:{time_default:.2f} 秒\n")
# 说明:方法2:指定较大的批量大小
# 较大的 batch_size 可以提高速度,但需要更多内存
print("方法2:使用较大的批量大小(batch_size=64)")
start_time = time.time()
embeddings_large_batch = model.encode(
texts,
batch_size=64, # 每次处理 64 条文本
show_progress_bar=True
)
time_large = time.time() - start_time
print(f"耗时:{time_large:.2f} 秒\n")
# 说明:方法3:指定较小的批量大小(适合内存较小的情况)
print("方法3:使用较小的批量大小(batch_size=8)")
start_time = time.time()
embeddings_small_batch = model.encode(
texts,
batch_size=8, # 每次处理 8 条文本
show_progress_bar=True
)
time_small = time.time() - start_time
print(f"耗时:{time_small:.2f} 秒\n")
# 说明:比较结果是否一致
print(f"结果一致性检查:")
print(f"默认批量 vs 大批量:{embeddings_default.shape == embeddings_large_batch.shape}")
print(f"默认批量 vs 小批量:{embeddings_default.shape == embeddings_small_batch.shape}")8.2 GPU 加速 #
如果有 GPU 可用,可以显著提高处理速度。
# -*- coding: utf-8 -*-
# 说明:演示如何使用 GPU 加速(如果有可用的 GPU)
# 说明:导入 torch 库用于检测 GPU
import torch
from sentence_transformers import SentenceTransformer
# 说明:检测是否有可用的 GPU
# cuda.is_available() 返回 True 表示系统有可用的 NVIDIA GPU
# 注意:macOS 上的 M 系列芯片使用 MPS(Metal Performance Shaders),不是 CUDA
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"当前使用设备:{device}")
# 说明:如果没有 GPU,会使用 CPU(速度会慢一些,但功能完全正常)
if device == "cpu":
print("未检测到 GPU,将使用 CPU 运行(速度较慢)")
# 说明:加载模型到指定设备
# device 参数指定模型运行在哪个设备上
model = SentenceTransformer("all-MiniLM-L6-v2", device=device)
# 说明:准备测试文本
texts = [f"示例文本 {i}" for i in range(100)]
# 说明:编码时指定设备
# device 参数确保编码过程在指定设备上执行
embeddings = model.encode(
texts,
batch_size=32,
show_progress_bar=True,
device=device # 明确指定设备
)
print(f"\n编码完成,得到 {embeddings.shape[0]} 个嵌入向量")
print(f"每个向量维度:{embeddings.shape[1]}")9. 实战案例:文档推荐系统 #
下面是一个完整的实战案例,封装成一个文档推荐类,可以根据查询找到最相似的文档。
# -*- coding: utf-8 -*-
# 说明:实战案例 - 文档推荐系统
# 封装一个完整的文档相似度推荐类
# 说明:导入必要的库
from sentence_transformers import SentenceTransformer, util
import numpy as np
# 说明:定义文档推荐类
class DocumentRecommender:
"""
文档推荐系统
功能:
- 添加文档到系统
- 根据查询文本推荐最相似的文档
"""
# 说明:初始化方法
def __init__(self, model_name: str = "all-MiniLM-L6-v2"):
"""
初始化文档推荐系统
参数:
model_name (str): 要使用的模型名称,默认为 "all-MiniLM-L6-v2"
"""
# 说明:加载模型
print(f"正在加载模型:{model_name}...")
self.model = SentenceTransformer(model_name)
print("模型加载完成!")
# 说明:初始化文档列表和嵌入向量
self.documents = [] # 存储文档文本
self.doc_embeddings = None # 存储文档的嵌入向量
# 说明:添加文档的方法
def add_documents(self, docs):
"""
添加文档到推荐系统
参数:
docs (list): 文档列表,每个元素是一个字符串
"""
# 说明:将新文档添加到文档列表
self.documents.extend(docs)
# 说明:对所有文档重新编码
# 每次添加新文档后,需要重新编码所有文档(包括新添加的)
print(f"正在编码 {len(self.documents)} 条文档...")
self.doc_embeddings = self.model.encode(
self.documents,
convert_to_tensor=True, # 使用张量格式,提高计算速度
show_progress_bar=True
)
print("文档编码完成!")
# 说明:推荐方法
def recommend(self, query: str, top_k: int = 3):
"""
根据查询文本推荐最相似的文档
参数:
query (str): 查询文本
top_k (int): 返回最相似的文档数量,默认为 3
返回:
list: 包含 (文档, 相似度分数) 的元组列表
"""
# 说明:检查是否有文档
if not self.documents:
print("错误:系统中没有文档,请先添加文档")
return []
# 说明:编码查询文本
query_emb = self.model.encode(query, convert_to_tensor=True)
# 说明:计算查询与所有文档的相似度
# cos_sim() 返回一个张量,[0] 表示第一个查询的结果
scores = util.cos_sim(query_emb, self.doc_embeddings)[0]
# 说明:找到相似度最高的 top_k 个文档
# argsort 对相似度进行排序,取最大的 top_k 个
# 使用负数是因为 argsort 默认是升序,我们要降序
top_indices = np.argsort(-scores.cpu().numpy())[:top_k]
# 说明:构造结果列表
# 每个元素是一个元组:(文档文本, 相似度分数)
results = []
for idx in top_indices:
doc = self.documents[idx]
score = float(scores[idx]) # 将张量中的值转换为 Python 浮点数
results.append((doc, score))
return results
# 说明:获取统计信息
def get_stats(self):
"""
获取系统的统计信息
返回:
dict: 包含文档数量的字典
"""
return {
"文档数量": len(self.documents)
}
# 说明:主程序入口,演示如何使用
if __name__ == "__main__":
# 说明:创建推荐系统实例
rec = DocumentRecommender()
# 说明:添加文档到系统
docs = [
"机器学习是人工智能的一个分支",
"我喜欢做饭并分享美食",
"Python 是数据分析常用语言",
"深度学习依靠神经网络"
]
rec.add_documents(docs)
# 说明:执行查询和推荐
query = "如何入门深度学习"
print(f"\n查询:'{query}'")
print("\n推荐结果:")
print("-" * 60)
results = rec.recommend(query, top_k=2)
for idx, (doc, score) in enumerate(results, 1):
print(f"{idx}. {doc}")
print(f" 相似度:{score:.4f}")
print("-" * 60)
# 说明:显示统计信息
print(f"\n系统统计:{rec.get_stats()}")10. 使用中文模型 #
默认模型对中文的支持可能不够好。如果需要更好的中文效果,可以使用专门针对中文优化的模型。
# -*- coding: utf-8 -*-
# 说明:演示如何使用中文优化的模型
# 说明:导入 SentenceTransformer
from sentence_transformers import SentenceTransformer, util
# 说明:加载中文优化的模型
# "shibing624/text2vec-base-chinese" 是一个专门针对中文优化的模型
# 首次运行时会自动下载模型
print("正在加载中文模型...")
model = SentenceTransformer("shibing624/text2vec-base-chinese")
print("模型加载完成!")
# 说明:准备中文测试文本
chinese_texts = [
"机器学习是人工智能的重要分支",
"深度学习依靠神经网络",
"自然语言处理可以理解文本语义",
"计算机视觉可以识别图像内容"
]
# 说明:编码中文文本
embeddings = model.encode(chinese_texts, show_progress_bar=True)
# 说明:测试相似度
query = "人工智能和机器学习"
query_embedding = model.encode(query, convert_to_tensor=True)
corpus_embeddings = model.encode(chinese_texts, convert_to_tensor=True)
# 说明:计算相似度
scores = util.cos_sim(query_embedding, corpus_embeddings)[0]
# 说明:显示结果
print(f"\n查询:'{query}'")
print("\n相似度结果:")
for text, score in zip(chinese_texts, scores):
print(f" {text}: {score:.4f}")模型选择建议:
- 通用场景:使用
all-MiniLM-L6-v2(速度快,效果不错)- 中文场景:使用
shibing624/text2vec-base-chinese(中文效果更好)- 多语言场景:使用
paraphrase-multilingual-MiniLM-L12-v2(支持多种语言)
11. 常见问题与排查 #
在使用 Sentence Transformers 时,可能会遇到一些常见问题。本节提供解决方案。
11.1 模型下载慢或失败 #
问题:首次加载模型时下载速度很慢或失败。
解决方案:
# -*- coding: utf-8 -*-
# 说明:演示如何使用镜像站点加速模型下载
# 说明:设置环境变量使用镜像站点
# 在加载模型之前设置这个环境变量
import os
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
# 说明:然后再加载模型
from sentence_transformers import SentenceTransformer
# 说明:现在加载模型会使用镜像站点
model = SentenceTransformer("all-MiniLM-L6-v2")
print("模型加载完成!")或者使用命令行的方式:
# Windows PowerShell:设置环境变量后运行 Python 脚本
$env:HF_ENDPOINT="https://hf-mirror.com"
python your_script.py# macOS / Linux 终端:设置环境变量后运行 Python 脚本
export HF_ENDPOINT=https://hf-mirror.com
python3 your_script.py11.2 内存不足 #
问题:处理大量文本时内存不足。
解决方案:
# -*- coding: utf-8 -*-
# 说明:演示如何通过减小批量大小来降低内存使用
# 说明:导入 SentenceTransformer
from sentence_transformers import SentenceTransformer
# 说明:加载模型
model = SentenceTransformer("all-MiniLM-L6-v2")
# 说明:准备大量文本
texts = [f"文本 {i}" for i in range(10000)]
# 说明:使用较小的批量大小
# 较小的 batch_size 会使用更少的内存,但可能稍微慢一些
embeddings = model.encode(
texts,
batch_size=8, # 减小批量大小(默认可能是 32)
show_progress_bar=True
)
print(f"编码完成,共 {embeddings.shape[0]} 条文本")11.3 中文效果不理想 #
问题:使用默认模型处理中文时,效果不够好。
解决方案:使用专门的中文模型(参考第 10 节)。
11.4 处理大量数据时的优化 #
问题:处理成千上万条文本时速度慢。
解决方案:
# -*- coding: utf-8 -*-
# 说明:演示如何优化大量数据的处理
# 说明:导入必要的库
from sentence_transformers import SentenceTransformer
import time
# 说明:加载模型
model = SentenceTransformer("all-MiniLM-L6-v2")
# 说明:准备大量数据
large_texts = [f"这是第 {i} 条文本,用于测试性能优化" for i in range(1000)]
# 说明:优化策略1:增大批量大小(如果内存允许)
print("策略1:增大批量大小")
start = time.time()
embeddings1 = model.encode(
large_texts,
batch_size=64, # 增大批量大小
show_progress_bar=True
)
time1 = time.time() - start
print(f"耗时:{time1:.2f} 秒\n")
# 说明:优化策略2:使用多线程(如果 CPU 核心数足够)
print("策略2:使用多线程编码")
start = time.time()
embeddings2 = model.encode(
large_texts,
batch_size=32,
show_progress_bar=True,
# 注意:某些版本的 sentence-transformers 可能不支持此参数
# 请根据实际情况调整
)
time2 = time.time() - start
print(f"耗时:{time2:.2f} 秒")
# 说明:策略3:缓存已编码的结果
# 如果某些文档不会改变,可以先编码并保存,避免重复计算
print("\n策略3:缓存编码结果")
# 这里只是示例,实际使用时可以将结果保存到文件或数据库
# 例如:使用 numpy.save() 保存,使用 numpy.load() 加载11.5 版本兼容问题 #
问题:不同库版本之间可能不兼容。
解决方案:
# Windows PowerShell:升级到最新稳定版本
python -m pip install --upgrade torch transformers sentence-transformers# macOS / Linux 终端:升级到最新稳定版本
python3 -m pip install --upgrade torch transformers sentence-transformers