Модель для расчетов эмбеддингов предложений на русском и английском языках получена методом дистилляции эмбеддингов
ai-forever/FRIDA (размер эмбеддингов - 1536, слоёв - 24) в
sergeyzh/LaBSE-ru-turbo (размер эмбеддингов - 768, слоёв - 12). Основной режим использования FRIDA - CLS pooling заменен на mean pooling. Каких-либо других изменений поведения модели не производилось. Дистиляция выполнена в максимально возможном объеме - эмбеддинги русских и английских предложений, работа префиксов.
Размер контекста модели соответствует FRIDA - 512 токенов.
Все префиксы унаследованы от FRIDA.
Оптимальный (обеспечивающий средние результаты) префикс для большинства задач - "categorize_entailment: " прописан по умолчанию в
config_sentence_transformers.json
Перечень используемых префиксов и их влияние на оценки модели в
encodechka:
Оценки модели на бенчмарке
ruMTEB:
1import torch
2import torch.nn.functional as F
3from transformers import AutoTokenizer, AutoModel
4
5
6def pool(hidden_state, mask, pooling_method="mean"):
7 if pooling_method == "mean":
8 s = torch.sum(hidden_state * mask.unsqueeze(-1).float(), dim=1)
9 d = mask.sum(axis=1, keepdim=True).float()
10 return s / d
11 elif pooling_method == "cls":
12 return hidden_state[:, 0]
13
14inputs = [
15 #
16 "paraphrase: В Ярославской области разрешили работу бань, но без посетителей",
17 "categorize_entailment: Женщину доставили в больницу, за ее жизнь сейчас борются врачи.",
18 "search_query: Сколько программистов нужно, чтобы вкрутить лампочку?",
19 #
20 "paraphrase: Ярославским баням разрешили работать без посетителей",
21 "categorize_entailment: Женщину спасают врачи.",
22 "search_document: Чтобы вкрутить лампочку, требуется три программиста: один напишет программу извлечения лампочки, другой — вкручивания лампочки, а третий проведет тестирование."
23]
24
25tokenizer = AutoTokenizer.from_pretrained("sergeyzh/BERTA")
26model = AutoModel.from_pretrained("sergeyzh/BERTA")
27
28tokenized_inputs = tokenizer(inputs, max_length=512, padding=True, truncation=True, return_tensors="pt")
29
30with torch.no_grad():
31 outputs = model(**tokenized_inputs)
32
33embeddings = pool(
34 outputs.last_hidden_state,
35 tokenized_inputs["attention_mask"],
36 pooling_method="mean"
37)
38
39embeddings = F.normalize(embeddings, p=2, dim=1)
40sim_scores = embeddings[:3] @ embeddings[3:].T
41print(sim_scores.diag().tolist())
42# [0.9530372023582458, 0.866746723651886, 0.7839133143424988]
43# [0.9360030293464661, 0.8591322302818298, 0.728583037853241] - FRIDA
1from sentence_transformers import SentenceTransformer
2
3# loads model with mean pooling
4model = SentenceTransformer("sergeyzh/BERTA")
5
6paraphrase = model.encode(["В Ярославской области разрешили работу бань, но без посетителей", "Ярославским баням разрешили работать без посетителей"], prompt="paraphrase: ")
7print(paraphrase[0] @ paraphrase[1].T)
8# 0.9530372
9# 0.9360032 - FRIDA
10
11categorize_entailment = model.encode(["Женщину доставили в больницу, за ее жизнь сейчас борются врачи.", "Женщину спасают врачи."], prompt="categorize_entailment: ")
12print(categorize_entailment[0] @ categorize_entailment[1].T)
13# 0.8667469
14# 0.8591322 - FRIDA
15
16query_embedding = model.encode("Сколько программистов нужно, чтобы вкрутить лампочку?", prompt="search_query: ")
17document_embedding = model.encode("Чтобы вкрутить лампочку, требуется три программиста: один напишет программу извлечения лампочки, другой — вкручивания лампочки, а третий проведет тестирование.", prompt="search_document: ")
18print(query_embedding @ document_embedding.T)
19# 0.7839136
20# 0.7285831 - FRIDA