LUKE Japanese Largeモデル:トークンのマスキングと予測時に予想外の出力
こんにちは、Hugging Faceのコミュニティの皆さん。
私は「studio-ousia/luke-japanese-large」のLUKE Japanese Largeモデルを使用していて、トークンをマスクして予測する際に問題に直面しました。
以下に使用したコードを示します:
from transformers import AutoTokenizer, AutoModelForMaskedLM
import torch
# Define the model
MODEL_NAME = "studio-ousia/luke-japanese-large"
# Load the pre-trained model's tokenizer (vocabulary)
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
# Tokenize the input
text = "人間とロボットは長らく人生を一緒に過ごしてきたのである。"
tokenized_text = tokenizer.tokenize(text)
# Mask a token for prediction using BertForMaskedLM
masked_index = 2
tokenized_text[masked_index] = '[MASK]'
# Convert the tokens into vocabulary indices
indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text)
# Convert the input into PyTorch tensor
tokens_tensor = torch.tensor([indexed_tokens]).to("cuda")
# Load the pre-trained model (weights)
model = AutoModelForMaskedLM.from_pretrained(MODEL_NAME)
model.eval()
model.to("cuda")
# Predict all tokens
with torch.no_grad():
outputs = model(tokens_tensor)
predictions = outputs[0]
# Confirm that 'S' is predicted
predicted_index = torch.argmax(predictions[0, masked_index]).item()
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
print(predicted_token)
print(predicted_index)
得られた出力は'''< "unk ">と 3 '''で、マスクした位置に対してはあまり意味がないように思われました。
私が何か見落としている点や、この結果を改善するための提案はありますか? この方法を使用してマスクしたトークンを適切に予測できていないように思えます。
あらかじめご協力いただきありがとうございます。
よろしくお願いいたします、
yotti0618
こんにちは。
上記のモデルの挙動は、2点修正することで改善されます。
マスクのトークンを
[MASK]
ではなく、<mask>
に置き換える
モデルによって、マスクのトークンが異なる場合があるので、ご注意ください。
マスクのトークンはtokenizer.mask_token
で取得することもできます。入力の先頭と末尾に特殊トークンを加える。
モデルが入力に特殊トークンが付加されている状況で学習されているので、使用する場合も特殊トークンが必要になります。
先頭の特殊トークンはtokenizer.cls_token
、末尾の特殊トークンはtokenizer.sep_token
で確認できます。
以下のコードは、tokenizer
にテキストを渡すことで、自動で特殊トークンを先頭と末尾に付加しています。
予測結果も意味があるものになりましたので、ご参考になれば幸いです。
from transformers import AutoTokenizer, AutoModelForMaskedLM
import torch
# Define the model
MODEL_NAME = "studio-ousia/luke-japanese-large"
# Load the pre-trained model's tokenizer (vocabulary)
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
# Tokenize the input
text = "人間とロボットは長らく人生を一緒に過ごしてきたのである。"
# Convert the input into PyTorch tensor
encoded_text = tokenizer(text, return_tensors="pt")
masked_index = 3
encoded_text["input_ids"][0][masked_index] = tokenizer.mask_token_id
print(tokenizer.convert_ids_to_tokens(encoded_text["input_ids"][0]))
encoded_text = encoded_text.to("cuda")
# Load the pre-trained model (weights)
model = AutoModelForMaskedLM.from_pretrained(MODEL_NAME)
model.eval()
model.to("cuda")
# Predict all tokens
with torch.no_grad():
outputs = model(**encoded_text)
predictions = outputs[0]
# Confirm that 'S' is predicted
predicted_index = torch.argmax(predictions[0, masked_index]).item()
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
print(predicted_token)
print(predicted_index)
出力
['<s>', '▁人間', 'と', '<mask>', 'は', '長', 'らく', '人生を', '一緒に', '過ご', 'してきた', 'のである', '。', '</s>']
動物
2661
こんばんは。確認できたました。モデルの学習方法に合わせることが重要だったんですね。
自動で特殊トークンを付加する方法まで教えていただき、ありがとうございます。
先頭の特殊トークンは tokenizer.cls_token、末尾の特殊トークンは tokenizer.sep_token 、マスクのトークンは tokenizer.mask_tokenで確認できることができることも知れてとても良かったです。
Lukeを使って、研究を進めていきたいと思います。
ご協力いただき、ありがとうございます。