【Transformers】警告The attention mask and the pad token id were not set. As a consequence・・・の解決方法

はるか
はるか
言語モデル使ってる時に警告が出た。「attention mask」と「pad token ID」が設定されてない。
ふゅか
ふゅか
ちゃんと設定しないと、予期しない動作が起こる可能性があるらしいね!?

1. 警告の内容

2. 警告の発生したコード

2.1. モデルの読み込み

モデルとしてllama3を使用します。トークナイザーとモデルを読み込みます。

from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

model_id = "meta-llama/Meta-Llama-3-8B"

tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    torch_dtype=torch.bfloat16,
    device_map="auto",
load_in_4bit=True)

2.2. 問題のあるコード

prompt="Octave is "
input_ids = tokenizer.encode(
    prompt,
    return_tensors="pt"
).to(model.device)
temperature= 0.1

outputs = model.generate(
    input_ids,
    max_new_tokens=50,
    do_sample=True,
    temperature=temperature,
)

output=tokenizer.decode(outputs[0],skip_special_tokens=True)

出力自体はちゃんと生成されます。内容に間違いがありますが…。Octaveは数値計算に特化したソフトウェアですが、出力には「Octaveは3Dプリンティング用のソフトウェアです」と誤った情報が含まれていました。

Octave is 3D printing software that allows you to create 3D models and print them on a 3D printer. It is a free and open-source software that is available for Windows, Mac, and Linux. Octave is a powerful tool that can

本題ですが、次のような警告が発生しました。

The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input’s attention_mask to obtain reliable results.
Setting pad_token_id to eos_token_id:None for open-end generation.
The attention mask is not set and cannot be inferred from input because pad token is same as eos token. As a consequence, you may observe unexpected behavior. Please pass your input’s attention_mask to obtain reliable results.

警告の内容を日本語にすると、

「attention mask」と「pad token ID」が設定されていないため、予期しない動作が発生する可能性があることを指摘しています信頼できる結果を得るために、attention_maskを入力に渡すように推奨されています。

ようは、attention_maskとpad token IDを指定しなさいということですね。

3. 解決方法

この警告を回避するためには、attention_maskを明示的に指定し、pad tokenを設定します。以下に修正したコードを示します。

prompt="Octave is "

# 必要に応じて pad_token を設定
if tokenizer.pad_token is None:
    tokenizer.pad_token = tokenizer.eos_token  
temperature = 0.1
# 入力に対して attention_mask を生成
inputs = tokenizer(prompt, return_tensors="pt", padding=True).to(model.device)
input_ids = inputs["input_ids"]
attention_mask = inputs["attention_mask"]

# モデル生成時に attention_mask を含める
outputs = model.generate(
    input_ids,
    attention_mask=attention_mask,
    max_new_tokens=50,
    do_sample=True,
    temperature=temperature,
    pad_token_id=tokenizer.pad_token_id  # ここに pad_token_id を渡す
)

output = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(output)

3.1. コードのポイント

pad_tokenの設定: トークナイザーにpad_tokenがない場合、eos_tokenをpad_tokenとして設定しています。


if tokenizer.pad_token is None:
    tokenizer.pad_token = tokenizer.eos_token  

attention_maskの生成: tokenizerからpadding=Trueを指定して、入力データとattention_maskを取得しています。

inputs = tokenizer(prompt, return_tensors="pt", padding=True).to(model.device)
input_ids = inputs["input_ids"]
attention_mask = inputs["attention_mask"]

pad_token_idとattention_maskの指定: トークンの生成時にpad_token_idとattention_maskを明示的に設定します。

outputs = model.generate(
    input_ids,
    attention_mask=attention_mask,
    max_new_tokens=50,
    do_sample=True,
    temperature=temperature,
    pad_token_id=tokenizer.pad_token_id  # ここに pad_token_id を渡す
)
ふゅか
ふゅか
これでThe attention maskの警告が出なくなったわけか〜。

4. Transformers・大規模言語モデルに関連する書籍

PR