web-dev-qa-db-ja.com

マスク位置にあるマルチトークン単語の確率を取得します

以下のスニペットが示すように、言語モデルに従ってトークンの確率を取得するのは比較的簡単です。モデルの出力を取得し、マスクされたトークンの出力に制限してから、出力ベクトルで要求されたトークンの確率を見つけることができます。ただし、これは単一トークンの単語でのみ機能します。トークナイザーの語彙に含まれる単語。単語が語彙に存在しない場合、トークナイザーはそれを知っている知っている断片にチャンクします(例の下部を参照)。しかし、入力文は1つのマスクされた位置のみで構成され、要求されたトークンにはそれよりも多くのトークンがあるため、どのようにしてその確率を取得できますか?最終的には、Wordのサブワード単位の数に関係なく機能するソリューションを探しています。

以下のコードでは、何が起こっているのかを説明する多くのコメントを追加し、printステートメントの特定の出力を出力しています。 「love」や「hate」などのトークンは、トークナイザーの語彙に含まれているため、予測が簡単であることがわかります。ただし、「叱責」はそうではないため、単一のマスクされた位置で予測することはできません。3つのサブワードユニットで構成されます。では、マスクされた位置での「叱責」をどのように予測できますか?

from transformers import BertTokenizer, BertForMaskedLM
import torch

# init model and tokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForMaskedLM.from_pretrained('bert-base-uncased')
model.eval()
# init softmax to get probabilities later on
sm = torch.nn.Softmax(dim=0)
torch.set_grad_enabled(False)

# set sentence with MASK token, convert to token_ids
sentence = f"I {tokenizer.mask_token} you"
token_ids = tokenizer.encode(sentence, return_tensors='pt')
print(token_ids)
# tensor([[ 101, 1045,  103, 2017,  102]])
# get the position of the masked token
masked_position = (token_ids.squeeze() == tokenizer.mask_token_id).nonzero().item()

# forward
output = model(token_ids)
last_hidden_state = output[0].squeeze(0)
# only get output for masked token
# output is the size of the vocabulary
mask_hidden_state = last_hidden_state[masked_position]
# convert to probabilities (softmax)
# giving a probability for each item in the vocabulary
probs = sm(mask_hidden_state)

# get probability of token 'hate'
hate_id = tokenizer.convert_tokens_to_ids('hate')
print('hate probability', probs[hate_id].item())
# hate probability 0.008057191967964172

# get probability of token 'love'
love_id = tokenizer.convert_tokens_to_ids('love')
print('love probability', probs[love_id].item())
# love probability 0.6704086065292358

# get probability of token 'reprimand' (?)
reprimand_id = tokenizer.convert_tokens_to_ids('reprimand')
# reprimand is not in the vocabulary, so it needs to be split into subword units
print(tokenizer.convert_ids_to_tokens(reprimand_id))
# [UNK]

reprimand_id = tokenizer.encode('reprimand', add_special_tokens=False)
print(tokenizer.convert_ids_to_tokens(reprimand_id))
# ['rep', '##rim', '##and']
# but how do we now get the probability of a multi-token Word in a single-token position?
4
Bram Vanroy

の代わりに sentence = f"I {tokenizer.mask_token} you"、予測:"I [MASK] [MASK] you"および"I [MASK] [MASK] [MASK] you"結果をフィルタリングし、Wordトークンチェーン全体を削除して、適切なサブワードのチェーンのみを検索します。もちろん、周囲のコンテキストワードを3つ以上指定すると、より良い結果が得られます。

しかし、それに着手する前に、ソフトマックスを再考してください。ディメンション= 0の場合、必要な単一のトークンだけでなく、すべてのトークン列およびすべてのトークン行に対してソフトマックス計算を実行します。ソフトマックス確率:

In [1]: import torch                                                                                                                      
In [2]: m = torch.nn.Softmax(dim=1) 
   ...: input = torch.randn(2, 3) 
   ...: input                                                                                                                        
Out[2]: 
tensor([[ 1.5542,  0.3776, -0.8047],
        [-0.3856,  1.1327, -0.1252]])

In [3]: m(input)                                                                                                                          
Out[3]: 
tensor([[0.7128, 0.2198, 0.0674],
        [0.1457, 0.6652, 0.1891]])

In [4]: soft = torch.nn.Softmax(dim=0) 
   ...: soft(input)                                                                                                                       
Out[4]: 
tensor([[0.8743, 0.3197, 0.3364],
        [0.1257, 0.6803, 0.6636]])
0
Todd Cook