藏语自然语言处理入门 - 4 找相似的句子

句向量与相似度:给一句话找"近义例句"

本节要做的三件小事

  1. sentences.txt 里的每句话变成一个"向量"(一串数字)。
  2. 用"余弦相似度"比较两句话有多像。
  3. 做一个Top-K 例句检索小工具:输入一句,返回最接近的几句。

做完你会得到:

  • embeddings.npy:每句的句向量(后续可复用)。
  • similar_examples.py:给定句子,找 Top-K 相似例句的脚本。
  • sim_results.txt(示例输出):你查过的结果记录。

小贴士:本课需要下载一个多语句向量模型(体积较大)。如果当前环境网络不方便,可先看懂流程与代码,改天在网络好时跑一下。


0. 准备

bash 复制代码
pip install sentence-transformers numpy pandas

模型选择(二选一):

  • 更准sentence-transformers/LaBSE(覆盖语种多,含藏语;体积较大)
  • 更轻 (可临时用):paraphrase-multilingual-MiniLM-L12-v2(更小更快,但对藏语可能略弱)

我会在代码里给出 MODEL_NAME,默认用 LaBSE;你也可以换成 MiniLM 版本试试。


1) 一次性向量化所有句子

把下面保存为 build_embeddings.py,放在和 sentences.txt 同目录下运行。

python 复制代码
# build_embeddings.py
# 功能:读取 sentences.txt -> 计算句向量 -> 保存 embeddings.npy 和 sentences_index.csv

from pathlib import Path
import numpy as np
from sentence_transformers import SentenceTransformer

SENTS_FILE = "sentences.txt"
MODEL_NAME = "sentence-transformers/LaBSE"  # 或 "paraphrase-multilingual-MiniLM-L12-v2"

def normalize(vectors: np.ndarray) -> np.ndarray:
    # L2 归一化,便于用点积近似余弦相似度
    norms = np.linalg.norm(vectors, axis=1, keepdims=True) + 1e-12
    return vectors / norms

def main():
    sents = [s.strip() for s in Path(SENTS_FILE).read_text(encoding="utf-8").splitlines() if s.strip()]
    if not sents:
        raise SystemExit("❌ sentences.txt 为空,请先完成前几课。")

    print(f"📦 加载模型:{MODEL_NAME}")
    model = SentenceTransformer(MODEL_NAME)

    print(f"🔢 计算向量(共 {len(sents)} 句)...")
    emb = model.encode(sents, batch_size=32, convert_to_numpy=True, normalize_embeddings=True)
    # 若你的模型没有自带 normalize_embeddings,可以改为: emb = normalize(emb)

    np.save("embeddings.npy", emb)
    Path("sentences_index.csv").write_text("\n".join(sents), encoding="utf-8")

    print("✅ 已保存:embeddings.npy / sentences_index.csv")

if __name__ == "__main__":
    main()

运行:

bash 复制代码
python build_embeddings.py

输出文件:

  • embeddings.npy:形状约为 [句子数, 向量维度]
  • sentences_index.csv:和向量同序的原始句子。

2) 近义例句检索

把下面保存为 similar_examples.py。它会读取上一步的 embeddings.npysentences_index.csv,然后对你输入的句子做检索。

python 复制代码
# similar_examples.py
# 用法示例:
#   python similar_examples.py --q "ཁྱེད་ལ་བཀྲ་ཤིས།" --k 5
# 输出:Top-K 相似句及相似度

import argparse
import numpy as np
from pathlib import Path
from sentence_transformers import SentenceTransformer, util

MODEL_NAME = "sentence-transformers/LaBSE"  # 或 "paraphrase-multilingual-MiniLM-L12-v2"

def load_corpus():
    sents = [s.strip() for s in Path("sentences_index.csv").read_text(encoding="utf-8").splitlines() if s.strip()]
    emb = np.load("embeddings.npy")
    if len(sents) != emb.shape[0]:
        raise SystemExit("❌ 句子数量与向量行数不一致,请重新构建。")
    return sents, emb

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--q", type=str, required=True, help="查询句子(藏文)")
    parser.add_argument("--k", type=int, default=5, help="返回前K条")
    args = parser.parse_args()

    sents, emb = load_corpus()
    print(f"📦 加载模型:{MODEL_NAME}")
    model = SentenceTransformer(MODEL_NAME)

    # 编码查询句(已做归一化,余弦相似度=点积)
    q_emb = model.encode([args.q], convert_to_numpy=True, normalize_embeddings=True)[0]

    # 相似度(向量点积)并排序
    scores = emb @ q_emb  # shape: [N]
    idx = np.argsort(-scores)[:args.k]

    lines = []
    for rank, i in enumerate(idx, 1):
        lines.append(f"[Top{rank}] score={scores[i]:.4f}\n{sents[i]}\n")

    out = "\n".join(lines)
    Path("sim_results.txt").write_text(out, encoding="utf-8")
    print(out)
    print("✅ 结果已保存:sim_results.txt")

if __name__ == "__main__":
    main()

试运行:

bash 复制代码
python similar_examples.py --q "ཁྱེད་ལ་བཀྲ་ཤིས།" --k 5

你会看到最接近的 5 句(通常是各种问候、祝福类句子)。


3) 代码"人话讲解"

  • 句向量:把一句话翻译成一个"坐标点"(比如 768 维),相似的句子会靠得更近。
  • 归一化 :把向量长度调成 1,这样点积≈余弦相似度,计算更快。
  • 相似度排序:对所有句子算分数,最高的前 K 条就是"近义例句"。
  • 缓存:向量只算一次保存,下次直接用,速度飞起。

4) 自检清单

  • embeddings.npysentences_index.csv 一一对应(行数要相等)。
  • 查询的句子是藏文 Unicode(不是图片/不是转写)。
  • 返回的 Top 结果读起来确实接近(同一话题、同一语气)。

5) 小任务

任务A(必做) :把 similar_examples.py 包一层简单函数,做个**"课堂查询"**:

  • 输入:一个词或短句;
  • 输出:Top 5 相似句;
  • 额外:把相似度 < 0.5 的结果过滤掉(避免"牵强相似")。

任务B(可选):做一个**"去重"**小规则:如果返回的句子同一行在原文里重复多次,只保留一次(可以按句子文本去重)。

任务C(可选) :把 --q 改成从文件读取 (比如 queries.txt 每行一个查询),一次性批量生成结果。


6) 常见小坑(快速排雷)

  • 模型下载太大/太慢?

    先跑小模型 paraphrase-multilingual-MiniLM-L12-v2 验证流程;等网络好再换回 LaBSE 做最终检索。

  • 结果不稳定?

    语料太短时很正常。多加几段同主题的句子,或先回第1--3课把清洗/停用词做好。

  • 中文/英文混在里面?

    句向量是多语的,一般也能"感觉"相似,但这门课我们以藏文主语料为主,更稳。

  • 返回了一些"太像的句子"(几乎重复)?

    检索前先对 sentences.txt 去重;或者在返回阶段做"文本去重"。


7) 本课小结

  • 我们把"句子 → 向量 → 相似度"这一条链路跑通了;
  • 以后你可以把这套向量直接复用到:聚类、主题分组、跨语检索
  • 这一步是"让机器感受语义"的关键基础。
相关推荐
北海道浪子12 分钟前
[免费送$1000]ClaudeCode、Codex等AI模型在开发中的使用
前端·人工智能·后端
福客AI23 分钟前
电商智能客服机器人:客服的服务革新之路
人工智能·机器人
CoderIsArt34 分钟前
CORDIC三角计算技术
人工智能·算法·机器学习
taxunjishu35 分钟前
Ethernet/ip 转 Modbus RTU 驱动,罗克韦尔 PLC 与华为逆变器打造光伏电站智能监控典范
人工智能·物联网·自动化·区块链
Alex艾力的IT数字空间37 分钟前
基于PyTorch和CuPy的GPU并行化遗传算法实现
数据结构·人工智能·pytorch·python·深度学习·算法·机器学习
却道天凉_好个秋1 小时前
OpenCV(十三):通道的分离与合并
人工智能·opencv·计算机视觉
七宝大爷1 小时前
NVIDIA Blackwell Ultra GB300深度解析:AI芯片性能的新巅峰
人工智能·gpu·gb300
鲸鱼在dn1 小时前
大语言模型的后训练与“灾难性遗忘”问题——李宏毅2025大模型第六讲笔记
人工智能·笔记·语言模型
滑水滑成滑头2 小时前
**标题:发散创新:智能交通系统的深度探究与实现**摘要:本文将详细
java·人工智能·python
海云安2 小时前
海云安入选安全牛《企业级AI大模型落地实战技术应用指南(2025版)》优秀案例
人工智能·安全