RoBERTaをベースとしたモデルで事前学習を行ってオリジナルな言語モデルを作った後、その言語モデルを個別タスクにファインチューニングしようとしたら、学習時に以下のようなエラーが出ました。
RuntimeError: CUDA error: CUBLAS_STATUS_NOT_INITIALIZED when calling `cublasCreate(handle)`
いろんな原因が考えられるかも知れませが、私の手元で起こった原因は以下のissueにあげられているようなRoBERTaのmax_position_embeddings
のサイズが原因でした。
- RoBERTa and 514
- max_len_single_sentence should be max_len - 2 for RoBERTa
- Why the RoBERTa's max_position_embeddings size is 512+2=514?
上記のエラーが発生する原因は以下の流れを踏んだ時です。
- 事前学習時に
max_position_embeddings=512
で学習(デフォルトをそのまま使用) - fine tuning時に文章の長さ(トークン数)が512のデータを順伝播させる
RoBERTaではトークンに位置情報の特徴量(position_embeddings
)を足し合わせる時、padding_idx + 1
を位置情報の開始時点としているため、511番目、512番目に位置するトークンのposition_embeddigs
は513番目と514番目の要素を参照する必要があるが、事前学習時にposition_embeddings
のサイズを512にしているため、参照先がなくてエラーが出たと思われます。
(RoBERTaのpadding_idx
は`1です。)
この辺の該当するソースコードは以下ですかね。
対処方法としては、ファインチューニングのときにmax_length=510
を設定するとか、事前学習時のBertConfigの設定で、max_position_embeddings=514
を設定すればエラーを回避できると思われます。
例えばRoBERTaをベースとしたモデルCamemBERT
を使う時は以下のような感じですかね。
from transformers import CamembertConfig, CamembertForMaskedLM
config = CamembertConfig(
vocab_size=len(tokenizer),
num_hidden_layers=12,
intermediate_size=768,
num_attention_heads=12,
max_position_embeddings=514, # 512+2
type_vocab_size=1
)
model = CamembertForMaskedLM(config)
なんかしっくりこないですが私の理解がおいつていないだけかもですが、issueによれば、RoBERTaのposition_embeddings
は0番目はランダムに生成され使用はされず、1番目は0ベクトルになっているようです。
from transformers import RobertaModel
model = RobertaModel.from_pretrained('roberta-base')
print(model.embeddings.position_embeddings.weight[:2])
# tensor([[-0.0115, 0.0204, 0.0197, ..., 0.0050, -0.0274, -0.0439],
# [ 0.0000, 0.0000, 0.0000, ..., 0.0000, 0.0000, 0.0000],
# [ 0.0346, -0.0169, -0.0895, ..., -0.0542, 0.0291, 0.0173]], ← ここから先頭のトークンの位置情報になっているらしい
# grad_fn=<SliceBackward>)
同じようなエラーが出て悩んでいる方にこの記事が届いて少しでもご参考になれば幸いです。
おわり