参照文献: Qwen-blog
Qwen 全体架构:
其中:
tokenizer
はテキストを語彙リスト内の数値に変換します。- 数値は
embedding
を通じて一対一のベクトルを得ます。 attention_mask
は左側、右側、双方向などを見えるように設定するためのものです。- 各種下流タスク、
Casual
、seqcls
などは、基本的に基礎モデルmodel
の後に対応するLinear
層が接続され、損失関数が異なります。
まず、github から transformer リポジトリをダウンロードし、transformer_213 と名付けます(私は 2.13 日付でダウンロードしたため)。このステップはパッケージと混同しないためのものです。
run_demo.ipynb を定義して qwen2 を詳しく理解します。
from transformers_213.src.transformers.models.qwen2 import Qwen2Config, Qwen2Model
import torch
def run_qwen2():
qwen2config = Qwen2Config(
vocab_size=151936,
hidden_size=4096//2,
num_hidden_layers=32//2,
num_attention_heads=32,
intermediate_size=2048//2
)
qwen2model = Qwen2Model(qwen2config)
input_ids = torch.randint(0, qwen2config.vocab_size, (4, 30))
res = qwen2model(input_ids)
print(res)
if __name__ == "__main__":
run_qwen2()
1 Qwen2Config#
Qwen2Config にはいくつかのカスタムハイパーパラメータが含まれています。例えば、vocab_size
、hidden_size
、num_hidden_layers
、num_attention_heads
など。dict
のように内部のハイパーパラメータを呼び出すことができます:config.pad_token_id
。
1.1 Qwen2Model#
1.1.1 初期化#
- モデルの 2 つの属性を設定しました:
padding_idx
(パディングトークンのインデックスを指定するため)、vocab_size
(語彙のサイズ) - モデルの埋め込み層、デコーダ層、正規化層を初期化しました
- 埋め込み層(
nn.Embedding
):モデルは埋め込み層を使用して入力トークンを密なベクトル表現にマッピングします。 - デコーダ層(
nn.ModuleList()
):モデルには複数のデコーダ層が含まれており、これらの層はQwen2DecoderLayer
によって定義されています - 正規化層
Qwen2RMSNorm
:正規化層は Root Mean Square Layer Normalization を使用しています gradient_checkpoint
を使用するかどうかを設定し、主にメモリを節約するために使用されますpost_init()
を呼び出して、いくつかの初期化と準備チェックのコードを完了します
class Qwen2Model(Qwen2PreTrainedModel):
def __init__(self, config: Qwen2Config):
super().__init__(config)
self.padding_idx = config.pad_token_id
self.vocab_size = config.vocab_size
self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
self.layers = nn.ModuleList(
[Qwen2DecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
)
self.norm = Qwen2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
self.gradient_checkpointing = False
# 重みを初期化し、最終処理を適用
self.post_init()
post_init
関数について:
主にパラメータの初期化と、初期化された勾配チェックポイントの役割を果たします
def post_init(self):
"""
各Transformerモデルの初期化の最後に実行されるメソッドで、モデルの
モジュールが適切に初期化されている必要があるコードを実行します(重みの初期化など)。
"""
self.init_weights()
self._backward_compatibility_gradient_checkpointing()
1.1.2 フォワード#
ここではコアの主幹について説明します:
inputs_embeds = self.embed_tokens(input_ids)
# embed positions
hidden_states = inputs_embeds
for idx, decoder_layer in enumerate(self.layers):
# すべてのhidden_statesをタプルとして保存
if output_hidden_states:
all_hidden_states += (hidden_states,)
# hsを各デコーダ層に送信
layer_outputs = decoder_layer(
hidden_states,
attention_mask=attention_mask,
position_ids=position_ids,
past_key_value=past_key_value,
output_attentions=output_attentions,
use_cache=use_cache,
)
# 前のデコーダー出力のhsを取得し、次の層に渡す
# 最初のものだけ、2番目はキャッシュの一種で、次の層に入ります
hidden_states = layer_outputs[0]
# 最後の層出力後のhidden_statesを正規化
hidden_states = self.norm(hidden_states)
# 最後の層のhidden_statesを追加
if output_hidden_states:
all_hidden_states += (hidden_states,)
output_hidden_states
を保存する場合、最初はinput_ids
に対してemb
を行い、次にn-1
層のdecoder_layer
の出力hs
を保存し、最後の層のlayer
の出力hs
を正規化後のhs
に加えます。- 最後は
BaseModelOutputWithPast
の形式で出力されます。
続く。。。