Intégration de phrases BERT à partir de transformateurs
J'essaie d'obtenir des vecteurs de phrase à partir d'états cachés dans un modèle BERT. En regardant les instructions de BertModel étreignant ici , qui disent:
from transformers import BertTokenizer, BertModel
tokenizer = BertTokenizer.from_pretrained('bert-base-multilingual-cased')
model = BertModel.from_pretrained("bert-base-multilingual-cased")
text = "Replace me by any text you'd like."
encoded_input = tokenizer(text, return_tensors='pt')
output = model(**encoded_input)
Alors, tout d'abord, comme c'est le cas sur le site Web, cela ne fonctionne pas. Vous obtenez:
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'BertTokenizer' object is not callable
Mais il semble qu'un changement mineur le corrige, en ce sens que vous n'appelez pas directement le tokenizer, mais demandez-lui d'encoder l'entrée:
encoded_input = tokenizer.encode(text, return_tensors="pt")
output = model(encoded_input)
OK, cela mis à part, les tenseurs que j'obtiens ont cependant une forme différente de celle à laquelle je m'attendais:
>>> output[0].shape
torch.Size([1,11,768])
C'est beaucoup de couches. Quel est le bon calque à utiliser pour les incorporations de phrases? [0]
? [-1]
? En moyenne plusieurs? J'ai pour objectif de pouvoir faire une similitude cosinus avec ceux-ci, j'ai donc besoin d'un vecteur 1xN approprié plutôt que d'un tenseur NxK.
Je vois que le projet populaire bert-as-a-service semble utiliser[0]
Est-ce correct? Existe-t-il une documentation sur ce que sont chacune des couches?
Réponses
Je ne pense pas qu'il existe une seule documentation faisant autorité indiquant quoi utiliser et quand. Vous devez expérimenter et mesurer ce qui convient le mieux à votre tâche. Les observations récentes sur le BERT sont bien résumées dans cet article:https://arxiv.org/pdf/2002.12327.pdf.
Je pense que la règle d'or est:
Utilisez la dernière couche si vous souhaitez affiner le modèle pour votre tâche spécifique. Et affinez chaque fois que vous le pouvez, plusieurs centaines, voire des dizaines d'exemples de formation suffisent.
Utilisez certaines des couches intermédiaires (7e ou 8e) si vous ne pouvez pas affiner le modèle. L'intuition derrière cela est que les couches développent d'abord une représentation de plus en plus abstraite et générale de l'entrée. À un moment donné, la représentation commence à être plus ciblée sur la tâche de pré-formation.
Bert-as-services utilise la dernière couche par défaut (mais elle est configurable). Ici, ce serait [:, -1]
. Cependant, il renvoie toujours une liste de vecteurs pour tous les jetons d'entrée. Le vecteur correspondant au premier [CLS]
jeton spécial (soi-disant ) est considéré comme l'incorporation de la phrase. C'est de là que [0]
vient le snipper auquel vous faites référence.
Bien que la réponse actuelle de Jindrich soit généralement correcte, elle ne répond pas entièrement à la question. L'OP a demandé quelle couche il devrait utiliser pour calculer la similitude cosinus entre les plongements de phrases et la réponse courte à cette question est aucune . Une métrique comme la similarité cosinus nécessite que les dimensions du vecteur contribuent de manière égale et significative, mais ce n'est pas le cas pour BERT. Jacob Devlin (l'un des auteurs de l'article du BERT) a écrit :
Je ne suis pas sûr de ce que sont ces vecteurs, car BERT ne génère pas de vecteurs de phrases significatifs. Il semble que ce soit une mise en commun moyenne des jetons de mots pour obtenir un vecteur de phrase, mais nous n'avons jamais suggéré que cela générerait des représentations de phrases significatives. Et même si ce sont des représentations décentes lorsqu'elles sont introduites dans un DNN formé pour une tâche en aval, cela ne signifie pas qu'elles seront significatives en termes de distance cosinus. (Puisque la distance cosinus est un espace linéaire où toutes les dimensions sont pondérées de manière égale).
Cependant, cela ne signifie pas que vous ne pouvez pas utiliser BERT pour une telle tâche. Cela signifie simplement que vous ne pouvez pas utiliser les poids pré-entraînés prêts à l'emploi. Vous pouvez soit former un classificateur au-dessus de BERT qui apprend quelles phrases sont similaires (en utilisant le [CLS]
jeton), soit utiliser des transformateurs de phrase qui peuvent être utilisés dans un scénario non supervisé car ils ont été formés pour produire des représentations de phrases significatives.