请问下:该模型返回的张量不是定长的
#16
by
Ark0810
- opened
我看到该模型返回的张量会根据词的数量返回(n,768)那么这种不定长向量会影响余弦相似度的计算吗,对向量检索的准确率有没有影响,是否需要padding 0
不会呀,只会返回定长的向量,如果是一个 batch , 就是 batch_size * 768 的向量。如果你那边的代码返回的是不定长的,可以把代码贴一下,我看看是怎么回事。
加载模型
tokenizer = AutoTokenizer.from_pretrained("moka-ai/m3e-base")
model = AutoModel.from_pretrained("moka-ai/m3e-base")
# 定义文本
text = "你好"
# 转成tensor输入
inputs = tokenizer(text, return_tensors="pt")
input_ids = inputs["input_ids"]
attention_mask = inputs["attention_mask"]
token_type_ids = inputs["token_type_ids"]
# 模型推理
with torch.no_grad():
outputs = model(input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids)
# 获取向量表示
embeddings = outputs.last_hidden_state[0]
res = embeddings.numpy()
print(res)
hi,似乎不应该直接使用 last_hidden_state
,借助sentence transformer包可以更方便地得到pooling后的embedding
可以给个python示例吗
就是直接使用 sentence-transformers
这个 Python 包,以下是一个示例,更多功能可以查阅相关文档
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('moka-ai/m3e-base')
# str -> tensor
text = 'hello world'
embedding = model.encode(text)
print(embedding.shape)
# a list of strings -> a list of tensors
texts = ['hello world', 'test embeddings']
embeddings = model.encode(texts)
for e in embeddings:
print(e.shape)
This comment has been hidden
OK 多谢了, 我查到同样可以这样pooling
import torch
pooler = torch.mean(outputs.last_hidden_state, 1)
可以的,m3e 模型使用的方法是将所有 token embedding 向量作平均,在 sentence-transformers
这个包里可以找到相关源码,是使用 pytorch 实现的
if self.pooling_mode_mean_tokens or self.pooling_mode_mean_sqrt_len_tokens:
input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
sum_embeddings = torch.sum(token_embeddings * input_mask_expanded, 1)
#If tokens are weighted (by WordWeights layer), feature 'token_weights_sum' will be present
if 'token_weights_sum' in features:
sum_mask = features['token_weights_sum'].unsqueeze(-1).expand(sum_embeddings.size())
else:
sum_mask = input_mask_expanded.sum(1)
sum_mask = torch.clamp(sum_mask, min=1e-9)
if self.pooling_mode_mean_tokens:
output_vectors.append(sum_embeddings / sum_mask)
if self.pooling_mode_mean_sqrt_len_tokens:
output_vectors.append(sum_embeddings / torch.sqrt(sum_mask))
这上面的 token_embeddings
实际上就是 last_hidden_state
(对于 Bert 这种模型,它输出的 last_hidden_state 就是每个输入 token 对应的向量表示),上面这段代码实际上就是根据 mask 把所有向量求和再除以长度
直接求平均的话,可能会有产生偏差,如果多个句子同时进去,tokenizer 会把所有序列 pad 到一个固定长度,然后用 attention mask 告诉模型那些 pad tokens 不参与计算,如果直接求平均,会把那些 pad tokens 算进去的
感谢 @habaneraa 的解释,全面且正确。👍
Ark0810
changed discussion status to
closed