LUKE Japanese Largeモデル:トークンのマスキングと予測時に予想外の出力

#1
by yotti0618 - opened

こんにちは、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

Studio Ousia org

こんにちは。
上記のモデルの挙動は、2点修正することで改善されます。

  1. マスクのトークンを [MASK] ではなく、<mask> に置き換える
    モデルによって、マスクのトークンが異なる場合があるので、ご注意ください。
    マスクのトークンは tokenizer.mask_token で取得することもできます。

  2. 入力の先頭と末尾に特殊トークンを加える。
    モデルが入力に特殊トークンが付加されている状況で学習されているので、使用する場合も特殊トークンが必要になります。
    先頭の特殊トークンは 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を使って、研究を進めていきたいと思います。

ご協力いただき、ありがとうございます。

ryo0634 changed discussion status to closed

Sign up or log in to comment