PythonでTransformerを実装する方法:基本構造と実装例をやさしく解説!

こんにちは。ゆうせいです。

今回は「TransformerをPythonで実装するにはどうすればいい?」というテーマでお話しします。

Transformerは、自然言語処理(NLP)を一変させた革命的なアーキテクチャですが、
実装となると「難しそう」「数式が多い」「どこから手をつければ…?」と感じる人も多いはず。

そこで今回は、

  • Transformerの構造を簡単におさらい
  • 実装に必要な要素を分解して解説
  • PyTorchでの実装例(シンプルなミニ版)

という流れで、Transformerを自力で動かすための基本をやさしくご紹介していきます!


1. Transformerの全体構造をざっくり把握しよう

Transformerは以下のようなEncoder-Decoder構造でできています:

入力系列 → [エンコーダ] → 中間表現 → [デコーダ] → 出力系列

でも、翻訳以外(分類・生成など)ではEncoderだけを使うケースが多いです。

Encoderの構造

  1. 入力の埋め込み(Embedding)
  2. 位置エンコーディング(Positional Encoding)
  3. 複数の「エンコーダ層」
    • Multi-Head Attention
    • 残差接続+LayerNorm
    • FeedForward Network

2. Pythonで実装する前の準備(必要な知識)

Transformer実装には次の概念が必要になります。

概念説明
ベクトルの埋め込み(Embedding)単語などを数値ベクトルに変換
位置エンコーディング入力の順序情報を加える
Self-Attention各単語が他の単語をどれだけ重視するかを計算
Multi-Head Attention複数の視点からAttentionを同時に行う
Feed Forward各位置のベクトルを非線形で変換
LayerNorm / 残差接続学習の安定化と深層化の補助

3. 実装例(PyTorch)

以下は、Encoderの最小構成をPyTorchで実装する例です。

import torch
import torch.nn as nn
import math

class PositionalEncoding(nn.Module):
    def __init__(self, d_model, max_len=5000):
        super().__init__()
        pe = torch.zeros(max_len, d_model)
        position = torch.arange(0, max_len).unsqueeze(1)
        div_term = torch.exp(
            torch.arange(0, d_model, 2) * (-math.log(10000.0) / d_model)
        )
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        self.pe = pe.unsqueeze(0)

    def forward(self, x):
        return x + self.pe[:, :x.size(1)].to(x.device)

class TransformerEncoderLayer(nn.Module):
    def __init__(self, d_model, nhead, dim_feedforward=2048):
        super().__init__()
        self.attn = nn.MultiheadAttention(d_model, nhead, batch_first=True)
        self.ff = nn.Sequential(
            nn.Linear(d_model, dim_feedforward),
            nn.ReLU(),
            nn.Linear(dim_feedforward, d_model),
        )
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)

    def forward(self, x):
        attn_output, _ = self.attn(x, x, x)
        x = self.norm1(x + attn_output)
        ff_output = self.ff(x)
        x = self.norm2(x + ff_output)
        return x

class SimpleTransformerEncoder(nn.Module):
    def __init__(self, vocab_size, d_model=512, nhead=8, num_layers=6, max_len=5000):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, d_model)
        self.pos_encoder = PositionalEncoding(d_model, max_len)
        self.layers = nn.ModuleList([
            TransformerEncoderLayer(d_model, nhead) for _ in range(num_layers)
        ])

    def forward(self, src):
        x = self.embedding(src)
        x = self.pos_encoder(x)
        for layer in self.layers:
            x = layer(x)
        return x

4. 学習部分(簡易版)

# 入力(例:単語ID列)
sample_input = torch.randint(0, 10000, (8, 32))  # batch=8, length=32
model = SimpleTransformerEncoder(vocab_size=10000)

# 出力ベクトル
output = model(sample_input)  # shape: [8, 32, 512]

5. HuggingFace Transformersを使うならもっと簡単!

from transformers import BertTokenizer, BertModel

tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
model = BertModel.from_pretrained("bert-base-uncased")

inputs = tokenizer("Transformers are powerful!", return_tensors="pt")
outputs = model(**inputs)

こんなに簡単に、実用的なモデルが使えます!


まとめ

  • TransformerはSelf-Attentionを使った「並列処理可能な系列モデル」
  • 実装では Embedding → Positional Encoding → Multi-Head Attention → FFN の構造
  • PyTorchで簡易的に書くこともできるし、HuggingFaceなら一瞬で本格モデルが使える
  • 数式を丁寧に追えば、自作実装も理解できるようになる!

今後の学習の指針

  • Attentionの数式(クエリ・キー・バリューの関係)を数式レベルで理解
  • マスク(Transformer Decoder)やCross-Attentionの実装に挑戦
  • トークナイザや語彙の扱い方(BPEやWordPiece)を調べてみよう
  • Transformerから派生した構造(BERT、GPT、ViT、T5など)も実験してみよう!

自分でTransformerを動かせると、最新のAI技術がぐっと身近になりますよ!

生成AI研修のおすすめメニュー

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。