模型概述
模型特點
模型能力
使用案例
🚀 USER-base
USER-base(面向俄語的通用句子編碼器,Universal Sentence Encoder for Russian)是一個基於 sentence-transformer 的模型,專門用於提取俄語句子的嵌入向量。它能將句子和段落映射到一個 768 維的密集向量空間,可用於聚類或語義搜索等任務。該模型基於 deepvk/deberta-v1-base
進行初始化,並針對俄語進行了專門訓練,未對其在其他語言上的性能進行評估。
🚀 快速開始
使用該模型,你需要安裝 sentence-transformers
:
pip install -U sentence-transformers
然後,你可以按以下方式使用該模型:
from sentence_transformers import SentenceTransformer
queries = [
"Когда был спущен на воду первый миноносец «Спокойный»?",
"Есть ли нефть в Удмуртии?"
]
passages = [
"Спокойный (эсминец)\nЗачислен в списки ВМФ СССР 19 августа 1952 года.",
"Нефтепоисковые работы в Удмуртии были начаты сразу после Второй мировой войны в 1945 году и продолжаются по сей день. Добыча нефти началась в 1967 году."
]
model = SentenceTransformer("deepvk/USER-base")
# Prompt should be specified according to the task (either 'query' or 'passage').
passage_embeddings = model.encode(passages, normalize_embeddings=True, prompt_name='passage')
# For tasks other than retrieval, you can simply use the `query` prompt, which is set by default.
query_embeddings = model.encode(queries, normalize_embeddings=True)
不過,你也可以直接使用 transformers
調用該模型:
import torch.nn.functional as F
from torch import Tensor, inference_mode
from transformers import AutoTokenizer, AutoModel
def average_pool(
last_hidden_states: Tensor,
attention_mask: Tensor
) -> Tensor:
last_hidden = last_hidden_states.masked_fill(
~attention_mask[..., None].bool(), 0.0
)
return last_hidden.sum(dim=1) / attention_mask.sum(dim=1)[..., None]
# You should manually add prompts when using the model directly. Each input text should start with "query: " or "passage: ".
# For tasks other than retrieval, you can simply use the "query: " prefix.
input_texts = [
"query: Когда был спущен на воду первый миноносец «Спокойный»?",
"query: Есть ли нефть в Удмуртии?",
"passage: Спокойный (эсминец)\nЗачислен в списки ВМФ СССР 19 августа 1952 года.",
"passage: Нефтепоисковые работы в Удмуртии были начаты сразу после Второй мировой войны в 1945 году и продолжаются по сей день. Добыча нефти началась в 1967 году."
]
tokenizer = AutoTokenizer.from_pretrained("deepvk/USER-base")
model = AutoModel.from_pretrained("deepvk/USER-base")
batch_dict = tokenizer(
input_texts, padding=True, truncation=True, return_tensors="pt"
)
with inference_mode():
outputs = model(**batch_dict)
embeddings = average_pool(
outputs.last_hidden_state, batch_dict["attention_mask"]
)
embeddings = F.normalize(embeddings, p=2, dim=1)
# Scores for query-passage
scores = (embeddings[:2] @ embeddings[2:].T) * 100
# [[55.86, 30.95],
# [22.82, 59.46]]
print(scores.round(decimals=2))
⚠️ 重要提示
每個輸入文本都應以 "query: " 或 "passage: " 開頭。對於檢索以外的任務,你可以直接使用 "query: " 前綴。
✨ 主要特性
- 專門為俄語設計,能有效提取俄語句子的嵌入向量。
- 將句子和段落映射到 768 維的密集向量空間,適用於聚類和語義搜索等任務。
📦 安裝指南
使用該模型,你需要安裝 sentence-transformers
:
pip install -U sentence-transformers
💻 使用示例
基礎用法
from sentence_transformers import SentenceTransformer
queries = [
"Когда был спущен на воду первый миноносец «Спокойный»?",
"Есть ли нефть в Удмуртии?"
]
passages = [
"Спокойный (эсминец)\nЗачислен в списки ВМФ СССР 19 августа 1952 года.",
"Нефтепоисковые работы в Удмуртии были начаты сразу после Второй мировой войны в 1945 году и продолжаются по сей день. Добыча нефти началась в 1967 году."
]
model = SentenceTransformer("deepvk/USER-base")
# Prompt should be specified according to the task (either 'query' or 'passage').
passage_embeddings = model.encode(passages, normalize_embeddings=True, prompt_name='passage')
# For tasks other than retrieval, you can simply use the `query` prompt, which is set by default.
query_embeddings = model.encode(queries, normalize_embeddings=True)
高級用法
import torch.nn.functional as F
from torch import Tensor, inference_mode
from transformers import AutoTokenizer, AutoModel
def average_pool(
last_hidden_states: Tensor,
attention_mask: Tensor
) -> Tensor:
last_hidden = last_hidden_states.masked_fill(
~attention_mask[..., None].bool(), 0.0
)
return last_hidden.sum(dim=1) / attention_mask.sum(dim=1)[..., None]
# You should manually add prompts when using the model directly. Each input text should start with "query: " or "passage: ".
# For tasks other than retrieval, you can simply use the "query: " prefix.
input_texts = [
"query: Когда был спущен на воду первый миноносец «Спокойный»?",
"query: Есть ли нефть в Удмуртии?",
"passage: Спокойный (эсминец)\nЗачислен в списки ВМФ СССР 19 августа 1952 года.",
"passage: Нефтепоисковые работы в Удмуртии были начаты сразу после Второй мировой войны в 1945 году и продолжаются по сей день. Добыча нефти началась в 1967 году."
]
tokenizer = AutoTokenizer.from_pretrained("deepvk/USER-base")
model = AutoModel.from_pretrained("deepvk/USER-base")
batch_dict = tokenizer(
input_texts, padding=True, truncation=True, return_tensors="pt"
)
with inference_mode():
outputs = model(**batch_dict)
embeddings = average_pool(
outputs.last_hidden_state, batch_dict["attention_mask"]
)
embeddings = F.normalize(embeddings, p=2, dim=1)
# Scores for query-passage
scores = (embeddings[:2] @ embeddings[2:].T) * 100
# [[55.86, 30.95],
# [22.82, 59.46]]
print(scores.round(decimals=2))
🔧 技術細節
訓練詳情
模型訓練旨在遵循 bge-base-en
的訓練算法,並在此基礎上進行了改進:
- 初始化:基於
deepvk/deberta-v1-base
進行初始化。 - 第一階段:在 mMarco 語料庫 的俄語部分上進行弱監督對比預訓練。
- 第二階段:基於數據對稱性對兩個不同的模型進行有監督微調,然後通過
LM-Cocktail
進行合併:- 修改指令設計,簡化多語言方法,以便更輕鬆地進行推理。對於對稱數據
(S1, S2)
,使用指令"query: S1"
和"query: S2"
;對於非對稱數據,使用"query: S1"
和"passage: S2"
。 - 由於對數據進行了分割,可以額外對對稱模型應用 AnglE 損失,以提高對稱任務的性能。
- 最後,將兩個模型合併,使用
LM-Cocktail
調整合並權重,生成最終模型 USER。
- 修改指令設計,簡化多語言方法,以便更輕鬆地進行推理。對於對稱數據
數據集
在模型開發過程中,額外收集了兩個數據集:deepvk/ru-HNP
和 deepvk/ru-WANLI
。
對稱數據集 | 規模 | 非對稱數據集 | 規模 |
---|---|---|---|
AllNLI | 282 644 | MIRACL | 10 000 |
MedNLI | 3 699 | MLDR | 1 864 |
RCB | 392 | Lenta | 185 972 |
Terra | 1 359 | Mlsum | 51 112 |
Tapaco | 91 240 | Mr-TyDi | 536 600 |
Opus100 | 1 000 000 | Panorama | 11 024 |
BiblePar | 62 195 | PravoIsrael | 26 364 |
RudetoxifierDataDetox | 31 407 | Xlsum | 124 486 |
RuParadetox | 11 090 | Fialka-v1 | 130 000 |
deepvk/ru-WANLI | 35 455 | RussianKeywords | 16 461 |
deepvk/ru-HNP | 500 000 | Gazeta | 121 928 |
Gsm8k-ru | 7 470 | ||
DSumRu | 27 191 | ||
SummDialogNews | 75 700 |
總正樣本對:3,352,653
總負樣本對:792,644(來自 AIINLI、MIRACL、deepvk/ru-WANLI、deepvk/ru-HNP 的負樣本對)
對於所有有標籤的數據集,僅使用其訓練集進行微調。對於 Gazeta、Mlsum、Xlsum 數據集,將 (標題/文本) 和 (標題/摘要) 對組合起來,用作非對稱數據。
AllNLI
是 SNLI、MNLI 和 ANLI 的俄語翻譯組合。
實驗
- 基準選擇:選擇
encodechka
排行榜上的當前頂級模型作為基線。此外,在MTEB
的俄語子集上對模型進行評估,該子集包含 10 個任務。由於計算資源過多,無法在某些 MTEB 任務(特別是聚類任務)上驗證 bge-m3。除了這兩個基準外,還在MIRACL
上對模型進行了評估。 - 實驗環境:所有實驗均使用 NVIDIA TESLA A100 40 GB GPU 進行。使用每個任務官方倉庫中的驗證腳本。
模型 | 大小(不含嵌入) | Encodechka (平均得分) | MTEB (俄語平均得分) | Miracl (Recall@100) |
---|---|---|---|---|
bge-m3 |
303 | 0.786 | 0.694 | 0.959 |
multilingual-e5-large |
303 | 0.78 | 0.665 | 0.927 |
USER (本模型) |
85 | 0.772 | 0.666 | 0.763 |
paraphrase-multilingual-mpnet-base-v2 |
85 | 0.76 | 0.625 | 0.149 |
multilingual-e5-base |
85 | 0.756 | 0.645 | 0.915 |
LaBSE-en-ru |
85 | 0.74 | 0.599 | 0.327 |
sn-xlm-roberta-base-snli-mnli-anli-xnli |
85 | 0.74 | 0.593 | 0.08 |
模型大小已列出,較大的模型在視覺上與其他模型有所區別。指標中的絕對領先者用粗體突出顯示,同規模模型中的領先者用下劃線標註。
本模型在 Encodechka 和 MTEB 上均優於所有其他同規模模型。鑑於該模型在檢索任務上相對於現有解決方案略有不足,未來研究將致力於解決這一問題。
📚 詳細文檔
常見問題解答
是否需要在輸入文本中添加 "query: " 和 "passage: " 前綴? 是的,模型是按此方式進行訓練的,否則會出現性能下降。以下是一些經驗法則:
- 對於非對稱任務(如開放問答中的段落檢索、臨時信息檢索),相應地使用
"query: "
和"passage: "
。 - 對於對稱任務(如語義相似度、雙語挖掘、釋義檢索),使用
"query: "
前綴。 - 如果你想將嵌入向量用作特徵(如線性探測分類、聚類),使用
"query: "
前綴。
引用
@misc{deepvk2024user,
title={USER: Universal Sentence Encoder for Russian},
author={Malashenko, Boris and Zemerov, Anton and Spirin, Egor},
url={https://huggingface.co/datasets/deepvk/USER-base},
publisher={Hugging Face}
year={2024},
}
📄 許可證
本項目採用 Apache-2.0 許可證。







