論文解説をGPT-4oを使って自動的に生成してみる

こんにちは、逆瀬川 ( https://x.com/gyakuse ) です！
論文をGPT-4oにPDFからテキスト抽出して読み込ませる方法はみんながよくやっていると思うので、今回は画像として取り扱ってみました。

## 今回主張したいこと

**PDFを画像として取り扱うと処理は遅いが格段に安い！！**

## 生成したもの

以下のようなものが生成できます (詳細は後ろのAppendix参考)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/8c48e32f-88aa-0f44-0868-aa2423877b4b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/81b3359c-defb-81ac-72d0-56dfdfb3e128.png)

## 作成したリポジトリ

https://github.com/nyosegawa/paper-reader-ochiai-method

## 今回やったこと

- 論文のPDFを画像として扱い、GPT-4oで落合メソッドを使って解説を生成させる
- 論文のPDFから数式や図表を抽出し、個々に解説を生成

## PDF文書を画像として取り扱う利点

画像として扱う利点は意外にもトークン数が小さく処理できること, レイアウトに依存した解釈を行ってくれることがあります。

## PDF文書を画像として取り扱う欠点

- 日本語かつ手書きテキストの場合、OCRの最先端モデルに文章理解能力が劣ります
- テキスト埋め込みPDFかつレイアウトや図表に依存しない文書の場合、テキスト抽出したほうが (言うまでもなく) 推論の精度が高くなります

## トークン効率の比較 (GPT-4oにおいて)

- 画像トークンの計算方法
    - 画像のw, hが `512*512` 以下または `detail: low` の場合は85, それ以外の場合はw, h を比率を維持しつつ `2048*2048` 以下にし、最短辺が768以下になるよう再度縮小。それを埋める `512*512 のタイル数(最大8)` * 170+85がトークン数となる


|処理方法|Time (second)|Completion Tokens|Prompt Tokens|Total Token|
|---|---|---|---|---|
|GPT-4o + Image|27.76|1,115|1,519|2,634|
|GPT-4o + Text|18.18|1,069|10,199|11,268|

Prompt Tokensはテキストの15%になっています。
計算しやすいようにCompletion Tokensをどちらも1,000とすると、

- 画像として処理した場合は0.022595ドル=3.55円
- テキスト抽出して処理した場合は0.065995ドル=10.38 円

と約3倍もの開きがあります。
一方で処理時間は1.5倍に増加しています。

## 実装紹介: 論文から解説生成

落合陽一さんが紹介したサーベイの方法論を使い、論文解説を生成します。

https://www.slideshare.net/slideshow/1-ftma15/47697911

https://note.com/teriyaki_ch/n/n77428e4462b6

### 処理手順

- arXiv URLからプレプリントをダウンロード
- base64形式に変換後
- GPT-4oに渡して解説を生成

### 実装

```py
def download_paper(arxiv_url: str, save_dir: str) -> str:
    """
    arXivから論文をダウンロードする関数

    Args:
        arxiv_url (str): ダウンロードする論文のarXivのURL
        save_dir (str): 論文を保存するディレクトリのパス

    Returns:
        str: ダウンロードした論文のPDFファイルのパス
    """
    paper_id = arxiv_url.split("/")[-1]
    result = arxiv.Search(id_list=[paper_id])
    paper = next(result.results())

    os.makedirs(save_dir, exist_ok=True)
    filename = f"{paper_id}.pdf"
    pdf_path = os.path.join(save_dir, filename)
    paper.download_pdf(dirpath=save_dir, filename=filename)

    return pdf_path

def generate_paper_summary_ochiai(images: list, arxiv_url: str) -> str:
    """
    落合メソッドで論文の要約を生成する関数

    Args:
        images (list): base64エンコードされた論文の画像のリスト
        arxiv_url (str): 論文のarXivのURL

    Returns:
        str: 生成された論文の要約
    """
    response = openai_client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "system",
                "content": """あなたは優秀な研究者です。提供された論文の画像を元に以下のフォーマットに従って論文の解説を行ってください。

# {論文タイトル}

date: {YYYY-MM-DD}
categories: {論文のカテゴリ}

## 1. どんなもの？
## 2. 先行研究と比べてどこがすごいの？
## 3. 技術や手法の"キモ"はどこにある？
## 4. どうやって有効だと検証した？
## 5. 議論はあるか？
## 6. 次に読むべき論文はあるか？
## 7. 想定される質問と回答
## 論文情報・リンク
- [著者，"タイトル，" ジャーナル名 voluem no.，ページ，年](論文リンク)
""",
            },
            {
                "role": "user",
                "content": [
                    f"論文URL: {arxiv_url}",
                    *map(
                        lambda x: {
                            "type": "image_url",
                            "image_url": {
                                "url": f"data:image/jpg;base64,{x}",
                                "detail": "low",
                            },
                        },
                        images,
                    ),
                    {
                        "type": "text",
                        "text": "論文の解説はMarkdown形式かつ日本語で記述してください。",
                    },
                ],
            },
        ],
    )
    print(response.usage)
    return response.choices[0].message.content

def pdf_to_base64(pdf_path: str) -> list:
    """
    PDFをbase64エンコードされた画像のリストに変換する関数

    Args:
        pdf_path (str): 変換するPDFファイルのパス

    Returns:
        list: base64エンコードされた画像のリスト
    """
    images = pdf2image.convert_from_path(pdf_path)

    base64_images = []

    for image in images:
        buffered = BytesIO()
        image.save(buffered, format="jpeg")
        img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
        base64_images.append(img_str)

    return base64_images

formatted_date = datetime.now().strftime("%Y%m%d_%H%M%S")
save_dir_name = os.path.join(tempfile.mkdtemp(), formatted_date)

pdf_path = download_paper(arxiv_url, save_dir_name)
images = pdf_to_base64(pdf_path)
paper_summary_ochiai = generate_paper_summary_ochiai(images, arxiv_url)
```

## 実装紹介: 数式や図表を抽出し解説生成

LayoutParser ( https://github.com/Layout-Parser/layout-parser ) の事前学習済みモデルを使い、数式や図表を抽出して解説を生成します。
LayoutParser のモデルは以下に一覧があります。

https://layout-parser.readthedocs.io/en/latest/notes/modelzoo.html

今回は図表の抽出は PubLayNet Dataset で学習されたものを使い、数式の抽出はMath Formula Detection(MFD) Dataset で学習されたものを使います。

### 処理手順

- LayoutParserによる抽出
- GPT-4oによる解説生成 (解説生成時にコンテキストとして、論文から抽出したテキストを全部渡しています)
    - コストを削りたい場合、サマリでもよいと思います。論文1ページあたり1K tokensくらい消費するので、1ページ1円くらい. Attention Is All You Need の場合, 15ページで約11K tokensで図表10枚, 数式3枚程度処理したので130円くらいかかっています。

### 実装

```py

def extract_figures_and_tables(pdf_path: str, save_dir: str) -> list:
    """
    PDFから図表を抽出する関数

    Args:
        pdf_path (str): 図表を抽出するPDFファイルのパス
        save_dir (str): 抽出した画像を保存するディレクトリのパス

    Returns:
        list: 抽出した図表の情報を格納したリスト
    """
    model = lp.Detectron2LayoutModel(
        "lp://PubLayNet/faster_rcnn_R_50_FPN_3x/config",
        extra_config=["MODEL.ROI_HEADS.SCORE_THRESH_TEST", 0.8],
        label_map={0: "Text", 1: "Title", 2: "List", 3: "Table", 4: "Figure"},
    )

    images = pdf2image.convert_from_path(pdf_path)

    figure_and_table_data = []
    os.makedirs(save_dir, exist_ok=True)

    for i, image in enumerate(images):
        image_np = np.array(image)
        image_np = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
        layout = model.detect(image_np)

        for j, block in enumerate(layout):
            if block.type in ["Table", "Figure"]:
                segment_image = block.pad(left=5, right=5, top=5, bottom=5).crop_image(
                    image_np
                )
                image_path = os.path.join(save_dir, f"page_{i}_block_{j}.jpg")
                cv2.imwrite(
                    image_path, segment_image, [int(cv2.IMWRITE_JPEG_QUALITY), 95]
                )
                with open(image_path, "rb") as f:
                    base64_image = base64.b64encode(f.read()).decode("utf-8")
                figure_and_table_data.append(
                    {"path": image_path, "base64": base64_image, "type": block.type}
                )

    return figure_and_table_data


def extract_formulas(pdf_path: str, save_dir: str) -> list:
    """
    PDFから数式を抽出する関数

    Args:
        pdf_path (str): 数式を抽出するPDFファイルのパス
        save_dir (str): 抽出した画像を保存するディレクトリのパス

    Returns:
        list: 抽出した数式の情報を格納したリスト
    """
    model = lp.Detectron2LayoutModel(
        "lp://MFD/faster_rcnn_R_50_FPN_3x/config",
        extra_config=["MODEL.ROI_HEADS.SCORE_THRESH_TEST", 0.8],
        label_map={1: "Equation"},
    )

    images = pdf2image.convert_from_path(pdf_path)

    figure_and_table_data = []
    os.makedirs(save_dir, exist_ok=True)

    for i, image in enumerate(images):
        image_np = np.array(image)
        image_np = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
        layout = model.detect(image_np)

        for j, block in enumerate(layout):
            if block.type in ["Equation"]:
                segment_image = block.pad(left=5, right=5, top=5, bottom=5).crop_image(
                    image_np
                )
                image_path = os.path.join(save_dir, f"page_{i}_block_{j}.jpg")
                cv2.imwrite(
                    image_path, segment_image, [int(cv2.IMWRITE_JPEG_QUALITY), 95]
                )
                with open(image_path, "rb") as f:
                    base64_image = base64.b64encode(f.read()).decode("utf-8")
                figure_and_table_data.append(
                    {"path": image_path, "base64": base64_image, "type": block.type}
                )

    return figure_and_table_data

def generate_image_explanation(image: str, pdf_text: str) -> str:
    """
    画像の説明を生成する関数

    Args:
        image (str): base64エンコードされた画像
        pdf_text (str): 論文から抽出したテキスト

    Returns:
        str: 生成された画像の説明
    """
    response = openai_client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "system",
                "content": f"あなたは優秀な研究者です。論文から抽出したテキスト情報は以下です:\n{pdf_text}\n\n提供された論文の画像の示す意味を説明してください。",
            },
            {
                "role": "user",
                "content": [
                    "これは論文から抽出した画像です",
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/jpg;base64,{image}",
                        },
                    },
                    {
                        "type": "text",
                        "text": "説明はMarkdown形式かつ日本語で記述してください。",
                    },
                ],
            },
        ],
    )
    print(response.usage)
    return response.choices[0].message.content


def generate_formula_explanation(image: str, pdf_text: str) -> str:
    """
    数式の説明を生成する関数

    Args:
        image (str): base64エンコードされた数式の画像
        pdf_text (str): 論文から抽出したテキスト

    Returns:
        str: 生成された数式の説明
    """
    response = openai_client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "system",
                "content": f"あなたは優秀な研究者です。論文から抽出したテキスト情報は以下です:\n{pdf_text}\n\n提供された論文の数式部分の画像を提供するので、この数式の解説を行ってください",
            },
            {
                "role": "user",
                "content": [
                    "これは論文から抽出した画像です",
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/jpg;base64,{image}",
                            "detail": "low",
                        },
                    },
                    {
                        "type": "text",
                        "text": "数式はmarkdown内で使えるmathjaxを用い$$で囲んでください。解説はMarkdown形式かつ日本語で記述してください。Markdownは```で囲まないでください",
                    },
                ],
            },
        ],
    )
    print(response.usage)
    return response.choices[0].message.content
```

## 課題

### 数式や図表の処理が遅い + 重い

わざわざレイアウト検出モデルを使っているため、遅いです。
ちゃんとした論文読解支援アプリケーションを作る場合は、数式部分をユーザーに矩形選択させ、https://github.com/RapidAI/RapidLatexOCR 等を使ってLaTeX形式に変換したあと言語モデルに投げるとよいでしょう。単純に矩形選択 -> 選択部分を画像として GPT-4o あるいは Gemini 1.5 Pro に投げるのもよいかもしれません。

あるいは https://github.com/breezedeus/Pix2Text 等を使い、PDF を Markdown 形式に一気に変換してしまうのもよいアプローチだと思います。さいきんは https://github.com/microsoft/ArxivFormula などのデータセットも登場してきているので、独自のモデルもずいぶん作りやすくなってきました。図表に関しても、TATR (Table Transformer, https://github.com/microsoft/table-transformer) 等を使っても良いと思います。個人的に検証中ですが, https://github.com/deepdoctection/deepdoctection が最近のDocument AI系の良いラッパーとして使えそうです。

ちなみに数式や図表の解説を別枠立てしているのは、論文を画像としてまとめて送ったときには数式をちゃんと理解していないためです。「数式部分を個々に解説してください」とするとhallucinationが容易に起こります。
Claude3 Opus や Gemini 1.5 Proではちゃんとテストしていませんが、もしかするとそちらのほうがよい結果になったりするかもしれません。どちらにせよ1年後にはこういう小細工もクラウド上にホスティングされた大規模言語モデルを利用する場合は不要になる気がします。

### 図表においてキャプションが有効活用できていない

LayoutParserでのレイアウト検出では、図や表の該当部分のみ抽出され、キャプションを検出できていません。DocXChainを使えばキャプション部分を検出できるため、推論の精度向上を図ることができます。

![AdvancedLiterateMachinery_Applications_DocXChain_at_main_·_AlibabaResearch_AdvancedLiterateMachinery_·_GitHub.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/1742e3c8-f781-72bc-4bdf-ab0b9755735a.png)

https://github.com/AlibabaResearch/AdvancedLiterateMachinery/tree/main/Applications/DocXChain

### ReferenceやAppendixが膨大になる場合の対処をしていない

ときに論文では著者名、Reference、Appendix等が膨大になる場合があります (HEP系の実験論文では著者が膨大になることがままあります)。そうしたときに省略する機構を備えていません。単純にパターンマッチングしたりレイアウト検出モデルでいい感じにやったりしたほうが良い場合もありそうです。

### (Gradioにおいて) インライン数式を表示できない

https://www.gradio.app/docs/gradio/markdown コンポーネントで表示しているのですが、インライン数式 (シングル`$`で囲むやつ) がうまく処理できていません。`latex_delimiters` オプションを適切に使えばよさそうなのですが、一旦放置しています。

## おわりに

GPT-4oを使った論文解説生成を今回は行いました。
画像理解能力が向上しトークン効率が良いため、PDF等の処理では画像として取り扱うケースも増えてきそうです。

## 関連

https://qiita.com/sakasegawa/items/f50aae7f3acf475411aa

https://blog.shikoan.com/arxiv_rag/

https://zenn.dev/iyo/articles/dd1151d3c9d129

# Appendix: 生成された論文解説

# Attention Is All You Need
date: 2017-06-02 categories: 自然言語処理、深層学習

## 1. どんなもの？
この論文は、トランスフォーマーモデルを紹介しています。トランスフォーマーは、シーケンス変換問題（例: 機械翻訳）に特化して設計された新しいニューラルネットワークアーキテクチャであり、全くリカレント（再帰）や畳み込み層を使用しません。代わりに、自己注意メカニズムと完全に接続された層に基づいています。

## 2. 先行研究と比べてどこがすごいの？
トランスフォーマーモデルは、従来のRNNやLSTMなどのシーケンスモデルと異なり、並列化が容易かつ計算資源の効率的な利用が可能です。これは、特に長文や複雑なシーケンスデータに対する処理能力を大幅に向上させ、訓練時間の短縮を実現します。また、その高い柔軟性と性能により、さまざまなタスクでSOTA（State-Of-The-Art）パフォーマンスを達成しています。

## 3. 技術や手法の"キモ"はどこにある？
トランスフォーマーの技術的な核心は自己注意メカニズムです。自己注意は、出力シーケンスの各要素が入力シーケンスの他の全ての要素とどう関連するかを直接モデリングします。これにより、長距離依存関係の取り扱いが効率的になり、リカレント層に依存する必要がなくなりました。

## 4. どうやって有効だと検証した？
トランスフォーマーモデルは、英語からドイツ語、および英語からフランス語への翻訳タスクで検証され、これらのベンチマークデータセットにおいて従来のSOTAモデルを上回る性能を示しました。また、モデルの異なる構成要素の影響を調べるために、各種のアブレーションスタディが行われました。

## 5. 議論はあるか？
トランスフォーマーモデルのシンプルさと効率性は高く評価されていますが、それでも大規模データセットと計算資源を必要とする点や、自己注意メカニズムに特有の欠点（例: 計算負荷が大きい）なども指摘されています。さらに、モデルの性能向上のためにポジショナルエンコーディングの改良や異なるモデル変種の試行が引き続き議論されています。

## 6. 次に読むべき論文はあるか？
トランスフォーマーに関する次の研究として、特に以下の論文を読むことが推奨されます：

- Devlin et al., 2018, "BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding"
- Vaswani et al., 2018, "Tensor2Tensor for Neural Machine Translation"

## 7. 想定される質問と回答

- Q: トランスフォーマーモデルの主なメリットは何ですか？
- A: 主なメリットは、並列化の容易さ、長距離依存関係処理の効率向上、計算資源の効率的利用です。
- Q: トランスフォーマーモデルの主要な構成要素は何ですか？
- A: 主要な構成要素は、自己注意メカニズムと完全に接続された層です。

## 論文情報・リンク
- [Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Łukasz Kaiser, and Illia Polosukhin, "Attention Is All You Need," 31st Conference on Neural Information Processing Systems (NIPS 2017), Long Beach, CA, USA](https://arxiv.org/abs/1706.03762)

## 数式の説明

### 数式画像0

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/3dc6c7ab-e34a-8d56-3c82-b68b3a5faf73.png)

この数式は「Scaled Dot-Product Attention」を表しています。この手法は、クエリ（$Q$）、キー（$K$）およびバリュー（$V$）のベクトルを使って、注意機構を実現しています。

具体的な手順は次の通りです：

Dot-Product：クエリ行列$Q$とキー行列$K^T$（Kの転置行列）を掛け合わせます。これにより、クエリとキーの間の関連度が計算されます。
Scaling：$\sqrt{d_k}$で割ることによって、数値が大きくなりすぎるのを防ぎ、結果を安定化させます。$d_k$はキーの次元数を表します。
Softmax：その結果をsoftmax関数に通し、各値を0から1の範囲に収め、合計が1になるようにします。これにより、注意の重み付けが行われます。
Weighted Sum：これらの重みを使って、バリュー行列$V$の加重平均を計算します。
これにより、クエリに対する適切な情報が動的に集約されることになります。

### 数式画像1

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/b3d6cd4a-51fe-1b0a-d2bd-f21263bf0830.png)

この数式は、位置毎のフィードフォワードネットワーク（Position-wise Feed-Forward Networks; FFN）の計算方法を示しています。FFNは各位置で独立に適用される全結合ネットワークです。以下は数式の各部分の説明です：

- $x$: 入力ベクトル
- $W_1, W_2$: 重み行列
- $b_1, b_2$: バイアスベクトル
- $\max(0, \cdot$): ReLU活性化関数（Rectified Linear Unit）。入力が0未満なら0を出力し、それ以外の場合はそのままの値を出力します。

FFNは基本的に、以下の2つの線形変換とその間のReLU活性化関数から成ります：

- 入力 $x$ に対して最初の線形変換（重み行列 $W_1$ とバイアス $b_1$ を適用）。これは $xW_1 + b_1$ で表されます。
- この結果に対しReLU活性化関数を適用し、非線形性を導入します：$\max(0, xW_1 + b_1)$
- 次に、この結果に対してもう一つの線形変換を適用します：$(\max(0, xW_1 + b_1))W_2 + b_2$

このようにして、入力ベクトル $x$ が変換され、最終的な出力が得られます。これは各層の出力を計算する1つの方法として、Transformerモデルにおいて用いられます。

### 数式画像2

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/dd728af6-b1c6-706a-5bc1-54f9023b12f1.png)

これらの数式は位置エンコーディング（Positional Encoding）の方法を示しています。位置エンコーディングは、系列データ（たとえば文章）の各位置に何らかの固定情報を与え、モデルが入力の順序情報を理解できるようにするために使用されます。

解説:

- $PE$: Positional Encodingの略。
- $pos$: 位置を示す変数。系列内のトークンの位置を表します。
- $i$: 次元（またはインデックス）を示す変数。
- $d_{model}$: モデルの次元数。

具体的には:

- $PE(pos, 2i)$は、位置 $pos$ に対するエンコーディングの偶数次元$2i$でのサイン関数を用いた計算です。この計算により得られる位置エンコーディングの値はサイン波の変化に基づいており、波長は次元 $i$ に依存します。
- $PE(pos, 2i+1)$ は、位置 $pos$ に対するエンコーディングの奇数次元$2i+1$でのコサイン関数を用いた計算です。この計算も同様に、波長は次元 $i$ に依存します。

これらのサインとコサインの関数により、位置エンコーディングはトークンの順序や相対的な位置情報を持つことができ、モデルが系列データの規則性やパターンを学習する助けになります。この方法を使うことで、モデルは異なる長さの系列データにも対応できます。

数式画像3

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/6baccc7a-ae73-f5dd-fed9-d0878eeae445.png)

この数式は、学習率（learning rate）を調整する方法を示しています。具体的には、モデルの訓練段階における学習率のスケジュールを定義しています。

- $d_{model}$はモデルの次元数を表し、一定のスケールを提供するためのパラメータです。この値が大きいほど、初期の学習率が小さくなります。
- $step\\_num$は現在の訓練ステップ数を表します。ここでは、訓練が進むにつれて学習率がどのように変動するかを管理します。
- $warmup\\_steps$はウォームアップ期間を示し、この期間中は学習率が徐々に増加します。
数式の右側部分

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/8ab64e5c-bac9-086b-1e05-69b664a03573.png)

はウォームアップ期間とそれ以降の学習率を決定するためのもので、2つの値のうち小さい方を取ります。

- $step\\_num^{-0.5}$は訓練が進むにつれて学習率が減少することを表します。
- $step\\_num \cdot warmup\\_steps^{-1.5}$はウォームアップ期間中に学習率が増加することを表します。
最終的に、全体の学習率 $lrate$ はこれらの値に基づき、初期のウォームアップ期間中は学習率が増加し、その後は減少するように調整されます。これにより、初期の訓練段階では大きなステップで探索し、モデルの安定が進むにつれて学習率を小さくしていくというメリットがあります。

## 図表の説明

### 画像0

![ダウンロード (7).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/8d2ae326-a41d-6cd6-dd4e-748d99977b43.jpeg)

この画像は、Transformerモデルのアーキテクチャを示しています。Transformerは、主に自然言語処理タスク（例えば、機械翻訳）で使用されるモデルです。

#### 左側（エンコーダー）

1. Input Embedding: 入力トークンはエンベッディング層で埋め込まれ、連続的なベクトル表現に変換されます。
2. Positional Encoding: 位置エンコーディングが加えられ、入力シーケンスの位置情報を注入します。
3. Multi-Head Attention: 複数の異なる注意機構が並列に実行されます。これは異なる部分に焦点を当てることで、より豊かな表現を学習します。
4. Add & Norm: 残差接続（Add）と層正規化（Norm）が適用されます。
Feed Forward: 全結合層が位置ごとに適用されます。
5. N×（繰り返し）: これらの構造が N 回繰り返されます。

#### 右側（デコーダー）

1. Output Embedding: 出力トークンもエンベッディング層で埋め込まれますが、出力シーケンスは一つ右にシフトされます。
2. Positional Encoding: 位置エンコーディングが加えられ、出力シーケンスの位置情報を注入します。
3. Masked Multi-Head Attention: マスクされたマルチヘッド注意機構により、デコーダーは未来のトークンに注意を払わないようにします。
4. Add & Norm: 残差接続と層正規化が適用されます。
Multi-Head Attention: エンコーダーからの出力に対してマルチヘッド注意が適用されます。
5. Add & Norm: 残差接続と層正規化が再度適用されます。
6. Feed Forward: 全結合層が位置ごとに適用されます。
7. Add & Norm: 再度、残差接続と層正規化が適用されます。
8. N×（繰り返し）: これらの構造が N 回繰り返されます。
9. Linear & Softmax: 最後に線形変換が行われ、ソフトマックス関数で出力トークンの確率が計算されます。

全体的に、Transformerはエンコーダーとデコーダーの両方で自己注意機構に基づくアーキテクチャを持ち、高度に並列化可能である点が特徴です。この特性により、トレーニングおよび推論の効率が大幅に改善されます。

### 画像1

![ダウンロード (8).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/cba69968-8145-4fd4-8f74-74baeb2e49c1.jpeg)

これは論文から抽出された図で、2つの異なる注意機構を説明しています。

#### 左側の図: Scaled Dot-Product Attention (スケールド・ドットプロダクト・アテンション)

1. MatMul (行列積) - クエリ Q とキー K の行列積を計算します。
2. Scale (スケール) - 次元数 dk の平方根でスケーリングします。
3. Mask (オプション, マスク) - 必要に応じて、将来のトークンをマスクする操作を行います。これはデコード時の予測に使用されます。
4. SoftMax (ソフトマックス) - 結果をソフトマックス関数に通し、注意重みを計算します。
5. MatMul (行列積) - 最後に、この注意重みを使って値 V の行列積を計算します。

#### 右側の図: Multi-Head Attention (マルチヘッド・アテンション)

1. Linear (線形変換) - クエリ Q、キー K、値 V をそれぞれ線形変換します。
2. Scaled Dot-Product Attention (スケールド・ドットプロダクト・アテンション) - この計算を h 個の異なるヘッドで並列に実行します。
3. Concat (連結) - 各ヘッドの出力を連結します。
4. Linear (線形変換) - 最後に、連結された出力に対して線形変換を適用します。

右側の図は、マルチヘッド・アテンションが複数のスケールド・ドットプロダクト・アテンションを並列に実行し、さらに多様な特徴を捉える機能を示しています。このプロセスにより、モデルは異なる部分空間の情報を同時に注数することができます。

### 画像2

![ダウンロード (9).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/69e46e5b-dd55-9ade-005f-12d610025a20.jpeg)

この画像は、論文「Attention Is All You Need」から抽出された「Multi-Head Attention（マルチヘッド・アテンション）」の図です。この図は、マルチヘッド・アテンションの構造を説明しています。

#### マルチヘッド・アテンションの各構成要素:

1. Linear（線形変換）: 画像の下部にある3つの「Linear」は、クエリ（Q）、キー（K）、バリュー（V）に対してそれぞれ線形変換を行います。
2. Scaled Dot-Product Attention（スケールド・ドットプロダクト・アテンション）:
中央に位置する紫色のボックスは、スケールド・ドットプロダクト・アテンションを実行する部分です。ここでは、クエリ、キー、バリューの線形変換後のベクトルを用いてアテンションを計算します。
3. h（ヘッドの数）: 図の中にある「h」は、ヘッドの数を表しており、複数のアテンションヘッドが並列で実行されることを示しています。
4. Concat（連結）: アテンションヘッドで得られた出力を連結（コンカテンネーション）する部分です。この処理により、全ヘッドの出力をまとめたベクトルが得られます。
5. Linear（線形変換）: 最上部の「Linear」は、連結後のベクトルに対して再度線形変換を行います。

#### マルチヘッド・アテンションの流れ:

1. クエリ（Q）、キー（K）、バリュー（V）それぞれに線形変換を適用。
2. 複数のスケールド・ドットプロダクト・アテンションを並列に適用。
3. 得られた複数のアテンションヘッドの出力を連結。
4. 連結した出力に対して再度線形変換を適用して最終的な出力を得る。

この構造により、マルチヘッド・アテンションは異なる部分空間に並行して注意を払うことができ、モデルの性能と表現力を高めることが可能です。

### 画像3

![ダウンロード (10).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/6dfac78f-9454-298a-786c-5b5e456d6234.jpeg)

この画像は、論文内の表を示しています。この表は、異なるレイヤータイプに対する層ごとの計算複雑度、逐次操作数、及び最大パス長を比較しています。

- Self-Attention (自己注意機構):
    - 層ごとの複雑度: $O(n^2 \cdot d)$
    - 逐次操作数: $O(1)$
    - 最大パス長: $O(1)$
- Recurrent (リカレント層):
    - 層ごとの複雑度: $O(n \cdot d^2)$
    - 逐次操作数: $O(n)$
    - 最大パス長: $O(n)$
- Convolutional (畳み込み層):
    - 層ごとの複雑度: $O(k \cdot n \cdot d^2)$
    - 逐次操作数: $O(1)$
    - 最大パス長: $O(\log_k(n))$
- Self-Attention (restricted) (制限付き自己注意機構):
    - 層ごとの複雑度: $O(r \cdot n \cdot d)$
    - 逐次操作数: $O(1)$
    - 最大パス長: $O(n/r)$

この表は、特に自己注意機構が他のアーキテクチャ（リカレントや畳み込み）と比較して、計算効率や依存関係の取り扱いの面でどのような利点を持つかを示しています。

### 画像4

![ダウンロード (11).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/ed2a0890-f2b3-42ec-06e3-db5b4d48260d.jpeg)

この画像は、機械翻訳モデルの性能とトレーニングコストに関する表です。横軸にはモデルの名前が記載されており、縦軸にはBLEUスコアとトレーニングコスト（FLOPs、浮動小数点演算数）が記載されています。

#### モデル一覧

- ByteNet
- Deep-Att + PosUnk
- GNMT + RL
- ConvS2S
- MoE
- Deep-Att + PosUnk Ensemble
- GNMT + RL Ensemble
- ConvS2S Ensemble
- Transformer (base model)
- Transformer (big)

#### BLEUスコア

BLEUスコアは、モデルの翻訳精度を評価するための指標です。ここでは、英語からドイツ語（EN-DE）と英語からフランス語（EN-FR）の翻訳タスクにおけるスコアが示されています。

#### トレーニングコスト

トレーニングコスト（FLOPs）はモデルのトレーニングに必要な計算量を示しています。数値が大きいほどトレーニングにかかる計算リソースが多く必要となります。

#### 主なポイント

Transformer (base model)はEN-DEで27.3、EN-FRで38.1のBLEUスコアを記録し、トレーニングコストは3.3 × 10^18 FLOPs（EN-DE）と2.3 × 10^19 FLOPs（EN-FR）です。
Transformer (big)はEN-DEで28.4、EN-FRで41.8のBLEUスコアを記録し、他のモデルよりも優れた性能を示しています。トレーニングコストは2.3 × 10^19 FLOPs（EN-FR）のみ記載されています。

#### モデル間の比較

Transformerモデルは、他のモデル（特にEnsembleモデル）に比べて高いBLEUスコアを示し、トレーニングコストも比較的低いことが分かります。
Ensembleモデルは単一モデルよりも高いBLEUスコアを示すことが多いが、トレーニングコストは大幅に増加します。
この表は、Transformerモデルが他の最新の翻訳モデルよりも効率的で高性能であることを示しています。

### 画像5

![ダウンロード (12).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/6b100998-d30b-df2e-33df-8cc09c413e23.jpeg)

この画像は「Attention Is All You Need」論文の表の一部であり、異なるモデル変種の性能評価を比較しています。表の内容は以下の通りです：

この表は、異なる設定のトランスフォーマーモデルの性能（Perplexity、BLEUスコア）やパラメータ数を比較しています。変種ごとの結果は、BLEUスコアやパラメータ数、およびPerplexity (PPL) などを通じてモデルの効果を分析したものです。

### 画像6

![ダウンロード (13).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/f285a48e-6d1e-0dea-5d62-9cdfdde9a3a2.jpeg)

この画像は、英語構文解析のパーサーに関する実験結果を示しています。表は以下のように構成されています：

- Parser: 解析器の名前と発表年、および引用文献が示されています。
- Training: 学習方法の種類（例：WSJのみ、半教師あり、マルチタスク、生成的）を示しています。
- WSJ 23 F1: 有名なPenn TreebankのWall Street Journalセクション23におけるF1スコアを示しています。このスコアは解析器の性能を評価するために使用されます。

具体的なデータは以下の通りです：

1. Vinyals & Kaiser et al. (2014):
    - 学習：WSJ only, discriminative
    - F1スコア：88.3
2. Petrov et al. (2006):
    - 学習：WSJ only, discriminative
    - F1スコア：90.4
3. Zhu et al. (2013):
    - 学習：WSJ only, discriminative
    - F1スコア：90.4
4. Dyer et al. (2016):
    - 学習：WSJ only, discriminative
    - F1スコア：91.7
5. Transformer (4 layers):
    - 学習：WSJ only, discriminative
    - F1スコア：91.3
6. Zhu et al. (2013):
    - 学習：semi-supervised
    - F1スコア：91.3
7. Huang & Harper (2009):
    - 学習：semi-supervised
    - F1スコア：91.3
8. McClosky et al. (2006):
    - 学習：semi-supervised
    - F1スコア：92.1
9. Vinyals & Kaiser et al. (2014):
    - 学習：semi-supervised
    - F1スコア：92.1
10. Transformer (4 layers):
    - 学習：semi-supervised
    - F1スコア：92.7
11. Luong et al. (2015):
    - 学習：multi-task
    - F1スコア：93.0
12. Dyer et al. (2016):
    - 学習：generative
    - F1スコア：93.3

この表から、Transformerモデルが他のいくつかのモデルと同様、非常に高いF1スコアを達成していることがわかります。特にsemi-supervisedの設定では、他のすべての解析器よりも高いスコア（92.7）を記録しています。

### 画像7

![ダウンロード (14).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/b31555a6-2639-2a1e-dbba-cf150cceb651.jpeg)

この画像は、論文「Attention Is All You Need」におけるTransformerモデルの自己注意メカニズムの例を示しています。この図はエンコーダの第5層の自己注意の分布を視覚化したもので、特定の単語が他の単語にどのように注意を向けているかを示しています。

#### 画像の説明

- テキストの内容: テキストは「It is in this spirit that a majority of American governments have passed new laws since 2009 making the registration or voting process more difficult.」で、着目する単語は「making」です。
- 線の意味: 異なる色の線は、異なる注意ヘッドがどの単語に注意を向けているかを示しています。この場合、「making」が他の単語（特に「more」や「difficult」など）に強い注意を向けていることが示されています。
- 注意の強さ: 線の太さや色の濃さは、特定の単語への注意の強さを表しています。

#### 注意メカニズムの重要性

- 長距離依存性のモデル化: この図は、Transformerモデルがどのように長距離の依存関係を自己注意メカニズムでモデル化するかを示しています。具体的には、「making」という動詞が「more difficult」という形容詞フレーズに強く依存していることが視覚化されています。
- 多頭注意機構（Multi-Head Attention）: 複数の注意ヘッドが異なる部分に注意を向けているのがわかります。これにより、モデルが異なる情報に同時に注意を向けることができ、多様な特徴を捉えることが可能になります。
この図はTransformerの中での注意の分布を理解する上で非常に重要であり、特に自己注意メカニズムが長距離依存性をどのように捉えているかを示す良い例となっています。

### 画像8

![ダウンロード (15).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/33524108-d829-2ed5-c0fb-83ccbb4fcf4f.jpeg)

この画像は、「Attention Is All You Need」論文における注意機構（Attention Mechanism）の可視化の一例です。画像は特定の単語に対してモデルがどのように注意（Attention）を払っているかを示しています。具体的には、各注意ヘッド（Attention Head）が文章内の異なる単語に焦点を当てている様子が表示されています。

#### 画像の説明:

- 上部図（Attention Visualization of Layer 5 Head 5）
    - 単語 'its' から別の単語への注意の流れが視覚化されています。
    - 複数の線が異なる単語に向かって伸びており、紫色の線の濃さが注意の強度を表しています。
    - 例えば、'its' が強く注意を払っている単語が特定の場所に集中しています。
- 下部図（Attention Isolation for 'its' in Layer 5 Heads 5 and 6）
    - 頭5と頭6（複数の注意ヘッド対応）の単語 'its' に対する注意の分布が個別に表示されています。
    - 線の集中度や太さが、それぞれの注意ヘッドが異なる単語に対してどの程度注意を払っているかを示しています。

このビジュアライゼーションは、Transformerモデルがどの単語に注目して文脈を理解しているかを理解するための重要な手がかりとなります。特に、文の構造や意味を掴むためにどのように注意が分散しているかが分かります。

### 画像9

![ダウンロード (16).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958603/d1b8ac4d-fbd3-5b59-44c5-4ca456285404.jpeg)

この画像は、Attentionメカニズムを使用しているトランスフォーマーモデルが、文の中でどのように異なる単語に注意を向けるかを視覚化したものです。画像に示されている2つの図は、トランスフォーマーモデルの異なるAttentionヘッドが注目している場所を示しています。

上部の緑色の線で示された図と、下部の赤色の線で示された図のいずれも、文中の「its」という単語に対するAttentionの重みを具体的に可視化しています。線の太さはAttentionの強さを表しており、太い線ほど強いAttentionを示しています。

文の構造や意味を理解するために、異なるAttentionヘッドが異なる単語間の関係に注目している様子が分かります。これにより、文の解析や翻訳などの自然言語処理タスクを行う際に、文の異なる部分がどのように関連しているのかをモデルが捉えていることが示されています。