Created
November 23, 2021 00:16
-
-
Save ShairozS/9481ec8da3082475292aadb55e596e5d to your computer and use it in GitHub Desktop.
Use a pre-trained BeRT model to create sentence embeddings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class BertEmbedder(torch.nn.Module): | |
| def __init__(self, bert_model='bert-base-uncased'): | |
| ''' | |
| Initialize a BeRT model and use it to create tensor sentence embeddings of length 768 | |
| Made from the guide at: https://mccormickml.com/2019/05/14/BERT-word-embeddings-tutorial/ | |
| ''' | |
| super().__init__() | |
| self.tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') | |
| self.model = BertModel.from_pretrained('bert-base-uncased', output_hidden_states = True) | |
| self.model.eval() | |
| def forward(self, text): | |
| # Run the text through BERT, and collect all of the hidden states produced | |
| # from all 12 layers. | |
| with torch.no_grad(): | |
| outputs = self.model(*self.preprocess(text)) | |
| # Evaluating the model will return a different number of objects based on | |
| # how it's configured in the `from_pretrained` call earlier. In this case, | |
| # becase we set `output_hidden_states = True`, the third item will be the | |
| # hidden states from all layers. See the documentation for more details: | |
| # https://huggingface.co/transformers/model_doc/bert.html#bertmodel | |
| hidden_states = outputs[2] | |
| token_embeddings = torch.stack(hidden_states, dim=0) | |
| token_embeddings = torch.squeeze(token_embeddings, dim=1) | |
| token_embeddings = token_embeddings.permute(1,0,2) | |
| # Stores the token vectors, with shape [22 x 768] | |
| token_vecs_sum = [] | |
| # `token_embeddings` is a [22 x 12 x 768] tensor. | |
| # For each token in the sentence... | |
| for token in token_embeddings: | |
| # `token` is a [12 x 768] tensor | |
| # Sum the vectors from the last four layers. | |
| sum_vec = torch.sum(token[-4:], dim=0) | |
| # Use `sum_vec` to represent `token`. | |
| token_vecs_sum.append(sum_vec) | |
| # `hidden_states` has shape [13 x 1 x 22 x 768] | |
| # `token_vecs` is a tensor with shape [22 x 768] | |
| token_vecs = hidden_states[-2][0] | |
| # Calculate the average of all 22 token vectors. | |
| sentence_embedding = torch.mean(hidden_states[10], 1).squeeze() | |
| #sentence_embedding = torch.mean(token_vecs, dim=0) | |
| return(sentence_embedding) | |
| def preprocess(self, text): | |
| marked_text = "[CLS] " + text + " [SEP]" | |
| # Tokenize our sentence with the BERT tokenizer. | |
| tokenized_text = self.tokenizer.tokenize(marked_text) | |
| # Map the token strings to their vocabulary indeces. | |
| indexed_tokens = self.tokenizer.convert_tokens_to_ids(tokenized_text) | |
| # Mark each of the 22 tokens as belonging to sentence "1". | |
| segments_ids = [1] * len(tokenized_text) | |
| # Convert inputs to PyTorch tensors | |
| tokens_tensor = torch.tensor([indexed_tokens]) | |
| segments_tensors = torch.tensor([segments_ids]) | |
| return(tokens_tensor, segments_tensors) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment