多语言 Bert 句子向量捕获的语言不仅仅是意义——像实习生一样工作?
Multilingual Bert sentence vector captures language used more than meaning - working as interned?
玩BERT,下载了Huggingface Multilingual Bert,输入三个句子,保存他们的句向量([CLS]
的embedding),然后通过GoogleTranslate翻译,通过模型并保存他们的句子向量。
然后我使用余弦相似度比较结果。
我很惊讶地发现每个句子向量都与从它翻译的句子生成的向量相差甚远(0.15-0.27 余弦距离),而来自同一语言的不同句子确实非常接近(0.02-0.04 余弦距离)距离)。
因此,与其将意义相似(但语言不同)的句子组合在一起(在 768 维 space ;) 中),不如将相同语言的不同句子组合在一起。
据我了解,多语言 Bert 的全部意义在于跨语言迁移学习——例如,在一种语言的表征上训练一个模型(比如 FC 网络),并让该模型可以很容易地用于其他语言。
如果(不同语言的)具有确切含义的句子被映射为比同一种语言的不同句子相距更远,那该怎么做呢?
我的代码:
import torch
import transformers
from transformers import AutoModel,AutoTokenizer
bert_name="bert-base-multilingual-cased"
tokenizer = AutoTokenizer.from_pretrained(bert_name)
MBERT = AutoModel.from_pretrained(bert_name)
#Some silly sentences
eng1='A cat jumped from the trees and startled the tourists'
e=tokenizer.encode(eng1, add_special_tokens=True)
ans_eng1=MBERT(torch.tensor([e]))
eng2='A small snake whispered secrets to large cats'
t=tokenizer.tokenize(eng2)
e=tokenizer.encode(eng2, add_special_tokens=True)
ans_eng2=MBERT(torch.tensor([e]))
eng3='A tiger sprinted from the bushes and frightened the guests'
e=tokenizer.encode(eng3, add_special_tokens=True)
ans_eng3=MBERT(torch.tensor([e]))
# Translated to Hebrew with Google Translate
heb1='חתול קפץ מהעץ והבהיל את התיירים'
e=tokenizer.encode(heb1, add_special_tokens=True)
ans_heb1=MBERT(torch.tensor([e]))
heb2='נחש קטן לחש סודות לחתולים גדולים'
e=tokenizer.encode(heb2, add_special_tokens=True)
ans_heb2=MBERT(torch.tensor([e]))
heb3='נמר רץ מהשיחים והפחיד את האורחים'
e=tokenizer.encode(heb3, add_special_tokens=True)
ans_heb3=MBERT(torch.tensor([e]))
from scipy import spatial
import numpy as np
# Compare Sentence Embeddings
result = spatial.distance.cosine(ans_eng1[1].data.numpy(), ans_heb1[1].data.numpy())
print ('Eng1-Heb1 - Translated sentences',result)
result = spatial.distance.cosine(ans_eng2[1].data.numpy(), ans_heb2[1].data.numpy())
print ('Eng2-Heb2 - Translated sentences',result)
result = spatial.distance.cosine(ans_eng3[1].data.numpy(), ans_heb3[1].data.numpy())
print ('Eng3-Heb3 - Translated sentences',result)
print ("\n---\n")
result = spatial.distance.cosine(ans_heb1[1].data.numpy(), ans_heb2[1].data.numpy())
print ('Heb1-Heb2 - Different sentences',result)
result = spatial.distance.cosine(ans_eng1[1].data.numpy(), ans_eng2[1].data.numpy())
print ('Heb1-Heb3 - Similiar sentences',result)
print ("\n---\n")
result = spatial.distance.cosine(ans_eng1[1].data.numpy(), ans_eng2[1].data.numpy())
print ('Eng1-Eng2 - Different sentences',result)
result = spatial.distance.cosine(ans_eng1[1].data.numpy(), ans_eng3[1].data.numpy())
print ('Eng1-Eng3 - Similiar sentences',result)
#Output:
"""
Eng1-Heb1 - Translated sentences 0.2074061632156372
Eng2-Heb2 - Translated sentences 0.15557605028152466
Eng3-Heb3 - Translated sentences 0.275478720664978
---
Heb1-Heb2 - Different sentences 0.044616520404815674
Heb1-Heb3 - Similar sentences 0.027982771396636963
---
Eng1-Eng2 - Different sentences 0.027982771396636963
Eng1-Eng3 - Similar sentences 0.024596810340881348
"""
P.S.
至少 Heb1 比 Heb2 更接近 Heb3。
这也适用于英语等价物,但不那么明显。
[CLS] Token 以某种方式表示输入序列,但具体如何表示很难说。语言当然是句子的重要特征,可能比意义更重要。 BERT 是一种预训练模型,它试图对意义、结构和语言等特征进行建模。如果你想有一个模型,帮助你识别两个不同语言的句子是否意味着同一件事,我可以想到两种不同的方法:
方法:您可以在该任务上训练分类器(SVM、逻辑回归甚至一些神经元网络,例如 CNN)。 Inputs: two [CLS]-Token, Output: Same meaning, or not same meaning.
作为训练数据,您可以选择 [CLS]-Token-不同语言的句子对,这些句子的含义相同或不同。要获得有意义的结果,您需要很多这样的句子对。幸运的是,您可以通过 google 翻译生成它们,或者使用平行文本,例如以多种语言存在的圣经,并从中提取句子对。
方法:针对该任务微调 bert 模型:
与之前的方法一样,您需要大量的训练数据。
BERT 模型的示例输入如下所示:
A cat jumped from the trees and startled the tourists [SEP] חתול קפץ מהעץ והבהיל את התיירים
要对这些句子是否具有相同的含义进行分类,您可以在 [CLS]-Token 之上添加一个分类层,并针对该任务微调整个模型。
注意:我从未使用过多语言 BERT 模型,这些方法是我想到的用于完成上述任务的方法。如果您尝试这些方法,我很想知道它们的表现如何。
目前还没有完全理解多语言 BERT 的作用及其工作原理。最近有两篇论文(第一篇from June, second from November)对此进行了一些探讨。
从论文来看,向量似乎倾向于根据语言(甚至语言家族)进行聚类,因此对语言进行分类非常容易。这是显示的聚类 in the paper:
因此,您可以从表示中减去语言的均值,并以某种方式得到一个跨语言向量,两篇论文都表明该向量可用于跨语言句子检索。
此外,似乎一千个平行句子(例如,在两种语言中)足以学习语言之间的投影。请注意,他们没有使用 [CLS]
向量,但他们对单个子词的向量进行了平均汇集。
玩BERT,下载了Huggingface Multilingual Bert,输入三个句子,保存他们的句向量([CLS]
的embedding),然后通过GoogleTranslate翻译,通过模型并保存他们的句子向量。
然后我使用余弦相似度比较结果。
我很惊讶地发现每个句子向量都与从它翻译的句子生成的向量相差甚远(0.15-0.27 余弦距离),而来自同一语言的不同句子确实非常接近(0.02-0.04 余弦距离)距离)。
因此,与其将意义相似(但语言不同)的句子组合在一起(在 768 维 space ;) 中),不如将相同语言的不同句子组合在一起。
据我了解,多语言 Bert 的全部意义在于跨语言迁移学习——例如,在一种语言的表征上训练一个模型(比如 FC 网络),并让该模型可以很容易地用于其他语言。
如果(不同语言的)具有确切含义的句子被映射为比同一种语言的不同句子相距更远,那该怎么做呢?
我的代码:
import torch
import transformers
from transformers import AutoModel,AutoTokenizer
bert_name="bert-base-multilingual-cased"
tokenizer = AutoTokenizer.from_pretrained(bert_name)
MBERT = AutoModel.from_pretrained(bert_name)
#Some silly sentences
eng1='A cat jumped from the trees and startled the tourists'
e=tokenizer.encode(eng1, add_special_tokens=True)
ans_eng1=MBERT(torch.tensor([e]))
eng2='A small snake whispered secrets to large cats'
t=tokenizer.tokenize(eng2)
e=tokenizer.encode(eng2, add_special_tokens=True)
ans_eng2=MBERT(torch.tensor([e]))
eng3='A tiger sprinted from the bushes and frightened the guests'
e=tokenizer.encode(eng3, add_special_tokens=True)
ans_eng3=MBERT(torch.tensor([e]))
# Translated to Hebrew with Google Translate
heb1='חתול קפץ מהעץ והבהיל את התיירים'
e=tokenizer.encode(heb1, add_special_tokens=True)
ans_heb1=MBERT(torch.tensor([e]))
heb2='נחש קטן לחש סודות לחתולים גדולים'
e=tokenizer.encode(heb2, add_special_tokens=True)
ans_heb2=MBERT(torch.tensor([e]))
heb3='נמר רץ מהשיחים והפחיד את האורחים'
e=tokenizer.encode(heb3, add_special_tokens=True)
ans_heb3=MBERT(torch.tensor([e]))
from scipy import spatial
import numpy as np
# Compare Sentence Embeddings
result = spatial.distance.cosine(ans_eng1[1].data.numpy(), ans_heb1[1].data.numpy())
print ('Eng1-Heb1 - Translated sentences',result)
result = spatial.distance.cosine(ans_eng2[1].data.numpy(), ans_heb2[1].data.numpy())
print ('Eng2-Heb2 - Translated sentences',result)
result = spatial.distance.cosine(ans_eng3[1].data.numpy(), ans_heb3[1].data.numpy())
print ('Eng3-Heb3 - Translated sentences',result)
print ("\n---\n")
result = spatial.distance.cosine(ans_heb1[1].data.numpy(), ans_heb2[1].data.numpy())
print ('Heb1-Heb2 - Different sentences',result)
result = spatial.distance.cosine(ans_eng1[1].data.numpy(), ans_eng2[1].data.numpy())
print ('Heb1-Heb3 - Similiar sentences',result)
print ("\n---\n")
result = spatial.distance.cosine(ans_eng1[1].data.numpy(), ans_eng2[1].data.numpy())
print ('Eng1-Eng2 - Different sentences',result)
result = spatial.distance.cosine(ans_eng1[1].data.numpy(), ans_eng3[1].data.numpy())
print ('Eng1-Eng3 - Similiar sentences',result)
#Output:
"""
Eng1-Heb1 - Translated sentences 0.2074061632156372
Eng2-Heb2 - Translated sentences 0.15557605028152466
Eng3-Heb3 - Translated sentences 0.275478720664978
---
Heb1-Heb2 - Different sentences 0.044616520404815674
Heb1-Heb3 - Similar sentences 0.027982771396636963
---
Eng1-Eng2 - Different sentences 0.027982771396636963
Eng1-Eng3 - Similar sentences 0.024596810340881348
"""
P.S.
至少 Heb1 比 Heb2 更接近 Heb3。 这也适用于英语等价物,但不那么明显。
[CLS] Token 以某种方式表示输入序列,但具体如何表示很难说。语言当然是句子的重要特征,可能比意义更重要。 BERT 是一种预训练模型,它试图对意义、结构和语言等特征进行建模。如果你想有一个模型,帮助你识别两个不同语言的句子是否意味着同一件事,我可以想到两种不同的方法:
方法:您可以在该任务上训练分类器(SVM、逻辑回归甚至一些神经元网络,例如 CNN)。
Inputs: two [CLS]-Token, Output: Same meaning, or not same meaning.
作为训练数据,您可以选择 [CLS]-Token-不同语言的句子对,这些句子的含义相同或不同。要获得有意义的结果,您需要很多这样的句子对。幸运的是,您可以通过 google 翻译生成它们,或者使用平行文本,例如以多种语言存在的圣经,并从中提取句子对。方法:针对该任务微调 bert 模型: 与之前的方法一样,您需要大量的训练数据。 BERT 模型的示例输入如下所示:
A cat jumped from the trees and startled the tourists [SEP] חתול קפץ מהעץ והבהיל את התיירים
要对这些句子是否具有相同的含义进行分类,您可以在 [CLS]-Token 之上添加一个分类层,并针对该任务微调整个模型。
注意:我从未使用过多语言 BERT 模型,这些方法是我想到的用于完成上述任务的方法。如果您尝试这些方法,我很想知道它们的表现如何。
目前还没有完全理解多语言 BERT 的作用及其工作原理。最近有两篇论文(第一篇from June, second from November)对此进行了一些探讨。
从论文来看,向量似乎倾向于根据语言(甚至语言家族)进行聚类,因此对语言进行分类非常容易。这是显示的聚类 in the paper:
因此,您可以从表示中减去语言的均值,并以某种方式得到一个跨语言向量,两篇论文都表明该向量可用于跨语言句子检索。
此外,似乎一千个平行句子(例如,在两种语言中)足以学习语言之间的投影。请注意,他们没有使用 [CLS]
向量,但他们对单个子词的向量进行了平均汇集。