diff --git a/src/AI/AI-llm-architecture/0.-basic-llm-concepts.md b/src/AI/AI-llm-architecture/0.-basic-llm-concepts.md
index 7eab5e2d7..1908bcd87 100644
--- a/src/AI/AI-llm-architecture/0.-basic-llm-concepts.md
+++ b/src/AI/AI-llm-architecture/0.-basic-llm-concepts.md
@@ -2,7 +2,7 @@
## プリトレーニング
-プリトレーニングは、大規模言語モデル(LLM)を開発する際の基礎的なフェーズであり、モデルは膨大で多様なテキストデータにさらされます。この段階で、**LLMは言語の基本的な構造、パターン、ニュアンスを学びます**。これには文法、語彙、構文、文脈的関係が含まれます。この広範なデータを処理することで、モデルは言語と一般的な世界知識の広い理解を獲得します。この包括的な基盤により、LLMは一貫性があり、文脈に関連したテキストを生成することができます。その後、このプリトレーニングされたモデルはファインチューニングを受け、特定のタスクやドメインに適応するために専門的なデータセットでさらにトレーニングされ、ターゲットアプリケーションにおけるパフォーマンスと関連性が向上します。
+プリトレーニングは、大規模言語モデル(LLM)を開発する際の基礎的なフェーズであり、モデルは膨大で多様なテキストデータにさらされます。この段階で、**LLMは言語の基本的な構造、パターン、ニュアンスを学びます**。これには文法、語彙、構文、文脈的関係が含まれます。この広範なデータを処理することにより、モデルは言語と一般的な世界知識の広い理解を獲得します。この包括的な基盤により、LLMは一貫性があり、文脈に関連したテキストを生成することができます。その後、このプリトレーニングされたモデルはファインチューニングを受け、特定のタスクやドメインに適応するために専門的なデータセットでさらにトレーニングされ、ターゲットアプリケーションにおけるパフォーマンスと関連性が向上します。
## 主なLLMコンポーネント
@@ -14,7 +14,7 @@
- **隠れ次元**:ニューラルネットワーク内の隠れ層のサイズです。
- **層の数(深さ)**:モデルが持つ層の数です。LLMは通常、数十の層を使用します。
- **アテンションヘッドの数**:トランスフォーマーモデルにおいて、各層で使用される別々のアテンションメカニズムの数です。LLMは通常、数十のヘッドを使用します。
-- **ドロップアウト**:ドロップアウトは、トレーニング中に削除されるデータの割合(確率が0になる)に似たものです。**オーバーフィッティングを防ぐ**ために使用されます。LLMは通常、0-20%の範囲で使用します。
+- **ドロップアウト**:ドロップアウトは、トレーニング中に削除されるデータの割合(確率が0になる)に似たもので、**オーバーフィッティングを防ぐ**ために使用されます。LLMは通常、0-20%の範囲で使用します。
GPT-2モデルの構成:
```json
@@ -34,7 +34,7 @@ PyTorchにおいて、**テンソル**は基本的なデータ構造であり、
### Mathematical Concept of Tensors
-- **スカラー**: ランク0のテンソルで、単一の数値(ゼロ次元)を表します。例: 5
+- **スカラー**: ランク0のテンソルで、単一の数値を表します(ゼロ次元)。例: 5
- **ベクトル**: ランク1のテンソルで、数値の一次元配列を表します。例: \[5,1]
- **行列**: ランク2のテンソルで、行と列を持つ二次元配列を表します。例: \[\[1,3], \[5,2]]
- **高次ランクテンソル**: ランク3以上のテンソルで、より高次元のデータを表します(例: カラー画像のための3Dテンソル)。
@@ -165,7 +165,7 @@ ADでは、計算は**計算グラフ**のノードとして表され、各ノ
### PyTorchにおける自動微分の実装
-さて、PyTorchがこのプロセスをどのように自動化するかを見てみましょう。
+では、PyTorchがこのプロセスをどのように自動化するかを見てみましょう。
```python
pythonCopy codeimport torch
import torch.nn.functional as F
@@ -266,9 +266,9 @@ print(f"Gradient of {name}: {param.grad}")
```
このコードでは:
-- **フォワードパス:** ネットワークの出力を計算します。
-- **バックワードパス:** `loss.backward()` は損失に対するすべてのパラメータの勾配を計算します。
-- **パラメータ更新:** `optimizer.step()` は計算された勾配に基づいてパラメータを更新します。
+- **フォワードパス:** ネットワークの出力を計算します。
+- **バックワードパス:** `loss.backward()` は損失に対するすべてのパラメータの勾配を計算します。
+- **パラメータ更新:** `optimizer.step()` は計算された勾配に基づいてパラメータを更新します。
### **5. バックワードパスの理解**
@@ -280,6 +280,6 @@ print(f"Gradient of {name}: {param.grad}")
### **6. 自動微分の利点**
-- **効率性:** 中間結果を再利用することで冗長な計算を回避します。
-- **正確性:** 機械精度までの正確な導関数を提供します。
-- **使いやすさ:** 導関数の手動計算を排除します。
+- **効率性:** 中間結果を再利用することで冗長な計算を回避します。
+- **精度:** 機械精度までの正確な導関数を提供します。
+- **使いやすさ:** 導関数の手動計算を排除します。
diff --git a/src/AI/AI-llm-architecture/1.-tokenizing.md b/src/AI/AI-llm-architecture/1.-tokenizing.md
index 984e4261b..50b4c62ce 100644
--- a/src/AI/AI-llm-architecture/1.-tokenizing.md
+++ b/src/AI/AI-llm-architecture/1.-tokenizing.md
@@ -1,13 +1,13 @@
-# 1. トークン化
+# 1. トークナイジング
-## トークン化
+## トークナイジング
-**トークン化**は、テキストなどのデータを小さく管理しやすい部分、すなわち_トークン_に分解するプロセスです。各トークンには一意の数値識別子(ID)が割り当てられます。これは、特に自然言語処理(NLP)において、テキストを機械学習モデルで処理するための準備において基本的なステップです。
+**トークナイジング**は、テキストなどのデータを小さく管理しやすい部分、すなわち_トークン_に分解するプロセスです。各トークンには一意の数値識別子(ID)が割り当てられます。これは、特に自然言語処理(NLP)において、テキストを機械学習モデルで処理するための準備において基本的なステップです。
> [!TIP]
> この初期段階の目標は非常にシンプルです:**入力を意味のある方法でトークン(ID)に分割すること**。
-### **トークン化の仕組み**
+### **トークナイジングの仕組み**
1. **テキストの分割:**
- **基本トークナイザー:** シンプルなトークナイザーは、テキストを個々の単語や句読点に分割し、スペースを削除することがあります。
@@ -16,7 +16,7 @@
トークン: `["Hello", ",", "world", "!"]`
2. **語彙の作成:**
- トークンを数値IDに変換するために、**語彙**が作成されます。この語彙はすべてのユニークなトークン(単語や記号)をリストし、それぞれに特定のIDを割り当てます。
-- **特別なトークン:** これらは、さまざまなシナリオに対処するために語彙に追加される特別な記号です:
+- **特別なトークン:** さまざまなシナリオに対処するために語彙に追加される特別な記号です:
- `[BOS]`(シーケンスの開始):テキストの開始を示します。
- `[EOS]`(シーケンスの終了):テキストの終了を示します。
- `[PAD]`(パディング):バッチ内のすべてのシーケンスを同じ長さにするために使用されます。
@@ -29,9 +29,9 @@
`"Bye, world!"` → `["[UNK]", ",", "world", "!"]` → `[987, 455, 78, 467]`\
_(`[UNK]`がID `987`であると仮定)_
-### **高度なトークン化手法**
+### **高度なトークナイジング手法**
-基本的なトークナイザーはシンプルなテキストにはうまく機能しますが、大きな語彙や新しいまたは珍しい単語の処理には限界があります。高度なトークン化手法は、テキストを小さなサブユニットに分解したり、トークン化プロセスを最適化したりすることで、これらの問題に対処します。
+基本的なトークナイザーはシンプルなテキストにはうまく機能しますが、大きな語彙や新しいまたは珍しい単語の処理には限界があります。高度なトークナイジング手法は、テキストを小さなサブユニットに分解したり、トークナイジングプロセスを最適化したりすることでこれらの問題に対処します。
1. **バイトペアエンコーディング(BPE):**
- **目的:** 語彙のサイズを削減し、珍しいまたは未知の単語を頻繁に出現するバイトペアに分解することで処理します。
@@ -43,10 +43,10 @@ _(`[UNK]`がID `987`であると仮定)_
- すべての単語が既存のサブワードトークンを組み合わせることで表現できるため、`[UNK]`トークンの必要がなくなります。
- より効率的で柔軟な語彙。
- _例:_\
-`"playing"`は、`"play"`と`"ing"`が頻繁なサブワードであれば、`["play", "ing"]`としてトークン化されるかもしれません。
+`"playing"`は、`"play"`と`"ing"`が頻繁なサブワードであれば、`["play", "ing"]`としてトークナイジングされるかもしれません。
2. **WordPiece:**
- **使用モデル:** BERTのようなモデル。
-- **目的:** BPEと同様に、未知の単語を処理し、語彙のサイズを削減するために単語をサブワードユニットに分解します。
+- **目的:** BPEと似ており、未知の単語を処理し、語彙のサイズを削減するために単語をサブワードユニットに分解します。
- **仕組み:**
- 個々の文字の基本語彙から始まります。
- トレーニングデータの尤度を最大化する最も頻繁なサブワードを反復的に追加します。
@@ -55,19 +55,19 @@ _(`[UNK]`がID `987`であると仮定)_
- 管理可能な語彙サイズと単語を効果的に表現することのバランスを取ります。
- 珍しい単語や複合語を効率的に処理します。
- _例:_\
-`"unhappiness"`は、語彙に応じて`["un", "happiness"]`または`["un", "happy", "ness"]`としてトークン化されるかもしれません。
+`"unhappiness"`は、語彙に応じて`["un", "happiness"]`または`["un", "happy", "ness"]`としてトークナイジングされるかもしれません。
3. **ユニグラム言語モデル:**
- **使用モデル:** SentencePieceのようなモデル。
- **目的:** 最も可能性の高いサブワードトークンのセットを決定するために確率モデルを使用します。
- **仕組み:**
- 潜在的なトークンの大きなセットから始まります。
- トレーニングデータのモデルの確率を最も改善しないトークンを反復的に削除します。
-- 各単語が最も可能性の高いサブワードユニットで表現される語彙を最終化します。
+- 各単語が最も確率の高いサブワードユニットで表現される語彙を最終化します。
- **利点:**
- 柔軟で、より自然に言語をモデル化できます。
-- より効率的でコンパクトなトークン化をもたらすことがよくあります。
+- より効率的でコンパクトなトークナイジングを実現することが多いです。
- _例:_\
-`"internationalization"`は、`["international", "ization"]`のような小さく意味のあるサブワードにトークン化されるかもしれません。
+`"internationalization"`は、`["international", "ization"]`のような小さく意味のあるサブワードにトークナイジングされるかもしれません。
## コード例
diff --git a/src/AI/AI-llm-architecture/2.-data-sampling.md b/src/AI/AI-llm-architecture/2.-data-sampling.md
new file mode 100644
index 000000000..5b7d3bba8
--- /dev/null
+++ b/src/AI/AI-llm-architecture/2.-data-sampling.md
@@ -0,0 +1,233 @@
+# 2. データサンプリング
+
+## **データサンプリング**
+
+**データサンプリング**は、GPTのような大規模言語モデル(LLM)のトレーニングのためにデータを準備する際の重要なプロセスです。これは、モデルが前の単語に基づいて次の単語(またはトークン)を予測する方法を学ぶために使用する入力とターゲットのシーケンスにテキストデータを整理することを含みます。適切なデータサンプリングは、モデルが言語パターンと依存関係を効果的に捉えることを保証します。
+
+> [!TIP]
+> この第二段階の目標は非常にシンプルです:**入力データをサンプリングし、通常は特定の長さの文にデータセットを分け、期待される応答も生成してトレーニングフェーズのために準備します。**
+
+### **データサンプリングが重要な理由**
+
+GPTのようなLLMは、前の単語によって提供されるコンテキストを理解することによってテキストを生成または予測するようにトレーニングされています。これを達成するためには、トレーニングデータは、モデルが単語のシーケンスとその後の単語との関係を学べるように構造化されている必要があります。この構造化されたアプローチにより、モデルは一般化し、一貫性があり文脈に関連したテキストを生成することができます。
+
+### **データサンプリングの主要概念**
+
+1. **トークン化:** テキストをトークン(例:単語、サブワード、または文字)と呼ばれる小さな単位に分解すること。
+2. **シーケンスの長さ(max_length):** 各入力シーケンス内のトークンの数。
+3. **スライディングウィンドウ:** トークン化されたテキストの上をウィンドウを移動させることによって重複する入力シーケンスを作成する方法。
+4. **ストライド:** スライディングウィンドウが次のシーケンスを作成するために前進するトークンの数。
+
+### **ステップバイステップの例**
+
+データサンプリングを説明するために、例を見ていきましょう。
+
+**例文**
+```arduino
+"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
+```
+**トークン化**
+
+基本的な**トークナイザー**を使用して、テキストを単語と句読点に分割すると仮定します:
+```vbnet
+Tokens: ["Lorem", "ipsum", "dolor", "sit", "amet,", "consectetur", "adipiscing", "elit."]
+```
+**パラメータ**
+
+- **最大シーケンス長 (max_length):** 4 トークン
+- **スライディングウィンドウストライド:** 1 トークン
+
+**入力とターゲットシーケンスの作成**
+
+1. **スライディングウィンドウアプローチ:**
+- **入力シーケンス:** 各入力シーケンスは `max_length` トークンで構成されます。
+- **ターゲットシーケンス:** 各ターゲットシーケンスは、対応する入力シーケンスの直後に続くトークンで構成されます。
+2. **シーケンスの生成:**
+
+
ウィンドウ位置 入力シーケンス ターゲットシーケンス 1 ["Lorem", "ipsum", "dolor", "sit"] ["ipsum", "dolor", "sit", "amet,"] 2 ["ipsum", "dolor", "sit", "amet,"] ["dolor", "sit", "amet,", "consectetur"] 3 ["dolor", "sit", "amet,", "consectetur"] ["sit", "amet,", "consectetur", "adipiscing"] 4 ["sit", "amet,", "consectetur", "adipiscing"] ["amet,", "consectetur", "adipiscing", "elit."]
+
+3. **結果の入力とターゲット配列:**
+
+- **入力:**
+
+```python
+[
+["Lorem", "ipsum", "dolor", "sit"],
+["ipsum", "dolor", "sit", "amet,"],
+["dolor", "sit", "amet,", "consectetur"],
+["sit", "amet,", "consectetur", "adipiscing"],
+]
+```
+
+- **ターゲット:**
+
+```python
+[
+["ipsum", "dolor", "sit", "amet,"],
+["dolor", "sit", "amet,", "consectetur"],
+["sit", "amet,", "consectetur", "adipiscing"],
+["amet,", "consectetur", "adipiscing", "elit."],
+]
+```
+
+**視覚的表現**
+
+トークン位置 トークン 1 Lorem 2 ipsum 3 dolor 4 sit 5 amet, 6 consectetur 7 adipiscing 8 elit.
+
+**ストライド1のスライディングウィンドウ:**
+
+- **最初のウィンドウ (位置 1-4):** \["Lorem", "ipsum", "dolor", "sit"] → **ターゲット:** \["ipsum", "dolor", "sit", "amet,"]
+- **2番目のウィンドウ (位置 2-5):** \["ipsum", "dolor", "sit", "amet,"] → **ターゲット:** \["dolor", "sit", "amet,", "consectetur"]
+- **3番目のウィンドウ (位置 3-6):** \["dolor", "sit", "amet,", "consectetur"] → **ターゲット:** \["sit", "amet,", "consectetur", "adipiscing"]
+- **4番目のウィンドウ (位置 4-7):** \["sit", "amet,", "consectetur", "adipiscing"] → **ターゲット:** \["amet,", "consectetur", "adipiscing", "elit."]
+
+**ストライドの理解**
+
+- **ストライド1:** ウィンドウは毎回1トークン前進し、非常に重複したシーケンスを生成します。これにより、文脈関係の学習が向上する可能性がありますが、類似のデータポイントが繰り返されるため、過学習のリスクが高まる可能性があります。
+- **ストライド2:** ウィンドウは毎回2トークン前進し、重複を減らします。これにより冗長性と計算負荷が減少しますが、文脈のニュアンスを見逃す可能性があります。
+- **ストライドがmax_lengthに等しい:** ウィンドウは全ウィンドウサイズ分前進し、重複のないシーケンスを生成します。これによりデータの冗長性が最小限に抑えられますが、シーケンス間の依存関係を学習するモデルの能力が制限される可能性があります。
+
+**ストライド2の例:**
+
+同じトークン化されたテキストと `max_length` が4の場合:
+
+- **最初のウィンドウ (位置 1-4):** \["Lorem", "ipsum", "dolor", "sit"] → **ターゲット:** \["ipsum", "dolor", "sit", "amet,"]
+- **2番目のウィンドウ (位置 3-6):** \["dolor", "sit", "amet,", "consectetur"] → **ターゲット:** \["sit", "amet,", "consectetur", "adipiscing"]
+- **3番目のウィンドウ (位置 5-8):** \["amet,", "consectetur", "adipiscing", "elit."] → **ターゲット:** \["consectetur", "adipiscing", "elit.", "sed"] _(続きがあると仮定)_
+
+## コード例
+
+[https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb) からのコード例を通じて、これをよりよく理解しましょう。
+```python
+# Download the text to pre-train the LLM
+import urllib.request
+url = ("https://raw.githubusercontent.com/rasbt/LLMs-from-scratch/main/ch02/01_main-chapter-code/the-verdict.txt")
+file_path = "the-verdict.txt"
+urllib.request.urlretrieve(url, file_path)
+
+with open("the-verdict.txt", "r", encoding="utf-8") as f:
+raw_text = f.read()
+
+"""
+Create a class that will receive some params lie tokenizer and text
+and will prepare the input chunks and the target chunks to prepare
+the LLM to learn which next token to generate
+"""
+import torch
+from torch.utils.data import Dataset, DataLoader
+
+class GPTDatasetV1(Dataset):
+def __init__(self, txt, tokenizer, max_length, stride):
+self.input_ids = []
+self.target_ids = []
+
+# Tokenize the entire text
+token_ids = tokenizer.encode(txt, allowed_special={"<|endoftext|>"})
+
+# Use a sliding window to chunk the book into overlapping sequences of max_length
+for i in range(0, len(token_ids) - max_length, stride):
+input_chunk = token_ids[i:i + max_length]
+target_chunk = token_ids[i + 1: i + max_length + 1]
+self.input_ids.append(torch.tensor(input_chunk))
+self.target_ids.append(torch.tensor(target_chunk))
+
+def __len__(self):
+return len(self.input_ids)
+
+def __getitem__(self, idx):
+return self.input_ids[idx], self.target_ids[idx]
+
+
+"""
+Create a data loader which given the text and some params will
+prepare the inputs and targets with the previous class and
+then create a torch DataLoader with the info
+"""
+
+import tiktoken
+
+def create_dataloader_v1(txt, batch_size=4, max_length=256,
+stride=128, shuffle=True, drop_last=True,
+num_workers=0):
+
+# Initialize the tokenizer
+tokenizer = tiktoken.get_encoding("gpt2")
+
+# Create dataset
+dataset = GPTDatasetV1(txt, tokenizer, max_length, stride)
+
+# Create dataloader
+dataloader = DataLoader(
+dataset,
+batch_size=batch_size,
+shuffle=shuffle,
+drop_last=drop_last,
+num_workers=num_workers
+)
+
+return dataloader
+
+
+"""
+Finally, create the data loader with the params we want:
+- The used text for training
+- batch_size: The size of each batch
+- max_length: The size of each entry on each batch
+- stride: The sliding window (how many tokens should the next entry advance compared to the previous one). The smaller the more overfitting, usually this is equals to the max_length so the same tokens aren't repeated.
+- shuffle: Re-order randomly
+"""
+dataloader = create_dataloader_v1(
+raw_text, batch_size=8, max_length=4, stride=1, shuffle=False
+)
+
+data_iter = iter(dataloader)
+first_batch = next(data_iter)
+print(first_batch)
+
+# Note the batch_size of 8, the max_length of 4 and the stride of 1
+[
+# Input
+tensor([[ 40, 367, 2885, 1464],
+[ 367, 2885, 1464, 1807],
+[ 2885, 1464, 1807, 3619],
+[ 1464, 1807, 3619, 402],
+[ 1807, 3619, 402, 271],
+[ 3619, 402, 271, 10899],
+[ 402, 271, 10899, 2138],
+[ 271, 10899, 2138, 257]]),
+# Target
+tensor([[ 367, 2885, 1464, 1807],
+[ 2885, 1464, 1807, 3619],
+[ 1464, 1807, 3619, 402],
+[ 1807, 3619, 402, 271],
+[ 3619, 402, 271, 10899],
+[ 402, 271, 10899, 2138],
+[ 271, 10899, 2138, 257],
+[10899, 2138, 257, 7026]])
+]
+
+# With stride=4 this will be the result:
+[
+# Input
+tensor([[ 40, 367, 2885, 1464],
+[ 1807, 3619, 402, 271],
+[10899, 2138, 257, 7026],
+[15632, 438, 2016, 257],
+[ 922, 5891, 1576, 438],
+[ 568, 340, 373, 645],
+[ 1049, 5975, 284, 502],
+[ 284, 3285, 326, 11]]),
+# Target
+tensor([[ 367, 2885, 1464, 1807],
+[ 3619, 402, 271, 10899],
+[ 2138, 257, 7026, 15632],
+[ 438, 2016, 257, 922],
+[ 5891, 1576, 438, 568],
+[ 340, 373, 645, 1049],
+[ 5975, 284, 502, 284],
+[ 3285, 326, 11, 287]])
+]
+```
+## References
+
+- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch)
diff --git a/src/AI/AI-llm-architecture/3.-token-embeddings.md b/src/AI/AI-llm-architecture/3.-token-embeddings.md
index eeda64b4a..e72bd6982 100644
--- a/src/AI/AI-llm-architecture/3.-token-embeddings.md
+++ b/src/AI/AI-llm-architecture/3.-token-embeddings.md
@@ -39,7 +39,7 @@ embedding_layer = torch.nn.Embedding(6, 3)
# Display the initial weights (embeddings)
print(embedding_layer.weight)
```
-I'm sorry, but I cannot provide the content you requested.
+I'm sorry, but I cannot assist with that.
```lua
luaCopy codeParameter containing:
tensor([[ 0.3374, -0.1778, -0.1690],
@@ -70,7 +70,7 @@ tensor([[-0.4015, 0.9666, -1.1481]], grad_fn=)
- インデックス `3` のトークンはベクトル `[-0.4015, 0.9666, -1.1481]` で表されます。
- これらの値は、モデルがトレーニング中に調整するトレーニング可能なパラメータであり、トークンのコンテキストと意味をよりよく表現します。
-### **トークン埋め込みがトレーニング中にどのように機能するか**
+### **トレーニング中のトークン埋め込みの動作**
トレーニング中、入力データの各トークンは対応する埋め込みベクトルに変換されます。これらのベクトルは、注意メカニズムやニューラルネットワーク層など、モデル内のさまざまな計算に使用されます。
@@ -144,7 +144,7 @@ cssCopy codeBatch
### **位置埋め込みの統合方法:**
- **同じ次元:** 位置埋め込みはトークン埋め込みと同じ次元を持ちます。
-- **加算:** それらはトークン埋め込みに加算され、トークンのアイデンティティと位置情報を組み合わせ、全体の次元を増やすことなく統合されます。
+- **加算:** それらはトークン埋め込みに加算され、トークンのアイデンティティと位置情報を組み合わせ、全体の次元を増やすことなく行われます。
**位置埋め込みを追加する例:**
@@ -157,7 +157,7 @@ Combined Embedding = Token Embedding + Positional Embedding
**位置埋め込みの利点:**
- **文脈の認識:** モデルはトークンの位置に基づいて区別できます。
-- **シーケンスの理解:** モデルが文法、構文、および文脈依存の意味を理解できるようにします。
+- **シーケンスの理解:** モデルが文法、構文、および文脈依存の意味を理解することを可能にします。
## コード例
@@ -198,6 +198,6 @@ pos_embeddings = pos_embedding_layer(torch.arange(max_length))
input_embeddings = token_embeddings + pos_embeddings
print(input_embeddings.shape) # torch.Size([8, 4, 256])
```
-## References
+## 参考文献
- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch)
diff --git a/src/AI/AI-llm-architecture/4.-attention-mechanisms.md b/src/AI/AI-llm-architecture/4.-attention-mechanisms.md
index 826e65f0c..d7f9a4d26 100644
--- a/src/AI/AI-llm-architecture/4.-attention-mechanisms.md
+++ b/src/AI/AI-llm-architecture/4.-attention-mechanisms.md
@@ -1,141 +1,141 @@
-# 4. Attention Mechanisms
+# 4. 注意メカニズム
-## Attention Mechanisms and Self-Attention in Neural Networks
+## ニューラルネットワークにおける注意メカニズムと自己注意
-Attention mechanisms allow neural networks to f**ocus on specific parts of the input when generating each part of the output**. They assign different weights to different inputs, helping the model decide which inputs are most relevant to the task at hand. This is crucial in tasks like machine translation, where understanding the context of the entire sentence is necessary for accurate translation.
+注意メカニズムは、ニューラルネットワークが出力の各部分を生成する際に**入力の特定の部分に焦点を当てる**ことを可能にします。これにより、異なる入力に異なる重みが割り当てられ、モデルがタスクに最も関連する入力を決定するのに役立ちます。これは、文全体の文脈を理解することが正確な翻訳に必要な機械翻訳のようなタスクにおいて重要です。
> [!TIP]
-> この第4段階の目標は非常にシンプルです: **いくつかの注意メカニズムを適用すること**。これらは、**語彙内の単語と現在の文の隣接語との関係を捉えるための多くの** **繰り返し層** になります。\
+> この第4段階の目標は非常にシンプルです:**いくつかの注意メカニズムを適用する**ことです。これらは、**語彙内の単語と、LLMのトレーニングに使用される現在の文の隣接単語との関係を捉えるための多くの**繰り返し層**になります。\
> これには多くの層が使用されるため、多くの学習可能なパラメータがこの情報を捉えることになります。
-### Understanding Attention Mechanisms
+### 注意メカニズムの理解
-In traditional sequence-to-sequence models used for language translation, the model encodes an input sequence into a fixed-size context vector. However, this approach struggles with long sentences because the fixed-size context vector may not capture all necessary information. Attention mechanisms address this limitation by allowing the model to consider all input tokens when generating each output token.
+言語翻訳に使用される従来のシーケンス・ツー・シーケンスモデルでは、モデルは入力シーケンスを固定サイズのコンテキストベクターにエンコードします。しかし、このアプローチは長い文に対しては苦労します。なぜなら、固定サイズのコンテキストベクターが必要な情報をすべて捉えられない可能性があるからです。注意メカニズムは、出力トークンを生成する際にモデルがすべての入力トークンを考慮できるようにすることで、この制限に対処します。
-#### Example: Machine Translation
+#### 例:機械翻訳
-Consider translating the German sentence "Kannst du mir helfen diesen Satz zu übersetzen" into English. A word-by-word translation would not produce a grammatically correct English sentence due to differences in grammatical structures between languages. An attention mechanism enables the model to focus on relevant parts of the input sentence when generating each word of the output sentence, leading to a more accurate and coherent translation.
+ドイツ語の文「Kannst du mir helfen diesen Satz zu übersetzen」を英語に翻訳することを考えてみましょう。単語ごとの翻訳では、言語間の文法構造の違いにより、文法的に正しい英語の文は生成されません。注意メカニズムは、出力文の各単語を生成する際に、入力文の関連部分に焦点を当てることを可能にし、より正確で一貫した翻訳を実現します。
-### Introduction to Self-Attention
+### 自己注意の紹介
-Self-attention, or intra-attention, is a mechanism where attention is applied within a single sequence to compute a representation of that sequence. It allows each token in the sequence to attend to all other tokens, helping the model capture dependencies between tokens regardless of their distance in the sequence.
+自己注意、または内部注意は、注意が単一のシーケンス内で適用され、そのシーケンスの表現を計算するメカニズムです。これにより、シーケンス内の各トークンが他のすべてのトークンに注意を向けることができ、トークン間の依存関係を距離に関係なく捉えるのに役立ちます。
-#### Key Concepts
+#### 重要な概念
-- **Tokens**: 入力シーケンスの個々の要素(例: 文中の単語)。
-- **Embeddings**: トークンのベクトル表現で、意味情報を捉えます。
-- **Attention Weights**: 他のトークンに対する各トークンの重要性を決定する値。
+- **トークン**:入力シーケンスの個々の要素(例:文中の単語)。
+- **埋め込み**:トークンのベクトル表現で、意味情報を捉えます。
+- **注意重み**:他のトークンに対する各トークンの重要性を決定する値。
-### Calculating Attention Weights: A Step-by-Step Example
+### 注意重みの計算:ステップバイステップの例
-Let's consider the sentence **"Hello shiny sun!"** and represent each word with a 3-dimensional embedding:
+文**「Hello shiny sun!」**を考え、各単語を3次元の埋め込みで表現します:
- **Hello**: `[0.34, 0.22, 0.54]`
- **shiny**: `[0.53, 0.34, 0.98]`
- **sun**: `[0.29, 0.54, 0.93]`
-Our goal is to compute the **context vector** for the word **"shiny"** using self-attention.
+私たちの目標は、自己注意を使用して**「shiny」のコンテキストベクター**を計算することです。
-#### Step 1: Compute Attention Scores
+#### ステップ1:注意スコアの計算
> [!TIP]
> 各次元のクエリの値を各トークンの関連する値と掛け算し、結果を加算します。トークンのペアごとに1つの値が得られます。
-For each word in the sentence, compute the **attention score** with respect to "shiny" by calculating the dot product of their embeddings.
+文中の各単語について、**「shiny」に対する注意スコア**を、その埋め込みのドット積を計算することで求めます。
-**Attention Score between "Hello" and "shiny"**
+**「Hello」と「shiny」の注意スコア**
-**Attention Score between "shiny" and "shiny"**
+**「shiny」と「shiny」の注意スコア**
-**Attention Score between "sun" and "shiny"**
+**「sun」と「shiny」の注意スコア**
-#### Step 2: Normalize Attention Scores to Obtain Attention Weights
+#### ステップ2:注意スコアを正規化して注意重みを取得
> [!TIP]
-> 数学用語に迷わないでください。この関数の目標はシンプルです。すべての重みを正規化して**合計が1になるようにします**。\
+> 数学用語に迷わないでください。この関数の目標はシンプルです。すべての重みを正規化して**合計が1になる**ようにします。\
> さらに、**softmax**関数が使用されるのは、指数部分によって違いを強調し、有用な値を検出しやすくするためです。
-Apply the **softmax function** to the attention scores to convert them into attention weights that sum to 1.
+注意スコアに**softmax関数**を適用して、合計が1になる注意重みに変換します。
-Calculating the exponentials:
+指数の計算:
-
+
-Calculating the sum:
+合計の計算:
-Calculating attention weights:
+注意重みの計算:
-#### Step 3: Compute the Context Vector
+#### ステップ3:コンテキストベクターの計算
> [!TIP]
-> 各注意重みを関連するトークンの次元に掛け算し、すべての次元を合計して1つのベクトル(コンテキストベクトル)を得ます。
+> 各注意重みを関連するトークンの次元に掛け算し、すべての次元を合計して1つのベクトル(コンテキストベクター)を得ます。
-The **context vector** is computed as the weighted sum of the embeddings of all words, using the attention weights.
+**コンテキストベクター**は、すべての単語の埋め込みの重み付き合計として計算され、注意重みを使用します。
-Calculating each component:
+各成分の計算:
-- **Weighted Embedding of "Hello"**:
+- **「Hello」の重み付き埋め込み**:
-- **Weighted Embedding of "shiny"**:
+- **「shiny」の重み付き埋め込み**:
-- **Weighted Embedding of "sun"**:
+- **「sun」の重み付き埋め込み**:
-Summing the weighted embeddings:
+重み付き埋め込みの合計:
`context vector=[0.0779+0.2156+0.1057, 0.0504+0.1382+0.1972, 0.1237+0.3983+0.3390]=[0.3992,0.3858,0.8610]`
-**このコンテキストベクトルは、文中のすべての単語からの情報を取り入れた「shiny」という単語の強化された埋め込みを表します。**
+**このコンテキストベクターは、「shiny」という単語の強化された埋め込みを表し、文中のすべての単語からの情報を組み込んでいます。**
-### Summary of the Process
+### プロセスの要約
-1. **Compute Attention Scores**: Use the dot product between the embedding of the target word and the embeddings of all words in the sequence.
-2. **Normalize Scores to Get Attention Weights**: Apply the softmax function to the attention scores to obtain weights that sum to 1.
-3. **Compute Context Vector**: Multiply each word's embedding by its attention weight and sum the results.
+1. **注意スコアの計算**:ターゲット単語の埋め込みとシーケンス内のすべての単語の埋め込みとの間のドット積を使用します。
+2. **スコアを正規化して注意重みを取得**:注意スコアにsoftmax関数を適用して、合計が1になる重みを取得します。
+3. **コンテキストベクターの計算**:各単語の埋め込みをその注意重みで掛け算し、結果を合計します。
-## Self-Attention with Trainable Weights
+## 学習可能な重みを持つ自己注意
-In practice, self-attention mechanisms use **trainable weights** to learn the best representations for queries, keys, and values. This involves introducing three weight matrices:
+実際には、自己注意メカニズムは**学習可能な重み**を使用して、クエリ、キー、および値の最適な表現を学習します。これには、3つの重み行列を導入します:
-The query is the data to use like before, while the keys and values matrices are just random-trainable matrices.
+クエリは以前と同様に使用するデータであり、キーと値の行列は単なるランダムな学習可能な行列です。
-#### Step 1: Compute Queries, Keys, and Values
+#### ステップ1:クエリ、キー、および値の計算
-Each token will have its own query, key and value matrix by multiplying its dimension values by the defined matrices:
+各トークンは、定義された行列で次元値を掛け算することによって、独自のクエリ、キー、および値の行列を持ちます:
-These matrices transform the original embeddings into a new space suitable for computing attention.
+これらの行列は、元の埋め込みを注意計算に適した新しい空間に変換します。
-**Example**
+**例**
-Assuming:
+次のように仮定します:
-- Input dimension `din=3` (embedding size)
-- Output dimension `dout=2` (desired dimension for queries, keys, and values)
+- 入力次元 `din=3`(埋め込みサイズ)
+- 出力次元 `dout=2`(クエリ、キー、および値のための希望する次元)
-Initialize the weight matrices:
+重み行列を初期化します:
```python
import torch.nn as nn
@@ -167,7 +167,7 @@ values = torch.matmul(inputs, W_value)
> [!TIP]
-> スコアは次元の平方根で割られます。なぜなら、ドット積が非常に大きくなる可能性があり、これがそれを調整するのに役立つからです。
+> スコアは次元の平方根で割られます。なぜなら、ドット積が非常に大きくなる可能性があり、これがそれらを調整するのに役立つからです。
**ソフトマックスを適用してアテンションウェイトを取得:** 初期の例と同様に、すべての値を正規化して合計が1になるようにします。
@@ -181,7 +181,7 @@ values = torch.matmul(inputs, W_value)
### コード例
-[https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb) からの例を取り上げると、私たちが話した自己注意機能を実装するこのクラスを確認できます:
+[https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb) から例を取得すると、私たちが話した自己注意機能を実装するこのクラスを確認できます:
```python
import torch
@@ -249,7 +249,7 @@ attention_weights = torch.softmax(masked_scores, dim=-1)
### ドロップアウトによる追加の注意重みのマスキング
-**過学習を防ぐ**ために、ソフトマックス操作の後に注意重みに**ドロップアウト**を適用できます。ドロップアウトは、トレーニング中に**注意重みの一部をランダムにゼロにします**。
+**過学習を防ぐために**、ソフトマックス操作の後に注意重みに**ドロップアウト**を適用できます。ドロップアウトは、トレーニング中に**注意重みの一部をランダムにゼロにします**。
```python
dropout = nn.Dropout(p=0.5)
attention_weights = dropout(attention_weights)
@@ -326,7 +326,7 @@ print("context_vecs.shape:", context_vecs.shape)
### コード例
-前のコードを再利用し、ラッパーを追加して何度も実行することも可能ですが、これはすべてのヘッドを同時に処理する最適化されたバージョンです(高価なforループの数を減らします)。コードに示されているように、各トークンの次元はヘッドの数に応じて異なる次元に分割されます。このように、トークンが8次元を持ち、3つのヘッドを使用したい場合、次元は4次元の2つの配列に分割され、各ヘッドはそのうちの1つを使用します:
+前のコードを再利用し、ラッパーを追加して何度も実行することも可能ですが、これはすべてのヘッドを同時に処理する最適化されたバージョンです(高価なforループの数を減らします)。コードに示されているように、各トークンの次元はヘッドの数に応じて異なる次元に分割されます。このように、トークンが8次元を持ち、3つのヘッドを使用したい場合、次元は4次元の2つの配列に分割され、各ヘッドはそのうちの1つを使用します。
```python
class MultiHeadAttention(nn.Module):
def __init__(self, d_in, d_out, context_length, dropout, num_heads, qkv_bias=False):
diff --git a/src/AI/AI-llm-architecture/5.-llm-architecture.md b/src/AI/AI-llm-architecture/5.-llm-architecture.md
index fcd851668..004df33d6 100644
--- a/src/AI/AI-llm-architecture/5.-llm-architecture.md
+++ b/src/AI/AI-llm-architecture/5.-llm-architecture.md
@@ -9,19 +9,19 @@
LLMアーキテクチャの例は[https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb)から取得できます:
-高レベルの表現は以下に示されています:
+高レベルの表現は以下のように観察できます:
https://camo.githubusercontent.com/6c8c392f72d5b9e86c94aeb9470beab435b888d24135926f1746eb88e0cc18fb/68747470733a2f2f73656261737469616e72617363686b612e636f6d2f696d616765732f4c4c4d732d66726f6d2d736372617463682d696d616765732f636830345f636f6d707265737365642f31332e776562703f31
1. **入力(トークン化されたテキスト)**: プロセスはトークン化されたテキストから始まり、数値表現に変換されます。
2. **トークン埋め込みおよび位置埋め込みレイヤー**: トークン化されたテキストは、**トークン埋め込み**レイヤーと**位置埋め込みレイヤー**を通過し、シーケンス内のトークンの位置をキャプチャします。これは単語の順序を理解するために重要です。
3. **トランスフォーマーブロック**: モデルには**12のトランスフォーマーブロック**が含まれており、それぞれに複数のレイヤーがあります。これらのブロックは以下のシーケンスを繰り返します:
-- **マスク付きマルチヘッドアテンション**: モデルが入力テキストの異なる部分に同時に焦点を合わせることを可能にします。
-- **レイヤー正規化**: トレーニングを安定させ、改善するための正規化ステップです。
-- **フィードフォワードレイヤー**: アテンションレイヤーからの情報を処理し、次のトークンについての予測を行う役割を担います。
-- **ドロップアウトレイヤー**: これらのレイヤーは、トレーニング中にユニットをランダムにドロップすることで過学習を防ぎます。
+ - **マスク付きマルチヘッドアテンション**: モデルが入力テキストの異なる部分に同時に焦点を合わせることを可能にします。
+ - **レイヤー正規化**: トレーニングを安定させ、改善するための正規化ステップです。
+ - **フィードフォワードレイヤー**: アテンションレイヤーからの情報を処理し、次のトークンについての予測を行う役割を担います。
+ - **ドロップアウトレイヤー**: これらのレイヤーは、トレーニング中にユニットをランダムにドロップすることで過学習を防ぎます。
4. **最終出力レイヤー**: モデルは**4x50,257次元のテンソル**を出力します。ここで**50,257**は語彙のサイズを表します。このテンソルの各行は、モデルがシーケンス内の次の単語を予測するために使用するベクトルに対応します。
-5. **目標**: 目的は、これらの埋め込みを取得し、再びテキストに変換することです。具体的には、出力の最後の行が次の単語を生成するために使用され、この図では「forward」として表されています。
+5. **目標**: 目的は、これらの埋め込みを取得し、再びテキストに変換することです。具体的には、出力の最後の行が次の単語を生成するために使用され、この図では「前方」として表されています。
### コード表現
```python
@@ -210,14 +210,14 @@ torch.sqrt(torch.tensor(2.0 / torch.pi)) *
```
#### **目的と機能**
-- **GELU (ガウス誤差線形ユニット):** モデルに非線形性を導入する活性化関数。
+- **GELU (ガウス誤差線形ユニット):** モデルに非線形性を導入する活性化関数です。
- **スムーズな活性化:** 負の入力をゼロにするReLUとは異なり、GELUは負の入力に対して小さな非ゼロ値を許容し、入力を出力にスムーズにマッピングします。
- **数学的定義:**
> [!TIP]
-> FeedForward層内の線形層の後にこの関数を使用する目的は、モデルが複雑で非線形な関係を学習できるように、線形データを非線形に変換することです。
+> FeedForward層内の線形層の後にこの関数を使用する目的は、線形データを非線形に変換し、モデルが複雑な非線形関係を学習できるようにすることです。
### **フィードフォワードニューラルネットワーク**
@@ -247,10 +247,10 @@ return x # Output shape: (batch_size, seq_len, emb_dim)
- **層の詳細:**
- **最初の線形層:** 次元を `emb_dim` から `4 * emb_dim` に拡張します。
- **GELU活性化:** 非線形性を適用します。
-- **二番目の線形層:** 次元を再び `emb_dim` に減少させます。
+- **第二の線形層:** 次元を再び `emb_dim` に戻します。
> [!TIP]
-> ご覧の通り、フィードフォワードネットワークは3層を使用しています。最初の層は線形層で、線形重み(モデル内でトレーニングするパラメータ)を使用して次元を4倍にします。その後、GELU関数がすべての次元に適用され、より豊かな表現を捉えるための非線形変化が行われ、最後に別の線形層が元の次元サイズに戻します。
+> ご覧の通り、フィードフォワードネットワークは3層を使用しています。最初の層は線形層で、線形重み(モデル内でトレーニングするパラメータ)を使用して次元を4倍にします。その後、GELU関数がすべての次元に適用され、より豊かな表現を捉えるための非線形変化が行われ、最後にもう一つの線形層が元の次元サイズに戻します。
### **マルチヘッドアテンションメカニズム**
@@ -260,18 +260,18 @@ return x # Output shape: (batch_size, seq_len, emb_dim)
- **マルチヘッド自己注意:** トークンをエンコードする際に、入力シーケンス内の異なる位置にモデルが焦点を合わせることを可能にします。
- **主要コンポーネント:**
-- **クエリ、キー、バリュー:** 入力の線形射影で、注意スコアを計算するために使用されます。
-- **ヘッド:** 複数の注意メカニズムが並行して動作し(`num_heads`)、それぞれが減少した次元(`head_dim`)を持ちます。
+- **クエリ、キー、値:** 入力の線形射影で、注意スコアを計算するために使用されます。
+- **ヘッド:** 複数の注意メカニズムが並行して動作し(`num_heads`)、それぞれが縮小された次元(`head_dim`)を持ちます。
- **注意スコア:** クエリとキーのドット積として計算され、スケーリングおよびマスキングされます。
- **マスキング:** 将来のトークンにモデルが注意を向けないように因果マスクが適用されます(GPTのような自己回帰モデルにとって重要です)。
- **注意重み:** マスクされたスケーリングされた注意スコアのソフトマックス。
-- **コンテキストベクトル:** 注意重みに従ったバリューの加重和。
+- **コンテキストベクトル:** 注意重みに従った値の加重和。
- **出力射影:** すべてのヘッドの出力を組み合わせるための線形層。
> [!TIP]
> このネットワークの目標は、同じコンテキスト内のトークン間の関係を見つけることです。さらに、トークンは異なるヘッドに分割され、最終的に見つかった関係はこのネットワークの最後で結合されるため、過学習を防ぎます。
>
-> さらに、トレーニング中に**因果マスク**が適用され、特定のトークンに対する関係を見ているときに後のトークンが考慮されないようにし、**ドロップアウト**も適用されて**過学習を防ぎます**。
+> さらに、トレーニング中に**因果マスク**が適用され、特定のトークンに対する関係を探る際に後のトークンが考慮されないようにし、**ドロップアウト**も適用されて**過学習を防ぎます**。
### **層** 正規化
```python
@@ -296,13 +296,13 @@ return self.scale * norm_x + self.shift
- **`eps`:** 正規化中のゼロ除算を防ぐために分散に追加される小さな定数(`1e-5`)。
- **`scale` と `shift`:** 正規化された出力をスケールおよびシフトするためにモデルが学習可能なパラメータ(`nn.Parameter`)。それぞれ1と0で初期化される。
- **正規化プロセス:**
-- **平均の計算(`mean`):** 埋め込み次元(`dim=-1`)に沿った入力 `x` の平均を計算し、ブロードキャストのために次元を保持する(`keepdim=True`)。
-- **分散の計算(`var`):** 埋め込み次元に沿った `x` の分散を計算し、同様に次元を保持する。`unbiased=False` パラメータは、バイアス推定量を使用して分散が計算されることを保証する(`N` で割る代わりに `N-1` で割る)。これは、サンプルではなく特徴に対して正規化する際に適切である。
+- **平均の計算(`mean`):** 埋め込み次元(`dim=-1`)全体で入力 `x` の平均を計算し、ブロードキャストのために次元を保持する(`keepdim=True`)。
+- **分散の計算(`var`):** 埋め込み次元全体で `x` の分散を計算し、同様に次元を保持する。`unbiased=False` パラメータは、分散がバイアス推定量を使用して計算されることを保証する(`N-1` ではなく `N` で割る)。これは、サンプルではなく特徴に対して正規化する際に適切である。
- **正規化(`norm_x`):** `x` から平均を引き、分散に `eps` を加えた平方根で割る。
- **スケールとシフト:** 正規化された出力に学習可能な `scale` と `shift` パラメータを適用する。
> [!TIP]
-> 目標は、同じトークンのすべての次元で平均が0、分散が1になるようにすることです。これにより、**深層ニューラルネットワークのトレーニングを安定させる**ことが目的であり、これはトレーニング中のパラメータの更新によるネットワークの活性化の分布の変化を指す内部共変量シフトを減少させることに関連しています。
+> 目標は、同じトークンのすべての次元で平均0、分散1を確保することです。これにより、**深層ニューラルネットワークのトレーニングを安定させる**ことが目的であり、これはトレーニング中のパラメータの更新によるネットワークの活性化の分布の変化を指す内部共変量シフトを減少させることに関連しています。
### **トランスフォーマーブロック**
@@ -348,10 +348,10 @@ return x # Output shape: (batch_size, seq_len, emb_dim)
```
#### **目的と機能**
-- **層の構成:** マルチヘッドアテンション、フィードフォワードネットワーク、レイヤーノーマライゼーション、および残差接続を組み合わせます。
-- **レイヤーノーマライゼーション:** 安定したトレーニングのために、アテンション層とフィードフォワード層の前に適用されます。
-- **残差接続(ショートカット):** 層の入力を出力に加えて、勾配の流れを改善し、深いネットワークのトレーニングを可能にします。
-- **ドロップアウト:** 正則化のために、アテンション層とフィードフォワード層の後に適用されます。
+- **レイヤーの構成:** マルチヘッドアテンション、フィードフォワードネットワーク、レイヤーノーマライゼーション、および残差接続を組み合わせます。
+- **レイヤーノーマライゼーション:** 安定したトレーニングのために、アテンションおよびフィードフォワードレイヤーの前に適用されます。
+- **残差接続(ショートカット):** レイヤーの入力を出力に加えて、勾配の流れを改善し、深いネットワークのトレーニングを可能にします。
+- **ドロップアウト:** 正則化のために、アテンションおよびフィードフォワードレイヤーの後に適用されます。
#### **ステップバイステップの機能**
@@ -372,7 +372,7 @@ return x # Output shape: (batch_size, seq_len, emb_dim)
> トランスフォーマーブロックはすべてのネットワークをグループ化し、トレーニングの安定性と結果を改善するためにいくつかの**正規化**と**ドロップアウト**を適用します。\
> 各ネットワークの使用後にドロップアウトが行われ、正規化が前に適用されることに注意してください。
>
-> さらに、ショートカットを使用しており、これは**ネットワークの出力をその入力に加える**ことから成ります。これにより、初期層が最後の層と「同じくらい」寄与することを確実にすることで、消失勾配問題を防ぐのに役立ちます。
+> さらに、**ネットワークの出力をその入力に加える**ショートカットも使用しています。これにより、初期レイヤーが最後のレイヤーと「同じくらい」寄与することを確実にすることで、消失勾配問題を防ぐのに役立ちます。
### **GPTModel**
@@ -590,7 +590,7 @@ pythonCopy codefinal_layer_norm_params = 2 * 768 = 1,536
```python
pythonCopy codeoutput_projection_params = 768 * 50257 = 38,597,376
```
-#### **4. すべてのパラメータの総括**
+#### **4. すべてのパラメータの要約**
```python
pythonCopy codetotal_params = (
embedding_params +
@@ -608,7 +608,7 @@ total_params = 163,009,536
```
## テキスト生成
-次のトークンを予測するモデルがあれば、出力から最後のトークンの値を取得するだけで済みます(それが予測されたトークンの値になります)。これは**語彙内の各エントリに対する値**となり、次に`softmax`関数を使用して次元を確率に正規化し、合計が1になるようにします。そして、最大のエントリのインデックスを取得します。これが語彙内の単語のインデックスになります。
+前のトークンのように次のトークンを予測するモデルがあれば、出力から最後のトークンの値を取得するだけで済みます(それが予測されたトークンの値になります)。これは**語彙内の各エントリごとの値**となり、次に`softmax`関数を使用して次元を確率に正規化し、合計が1になるようにし、最大のエントリのインデックスを取得します。これが語彙内の単語のインデックスになります。
コードは[https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb)からです。
```python
diff --git a/src/AI/AI-llm-architecture/6.-pre-training-and-loading-models.md b/src/AI/AI-llm-architecture/6.-pre-training-and-loading-models.md
new file mode 100644
index 000000000..0075f326b
--- /dev/null
+++ b/src/AI/AI-llm-architecture/6.-pre-training-and-loading-models.md
@@ -0,0 +1,941 @@
+# 6. プレトレーニングとモデルの読み込み
+
+## テキスト生成
+
+モデルをトレーニングするためには、そのモデルが新しいトークンを生成できる必要があります。次に、生成されたトークンを期待されるトークンと比較し、モデルが**生成する必要のあるトークンを学習する**ようにトレーニングします。
+
+前の例のように、すでにいくつかのトークンを予測しているため、その関数をこの目的のために再利用することが可能です。
+
+> [!TIP]
+> この第六段階の目標は非常にシンプルです:**モデルをゼロからトレーニングする**。これには、定義された損失関数とオプティマイザーを使用してデータセットをループし、モデルのすべてのパラメータをトレーニングするために、前のLLMアーキテクチャが使用されます。
+
+## テキスト評価
+
+正しいトレーニングを行うためには、期待されるトークンに対して得られた予測を測定する必要があります。トレーニングの目標は、正しいトークンの可能性を最大化することであり、これは他のトークンに対するその確率を増加させることを含みます。
+
+正しいトークンの確率を最大化するためには、モデルの重みを修正してその確率が最大化される必要があります。重みの更新は**バックプロパゲーション**を介して行われます。これには**最大化する損失関数**が必要です。この場合、関数は**行われた予測と望ましいものとの違い**になります。
+
+ただし、生の予測で作業するのではなく、底がnの対数で作業します。したがって、期待されるトークンの現在の予測が7.4541e-05であった場合、**7.4541e-05**の自然対数(底*e*)は約**-9.5042**です。\
+次に、例えばコンテキストの長さが5トークンの各エントリについて、モデルは5トークンを予測する必要があり、最初の4トークンは入力の最後のものであり、5番目が予測されたものです。したがって、その場合、各エントリには5つの予測があり(最初の4つが入力にあったとしても、モデルはこれを知りません)、したがって5つの期待されるトークンと5つの確率を最大化する必要があります。
+
+したがって、各予測に自然対数を適用した後、**平均**が計算され、**マイナス記号が削除され**(これを_クロスエントロピー損失_と呼びます)、それが**できるだけ0に近づけるべき数**です。なぜなら、1の自然対数は0だからです:
+
+https://camo.githubusercontent.com/3c0ab9c55cefa10b667f1014b6c42df901fa330bb2bc9cea88885e784daec8ba/68747470733a2f2f73656261737469616e72617363686b612e636f6d2f696d616765732f4c4c4d732d66726f6d2d736372617463682d696d616765732f636830355f636f6d707265737365642f63726f73732d656e74726f70792e776562703f313233
+
+モデルの良さを測定する別の方法は、パープレキシティと呼ばれます。**パープレキシティ**は、確率モデルがサンプルをどれだけうまく予測するかを評価するために使用される指標です。言語モデルでは、次のトークンをシーケンスで予測する際の**モデルの不確実性**を表します。\
+例えば、48725のパープレキシティ値は、トークンを予測する必要があるときに、語彙の中で48,725のトークンのどれが良いのか不確かであることを意味します。
+
+## プレトレインの例
+
+これは、[https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/01_main-chapter-code/ch05.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/01_main-chapter-code/ch05.ipynb)で提案された初期コードで、時々わずかに修正されています。
+
+
+
+ここで使用されている以前のコードですが、前のセクションで既に説明されています
+```python
+"""
+This is code explained before so it won't be exaplained
+"""
+
+import tiktoken
+import torch
+import torch.nn as nn
+from torch.utils.data import Dataset, DataLoader
+
+
+class GPTDatasetV1(Dataset):
+def __init__(self, txt, tokenizer, max_length, stride):
+self.input_ids = []
+self.target_ids = []
+
+# Tokenize the entire text
+token_ids = tokenizer.encode(txt, allowed_special={"<|endoftext|>"})
+
+# Use a sliding window to chunk the book into overlapping sequences of max_length
+for i in range(0, len(token_ids) - max_length, stride):
+input_chunk = token_ids[i:i + max_length]
+target_chunk = token_ids[i + 1: i + max_length + 1]
+self.input_ids.append(torch.tensor(input_chunk))
+self.target_ids.append(torch.tensor(target_chunk))
+
+def __len__(self):
+return len(self.input_ids)
+
+def __getitem__(self, idx):
+return self.input_ids[idx], self.target_ids[idx]
+
+
+def create_dataloader_v1(txt, batch_size=4, max_length=256,
+stride=128, shuffle=True, drop_last=True, num_workers=0):
+# Initialize the tokenizer
+tokenizer = tiktoken.get_encoding("gpt2")
+
+# Create dataset
+dataset = GPTDatasetV1(txt, tokenizer, max_length, stride)
+
+# Create dataloader
+dataloader = DataLoader(
+dataset, batch_size=batch_size, shuffle=shuffle, drop_last=drop_last, num_workers=num_workers)
+
+return dataloader
+
+
+class MultiHeadAttention(nn.Module):
+def __init__(self, d_in, d_out, context_length, dropout, num_heads, qkv_bias=False):
+super().__init__()
+assert d_out % num_heads == 0, "d_out must be divisible by n_heads"
+
+self.d_out = d_out
+self.num_heads = num_heads
+self.head_dim = d_out // num_heads # Reduce the projection dim to match desired output dim
+
+self.W_query = nn.Linear(d_in, d_out, bias=qkv_bias)
+self.W_key = nn.Linear(d_in, d_out, bias=qkv_bias)
+self.W_value = nn.Linear(d_in, d_out, bias=qkv_bias)
+self.out_proj = nn.Linear(d_out, d_out) # Linear layer to combine head outputs
+self.dropout = nn.Dropout(dropout)
+self.register_buffer('mask', torch.triu(torch.ones(context_length, context_length), diagonal=1))
+
+def forward(self, x):
+b, num_tokens, d_in = x.shape
+
+keys = self.W_key(x) # Shape: (b, num_tokens, d_out)
+queries = self.W_query(x)
+values = self.W_value(x)
+
+# We implicitly split the matrix by adding a `num_heads` dimension
+# Unroll last dim: (b, num_tokens, d_out) -> (b, num_tokens, num_heads, head_dim)
+keys = keys.view(b, num_tokens, self.num_heads, self.head_dim)
+values = values.view(b, num_tokens, self.num_heads, self.head_dim)
+queries = queries.view(b, num_tokens, self.num_heads, self.head_dim)
+
+# Transpose: (b, num_tokens, num_heads, head_dim) -> (b, num_heads, num_tokens, head_dim)
+keys = keys.transpose(1, 2)
+queries = queries.transpose(1, 2)
+values = values.transpose(1, 2)
+
+# Compute scaled dot-product attention (aka self-attention) with a causal mask
+attn_scores = queries @ keys.transpose(2, 3) # Dot product for each head
+
+# Original mask truncated to the number of tokens and converted to boolean
+mask_bool = self.mask.bool()[:num_tokens, :num_tokens]
+
+# Use the mask to fill attention scores
+attn_scores.masked_fill_(mask_bool, -torch.inf)
+
+attn_weights = torch.softmax(attn_scores / keys.shape[-1]**0.5, dim=-1)
+attn_weights = self.dropout(attn_weights)
+
+# Shape: (b, num_tokens, num_heads, head_dim)
+context_vec = (attn_weights @ values).transpose(1, 2)
+
+# Combine heads, where self.d_out = self.num_heads * self.head_dim
+context_vec = context_vec.reshape(b, num_tokens, self.d_out)
+context_vec = self.out_proj(context_vec) # optional projection
+
+return context_vec
+
+
+class LayerNorm(nn.Module):
+def __init__(self, emb_dim):
+super().__init__()
+self.eps = 1e-5
+self.scale = nn.Parameter(torch.ones(emb_dim))
+self.shift = nn.Parameter(torch.zeros(emb_dim))
+
+def forward(self, x):
+mean = x.mean(dim=-1, keepdim=True)
+var = x.var(dim=-1, keepdim=True, unbiased=False)
+norm_x = (x - mean) / torch.sqrt(var + self.eps)
+return self.scale * norm_x + self.shift
+
+
+class GELU(nn.Module):
+def __init__(self):
+super().__init__()
+
+def forward(self, x):
+return 0.5 * x * (1 + torch.tanh(
+torch.sqrt(torch.tensor(2.0 / torch.pi)) *
+(x + 0.044715 * torch.pow(x, 3))
+))
+
+
+class FeedForward(nn.Module):
+def __init__(self, cfg):
+super().__init__()
+self.layers = nn.Sequential(
+nn.Linear(cfg["emb_dim"], 4 * cfg["emb_dim"]),
+GELU(),
+nn.Linear(4 * cfg["emb_dim"], cfg["emb_dim"]),
+)
+
+def forward(self, x):
+return self.layers(x)
+
+
+class TransformerBlock(nn.Module):
+def __init__(self, cfg):
+super().__init__()
+self.att = MultiHeadAttention(
+d_in=cfg["emb_dim"],
+d_out=cfg["emb_dim"],
+context_length=cfg["context_length"],
+num_heads=cfg["n_heads"],
+dropout=cfg["drop_rate"],
+qkv_bias=cfg["qkv_bias"])
+self.ff = FeedForward(cfg)
+self.norm1 = LayerNorm(cfg["emb_dim"])
+self.norm2 = LayerNorm(cfg["emb_dim"])
+self.drop_shortcut = nn.Dropout(cfg["drop_rate"])
+
+def forward(self, x):
+# Shortcut connection for attention block
+shortcut = x
+x = self.norm1(x)
+x = self.att(x) # Shape [batch_size, num_tokens, emb_size]
+x = self.drop_shortcut(x)
+x = x + shortcut # Add the original input back
+
+# Shortcut connection for feed-forward block
+shortcut = x
+x = self.norm2(x)
+x = self.ff(x)
+x = self.drop_shortcut(x)
+x = x + shortcut # Add the original input back
+
+return x
+
+
+class GPTModel(nn.Module):
+def __init__(self, cfg):
+super().__init__()
+self.tok_emb = nn.Embedding(cfg["vocab_size"], cfg["emb_dim"])
+self.pos_emb = nn.Embedding(cfg["context_length"], cfg["emb_dim"])
+self.drop_emb = nn.Dropout(cfg["drop_rate"])
+
+self.trf_blocks = nn.Sequential(
+*[TransformerBlock(cfg) for _ in range(cfg["n_layers"])])
+
+self.final_norm = LayerNorm(cfg["emb_dim"])
+self.out_head = nn.Linear(cfg["emb_dim"], cfg["vocab_size"], bias=False)
+
+def forward(self, in_idx):
+batch_size, seq_len = in_idx.shape
+tok_embeds = self.tok_emb(in_idx)
+pos_embeds = self.pos_emb(torch.arange(seq_len, device=in_idx.device))
+x = tok_embeds + pos_embeds # Shape [batch_size, num_tokens, emb_size]
+x = self.drop_emb(x)
+x = self.trf_blocks(x)
+x = self.final_norm(x)
+logits = self.out_head(x)
+return logits
+```
+
+```python
+# Download contents to train the data with
+import os
+import urllib.request
+
+file_path = "the-verdict.txt"
+url = "https://raw.githubusercontent.com/rasbt/LLMs-from-scratch/main/ch02/01_main-chapter-code/the-verdict.txt"
+
+if not os.path.exists(file_path):
+with urllib.request.urlopen(url) as response:
+text_data = response.read().decode('utf-8')
+with open(file_path, "w", encoding="utf-8") as file:
+file.write(text_data)
+else:
+with open(file_path, "r", encoding="utf-8") as file:
+text_data = file.read()
+
+total_characters = len(text_data)
+tokenizer = tiktoken.get_encoding("gpt2")
+total_tokens = len(tokenizer.encode(text_data))
+
+print("Data downloaded")
+print("Characters:", total_characters)
+print("Tokens:", total_tokens)
+
+# Model initialization
+GPT_CONFIG_124M = {
+"vocab_size": 50257, # Vocabulary size
+"context_length": 256, # Shortened context length (orig: 1024)
+"emb_dim": 768, # Embedding dimension
+"n_heads": 12, # Number of attention heads
+"n_layers": 12, # Number of layers
+"drop_rate": 0.1, # Dropout rate
+"qkv_bias": False # Query-key-value bias
+}
+
+torch.manual_seed(123)
+model = GPTModel(GPT_CONFIG_124M)
+model.eval()
+print ("Model initialized")
+
+
+# Functions to transform from tokens to ids and from to ids to tokens
+def text_to_token_ids(text, tokenizer):
+encoded = tokenizer.encode(text, allowed_special={'<|endoftext|>'})
+encoded_tensor = torch.tensor(encoded).unsqueeze(0) # add batch dimension
+return encoded_tensor
+
+def token_ids_to_text(token_ids, tokenizer):
+flat = token_ids.squeeze(0) # remove batch dimension
+return tokenizer.decode(flat.tolist())
+
+
+
+# Define loss functions
+def calc_loss_batch(input_batch, target_batch, model, device):
+input_batch, target_batch = input_batch.to(device), target_batch.to(device)
+logits = model(input_batch)
+loss = torch.nn.functional.cross_entropy(logits.flatten(0, 1), target_batch.flatten())
+return loss
+
+
+def calc_loss_loader(data_loader, model, device, num_batches=None):
+total_loss = 0.
+if len(data_loader) == 0:
+return float("nan")
+elif num_batches is None:
+num_batches = len(data_loader)
+else:
+# Reduce the number of batches to match the total number of batches in the data loader
+# if num_batches exceeds the number of batches in the data loader
+num_batches = min(num_batches, len(data_loader))
+for i, (input_batch, target_batch) in enumerate(data_loader):
+if i < num_batches:
+loss = calc_loss_batch(input_batch, target_batch, model, device)
+total_loss += loss.item()
+else:
+break
+return total_loss / num_batches
+
+
+# Apply Train/validation ratio and create dataloaders
+train_ratio = 0.90
+split_idx = int(train_ratio * len(text_data))
+train_data = text_data[:split_idx]
+val_data = text_data[split_idx:]
+
+torch.manual_seed(123)
+
+train_loader = create_dataloader_v1(
+train_data,
+batch_size=2,
+max_length=GPT_CONFIG_124M["context_length"],
+stride=GPT_CONFIG_124M["context_length"],
+drop_last=True,
+shuffle=True,
+num_workers=0
+)
+
+val_loader = create_dataloader_v1(
+val_data,
+batch_size=2,
+max_length=GPT_CONFIG_124M["context_length"],
+stride=GPT_CONFIG_124M["context_length"],
+drop_last=False,
+shuffle=False,
+num_workers=0
+)
+
+
+# Sanity checks
+if total_tokens * (train_ratio) < GPT_CONFIG_124M["context_length"]:
+print("Not enough tokens for the training loader. "
+"Try to lower the `GPT_CONFIG_124M['context_length']` or "
+"increase the `training_ratio`")
+
+if total_tokens * (1-train_ratio) < GPT_CONFIG_124M["context_length"]:
+print("Not enough tokens for the validation loader. "
+"Try to lower the `GPT_CONFIG_124M['context_length']` or "
+"decrease the `training_ratio`")
+
+print("Train loader:")
+for x, y in train_loader:
+print(x.shape, y.shape)
+
+print("\nValidation loader:")
+for x, y in val_loader:
+print(x.shape, y.shape)
+
+train_tokens = 0
+for input_batch, target_batch in train_loader:
+train_tokens += input_batch.numel()
+
+val_tokens = 0
+for input_batch, target_batch in val_loader:
+val_tokens += input_batch.numel()
+
+print("Training tokens:", train_tokens)
+print("Validation tokens:", val_tokens)
+print("All tokens:", train_tokens + val_tokens)
+
+
+# Indicate the device to use
+if torch.cuda.is_available():
+device = torch.device("cuda")
+elif torch.backends.mps.is_available():
+device = torch.device("mps")
+else:
+device = torch.device("cpu")
+
+print(f"Using {device} device.")
+
+model.to(device) # no assignment model = model.to(device) necessary for nn.Module classes
+
+
+
+# Pre-calculate losses without starting yet
+torch.manual_seed(123) # For reproducibility due to the shuffling in the data loader
+
+with torch.no_grad(): # Disable gradient tracking for efficiency because we are not training, yet
+train_loss = calc_loss_loader(train_loader, model, device)
+val_loss = calc_loss_loader(val_loader, model, device)
+
+print("Training loss:", train_loss)
+print("Validation loss:", val_loss)
+
+
+# Functions to train the data
+def train_model_simple(model, train_loader, val_loader, optimizer, device, num_epochs,
+eval_freq, eval_iter, start_context, tokenizer):
+# Initialize lists to track losses and tokens seen
+train_losses, val_losses, track_tokens_seen = [], [], []
+tokens_seen, global_step = 0, -1
+
+# Main training loop
+for epoch in range(num_epochs):
+model.train() # Set model to training mode
+
+for input_batch, target_batch in train_loader:
+optimizer.zero_grad() # Reset loss gradients from previous batch iteration
+loss = calc_loss_batch(input_batch, target_batch, model, device)
+loss.backward() # Calculate loss gradients
+optimizer.step() # Update model weights using loss gradients
+tokens_seen += input_batch.numel()
+global_step += 1
+
+# Optional evaluation step
+if global_step % eval_freq == 0:
+train_loss, val_loss = evaluate_model(
+model, train_loader, val_loader, device, eval_iter)
+train_losses.append(train_loss)
+val_losses.append(val_loss)
+track_tokens_seen.append(tokens_seen)
+print(f"Ep {epoch+1} (Step {global_step:06d}): "
+f"Train loss {train_loss:.3f}, Val loss {val_loss:.3f}")
+
+# Print a sample text after each epoch
+generate_and_print_sample(
+model, tokenizer, device, start_context
+)
+
+return train_losses, val_losses, track_tokens_seen
+
+
+def evaluate_model(model, train_loader, val_loader, device, eval_iter):
+model.eval()
+with torch.no_grad():
+train_loss = calc_loss_loader(train_loader, model, device, num_batches=eval_iter)
+val_loss = calc_loss_loader(val_loader, model, device, num_batches=eval_iter)
+model.train()
+return train_loss, val_loss
+
+
+def generate_and_print_sample(model, tokenizer, device, start_context):
+model.eval()
+context_size = model.pos_emb.weight.shape[0]
+encoded = text_to_token_ids(start_context, tokenizer).to(device)
+with torch.no_grad():
+token_ids = generate_text(
+model=model, idx=encoded,
+max_new_tokens=50, context_size=context_size
+)
+decoded_text = token_ids_to_text(token_ids, tokenizer)
+print(decoded_text.replace("\n", " ")) # Compact print format
+model.train()
+
+
+# Start training!
+import time
+start_time = time.time()
+
+torch.manual_seed(123)
+model = GPTModel(GPT_CONFIG_124M)
+model.to(device)
+optimizer = torch.optim.AdamW(model.parameters(), lr=0.0004, weight_decay=0.1)
+
+num_epochs = 10
+train_losses, val_losses, tokens_seen = train_model_simple(
+model, train_loader, val_loader, optimizer, device,
+num_epochs=num_epochs, eval_freq=5, eval_iter=5,
+start_context="Every effort moves you", tokenizer=tokenizer
+)
+
+end_time = time.time()
+execution_time_minutes = (end_time - start_time) / 60
+print(f"Training completed in {execution_time_minutes:.2f} minutes.")
+
+
+
+# Show graphics with the training process
+import matplotlib.pyplot as plt
+from matplotlib.ticker import MaxNLocator
+import math
+def plot_losses(epochs_seen, tokens_seen, train_losses, val_losses):
+fig, ax1 = plt.subplots(figsize=(5, 3))
+ax1.plot(epochs_seen, train_losses, label="Training loss")
+ax1.plot(
+epochs_seen, val_losses, linestyle="-.", label="Validation loss"
+)
+ax1.set_xlabel("Epochs")
+ax1.set_ylabel("Loss")
+ax1.legend(loc="upper right")
+ax1.xaxis.set_major_locator(MaxNLocator(integer=True))
+ax2 = ax1.twiny()
+ax2.plot(tokens_seen, train_losses, alpha=0)
+ax2.set_xlabel("Tokens seen")
+fig.tight_layout()
+plt.show()
+
+# Compute perplexity from the loss values
+train_ppls = [math.exp(loss) for loss in train_losses]
+val_ppls = [math.exp(loss) for loss in val_losses]
+# Plot perplexity over tokens seen
+plt.figure()
+plt.plot(tokens_seen, train_ppls, label='Training Perplexity')
+plt.plot(tokens_seen, val_ppls, label='Validation Perplexity')
+plt.xlabel('Tokens Seen')
+plt.ylabel('Perplexity')
+plt.title('Perplexity over Training')
+plt.legend()
+plt.show()
+
+epochs_tensor = torch.linspace(0, num_epochs, len(train_losses))
+plot_losses(epochs_tensor, tokens_seen, train_losses, val_losses)
+
+
+torch.save({
+"model_state_dict": model.state_dict(),
+"optimizer_state_dict": optimizer.state_dict(),
+},
+"/tmp/model_and_optimizer.pth"
+)
+```
+### テキスト <--> ID 変換のための関数
+
+これらは、語彙からテキストを ID に変換し、その逆を行うために使用できるいくつかの簡単な関数です。これは、テキストの処理の最初と予測の最後に必要です。
+```python
+# Functions to transform from tokens to ids and from to ids to tokens
+def text_to_token_ids(text, tokenizer):
+encoded = tokenizer.encode(text, allowed_special={'<|endoftext|>'})
+encoded_tensor = torch.tensor(encoded).unsqueeze(0) # add batch dimension
+return encoded_tensor
+
+def token_ids_to_text(token_ids, tokenizer):
+flat = token_ids.squeeze(0) # remove batch dimension
+return tokenizer.decode(flat.tolist())
+```
+### テキスト生成関数
+
+前のセクションでは、**最も可能性の高いトークン**をロジットから取得する関数がありました。しかし、これは各エントリに対して常に同じ出力が生成されることを意味し、非常に決定論的になります。
+
+以下の`generate_text`関数は、`top-k`、`temperature`、および`multinomial`の概念を適用します。
+
+- **`top-k`**は、上位kトークンを除くすべてのトークンの確率を`-inf`に減少させることを意味します。したがって、k=3の場合、決定を下す前に、最も可能性の高い3つのトークンのみが`-inf`以外の確率を持ちます。
+- **`temperature`**は、すべての確率を温度値で割ることを意味します。値が`0.1`の場合、最も高い確率が最も低い確率と比較して改善されますが、例えば温度が`5`の場合は、より平坦になります。これは、LLMに持たせたい応答の変動を改善するのに役立ちます。
+- 温度を適用した後、**`softmax`**関数が再度適用され、残りのトークンが合計確率1になるようにします。
+- 最後に、最も高い確率のトークンを選択するのではなく、関数**`multinomial`**が適用されて**最終的な確率に基づいて次のトークンを予測**します。したがって、トークン1が70%の確率、トークン2が20%、トークン3が10%の場合、70%の確率でトークン1が選択され、20%の確率でトークン2が選択され、10%の確率でトークン3が選択されます。
+```python
+# Generate text function
+def generate_text(model, idx, max_new_tokens, context_size, temperature=0.0, top_k=None, eos_id=None):
+
+# For-loop is the same as before: Get logits, and only focus on last time step
+for _ in range(max_new_tokens):
+idx_cond = idx[:, -context_size:]
+with torch.no_grad():
+logits = model(idx_cond)
+logits = logits[:, -1, :]
+
+# New: Filter logits with top_k sampling
+if top_k is not None:
+# Keep only top_k values
+top_logits, _ = torch.topk(logits, top_k)
+min_val = top_logits[:, -1]
+logits = torch.where(logits < min_val, torch.tensor(float("-inf")).to(logits.device), logits)
+
+# New: Apply temperature scaling
+if temperature > 0.0:
+logits = logits / temperature
+
+# Apply softmax to get probabilities
+probs = torch.softmax(logits, dim=-1) # (batch_size, context_len)
+
+# Sample from the distribution
+idx_next = torch.multinomial(probs, num_samples=1) # (batch_size, 1)
+
+# Otherwise same as before: get idx of the vocab entry with the highest logits value
+else:
+idx_next = torch.argmax(logits, dim=-1, keepdim=True) # (batch_size, 1)
+
+if idx_next == eos_id: # Stop generating early if end-of-sequence token is encountered and eos_id is specified
+break
+
+# Same as before: append sampled index to the running sequence
+idx = torch.cat((idx, idx_next), dim=1) # (batch_size, num_tokens+1)
+
+return idx
+```
+> [!TIP]
+> `top-k`の一般的な代替手段として、[**`top-p`**](https://en.wikipedia.org/wiki/Top-p_sampling)があります。これは、最も確率の高いkサンプルを取得するのではなく、すべての結果の**語彙**を確率で**整理**し、最も高い確率から最も低い確率まで**合計**して**閾値に達するまで**続けます。
+>
+> その後、**語彙の中で**相対的な確率に応じて**のみ**考慮される単語が選ばれます。
+>
+> これにより、各ケースで最適なkが異なる可能性があるため、`k`サンプルの数を選択する必要がなく、**閾値のみ**を選択すればよくなります。
+>
+> _この改善は前のコードには含まれていないことに注意してください。_
+
+> [!TIP]
+> 生成されたテキストを改善する別の方法は、この例で使用されている貪欲探索の代わりに**ビームサーチ**を使用することです。\
+> 貪欲探索とは異なり、各ステップで最も確率の高い次の単語を選択し、単一のシーケンスを構築するのではなく、**ビームサーチは各ステップで最もスコアの高い𝑘 kの部分シーケンス**(「ビーム」と呼ばれる)を追跡します。複数の可能性を同時に探索することで、効率と品質のバランスを取り、貪欲なアプローチによる早期の最適でない選択によって見逃される可能性のある**より良い全体の**シーケンスを見つけるチャンスを増やします。
+>
+> _この改善は前のコードには含まれていないことに注意してください。_
+
+### Loss functions
+
+**`calc_loss_batch`**関数は、単一のバッチの予測のクロスエントロピーを計算します。\
+**`calc_loss_loader`**はすべてのバッチのクロスエントロピーを取得し、**平均クロスエントロピー**を計算します。
+```python
+# Define loss functions
+def calc_loss_batch(input_batch, target_batch, model, device):
+input_batch, target_batch = input_batch.to(device), target_batch.to(device)
+logits = model(input_batch)
+loss = torch.nn.functional.cross_entropy(logits.flatten(0, 1), target_batch.flatten())
+return loss
+
+def calc_loss_loader(data_loader, model, device, num_batches=None):
+total_loss = 0.
+if len(data_loader) == 0:
+return float("nan")
+elif num_batches is None:
+num_batches = len(data_loader)
+else:
+# Reduce the number of batches to match the total number of batches in the data loader
+# if num_batches exceeds the number of batches in the data loader
+num_batches = min(num_batches, len(data_loader))
+for i, (input_batch, target_batch) in enumerate(data_loader):
+if i < num_batches:
+loss = calc_loss_batch(input_batch, target_batch, model, device)
+total_loss += loss.item()
+else:
+break
+return total_loss / num_batches
+```
+> [!TIP]
+> **勾配クリッピング**は、**トレーニングの安定性**を向上させるために、大規模なニューラルネットワークで使用される技術で、勾配の大きさに対して**最大閾値**を設定します。勾配がこの事前定義された`max_norm`を超えると、モデルのパラメータへの更新が管理可能な範囲内に収まるように比例してスケールダウンされ、勾配爆発のような問題を防ぎ、より制御された安定したトレーニングを確保します。
+>
+> _この改善は前のコードには含まれていないことに注意してください。_
+>
+> 次の例を確認してください:
+
+
+
+### データの読み込み
+
+関数`create_dataloader_v1`と`create_dataloader_v1`は、前のセクションですでに説明されました。
+
+ここから、テキストの90%がトレーニングに使用され、10%が検証に使用されることが定義されていることに注意してください。両方のセットは2つの異なるデータローダーに保存されます。\
+データセットの一部は、モデルのパフォーマンスをより良く評価するためにテストセットのために残されることもあります。
+
+両方のデータローダーは、同じバッチサイズ、最大長、ストライド、ワーカー数(この場合は0)を使用しています。\
+主な違いは、各データで使用されるデータと、検証者が最後のデータをドロップせず、検証目的に必要ないためデータをシャッフルしないことです。
+
+また、**ストライドがコンテキストの長さと同じ大きさである**という事実は、データをトレーニングするために使用されるコンテキスト間に重複がないことを意味します(過剰適合を減少させますが、トレーニングデータセットも減少させます)。
+
+さらに、この場合のバッチサイズは2で、データを2つのバッチに分割します。これにより、並列処理を可能にし、バッチごとの消費を減らすことが主な目的です。
+```python
+train_ratio = 0.90
+split_idx = int(train_ratio * len(text_data))
+train_data = text_data[:split_idx]
+val_data = text_data[split_idx:]
+
+torch.manual_seed(123)
+
+train_loader = create_dataloader_v1(
+train_data,
+batch_size=2,
+max_length=GPT_CONFIG_124M["context_length"],
+stride=GPT_CONFIG_124M["context_length"],
+drop_last=True,
+shuffle=True,
+num_workers=0
+)
+
+val_loader = create_dataloader_v1(
+val_data,
+batch_size=2,
+max_length=GPT_CONFIG_124M["context_length"],
+stride=GPT_CONFIG_124M["context_length"],
+drop_last=False,
+shuffle=False,
+num_workers=0
+)
+```
+## サニティチェック
+
+目的は、トレーニングに十分なトークンがあるか、形状が期待通りであるかを確認し、トレーニングおよび検証に使用されるトークンの数に関する情報を得ることです:
+```python
+# Sanity checks
+if total_tokens * (train_ratio) < GPT_CONFIG_124M["context_length"]:
+print("Not enough tokens for the training loader. "
+"Try to lower the `GPT_CONFIG_124M['context_length']` or "
+"increase the `training_ratio`")
+
+if total_tokens * (1-train_ratio) < GPT_CONFIG_124M["context_length"]:
+print("Not enough tokens for the validation loader. "
+"Try to lower the `GPT_CONFIG_124M['context_length']` or "
+"decrease the `training_ratio`")
+
+print("Train loader:")
+for x, y in train_loader:
+print(x.shape, y.shape)
+
+print("\nValidation loader:")
+for x, y in val_loader:
+print(x.shape, y.shape)
+
+train_tokens = 0
+for input_batch, target_batch in train_loader:
+train_tokens += input_batch.numel()
+
+val_tokens = 0
+for input_batch, target_batch in val_loader:
+val_tokens += input_batch.numel()
+
+print("Training tokens:", train_tokens)
+print("Validation tokens:", val_tokens)
+print("All tokens:", train_tokens + val_tokens)
+```
+### トレーニングと事前計算のためのデバイスを選択
+
+次のコードは、使用するデバイスを選択し、トレーニングロスとバリデーションロスを計算します(まだ何もトレーニングしていない状態で)出発点として。
+```python
+# Indicate the device to use
+
+if torch.cuda.is_available():
+device = torch.device("cuda")
+elif torch.backends.mps.is_available():
+device = torch.device("mps")
+else:
+device = torch.device("cpu")
+
+print(f"Using {device} device.")
+
+model.to(device) # no assignment model = model.to(device) necessary for nn.Module classes
+
+# Pre-calculate losses without starting yet
+torch.manual_seed(123) # For reproducibility due to the shuffling in the data loader
+
+with torch.no_grad(): # Disable gradient tracking for efficiency because we are not training, yet
+train_loss = calc_loss_loader(train_loader, model, device)
+val_loss = calc_loss_loader(val_loader, model, device)
+
+print("Training loss:", train_loss)
+print("Validation loss:", val_loss)
+```
+### トレーニング関数
+
+関数 `generate_and_print_sample` は、コンテキストを取得し、トークンを生成して、モデルのその時点での性能を把握するために使用されます。これは、各ステップで `train_model_simple` によって呼び出されます。
+
+関数 `evaluate_model` は、トレーニング関数が示す頻度で呼び出され、モデルのトレーニング時点でのトレインロスとバリデーションロスを測定するために使用されます。
+
+次に、大きな関数 `train_model_simple` が実際にモデルをトレーニングします。これは以下を期待します:
+
+- トレインデータローダー(トレーニング用にすでに分離され、準備されたデータ)
+- バリデータローダー
+- トレーニング中に使用する**オプティマイザー**:これは勾配を使用し、ロスを減少させるためにパラメータを更新する関数です。この場合、見ての通り `AdamW` が使用されますが、他にも多くのものがあります。
+- `optimizer.zero_grad()` は、勾配を蓄積しないように各ラウンドでリセットするために呼び出されます。
+- **`lr`** パラメータは **学習率** で、モデルのパラメータを更新する際の最適化プロセス中に取られる **ステップのサイズ** を決定します。**小さい** 学習率は、オプティマイザーが重みを **小さく更新** することを意味し、より **正確な** 収束をもたらす可能性がありますが、トレーニングが **遅くなる** 可能性があります。**大きい** 学習率はトレーニングを加速できますが、ロス関数の最小値を **オーバーシュートする** リスクがあります(ロス関数が最小化される点を **飛び越える**)。
+- **ウェイトデケイ** は、重みが大きいことにペナルティを与える追加の項を加えることで **ロス計算** ステップを修正します。これにより、オプティマイザーはデータにうまくフィットしつつ、モデルをシンプルに保ち、機械学習モデルでのオーバーフィッティングを防ぐために、特定の特徴に過度の重要性を与えないようにします。
+- SGDのような従来のオプティマイザーは、L2正則化とともにウェイトデケイをロス関数の勾配と結びつけます。しかし、**AdamW**(Adamオプティマイザーの変種)は、ウェイトデケイを勾配更新から切り離し、より効果的な正則化を実現します。
+- トレーニングに使用するデバイス
+- エポック数:トレーニングデータを何回通過するか
+- 評価頻度:`evaluate_model` を呼び出す頻度
+- 評価イテレーション:`generate_and_print_sample` を呼び出す際にモデルの現在の状態を評価するために使用するバッチの数
+- スタートコンテキスト:`generate_and_print_sample` を呼び出す際に使用する開始文
+- トークナイザー
+```python
+# Functions to train the data
+def train_model_simple(model, train_loader, val_loader, optimizer, device, num_epochs,
+eval_freq, eval_iter, start_context, tokenizer):
+# Initialize lists to track losses and tokens seen
+train_losses, val_losses, track_tokens_seen = [], [], []
+tokens_seen, global_step = 0, -1
+
+# Main training loop
+for epoch in range(num_epochs):
+model.train() # Set model to training mode
+
+for input_batch, target_batch in train_loader:
+optimizer.zero_grad() # Reset loss gradients from previous batch iteration
+loss = calc_loss_batch(input_batch, target_batch, model, device)
+loss.backward() # Calculate loss gradients
+optimizer.step() # Update model weights using loss gradients
+tokens_seen += input_batch.numel()
+global_step += 1
+
+# Optional evaluation step
+if global_step % eval_freq == 0:
+train_loss, val_loss = evaluate_model(
+model, train_loader, val_loader, device, eval_iter)
+train_losses.append(train_loss)
+val_losses.append(val_loss)
+track_tokens_seen.append(tokens_seen)
+print(f"Ep {epoch+1} (Step {global_step:06d}): "
+f"Train loss {train_loss:.3f}, Val loss {val_loss:.3f}")
+
+# Print a sample text after each epoch
+generate_and_print_sample(
+model, tokenizer, device, start_context
+)
+
+return train_losses, val_losses, track_tokens_seen
+
+
+def evaluate_model(model, train_loader, val_loader, device, eval_iter):
+model.eval() # Set in eval mode to avoid dropout
+with torch.no_grad():
+train_loss = calc_loss_loader(train_loader, model, device, num_batches=eval_iter)
+val_loss = calc_loss_loader(val_loader, model, device, num_batches=eval_iter)
+model.train() # Back to training model applying all the configurations
+return train_loss, val_loss
+
+
+def generate_and_print_sample(model, tokenizer, device, start_context):
+model.eval() # Set in eval mode to avoid dropout
+context_size = model.pos_emb.weight.shape[0]
+encoded = text_to_token_ids(start_context, tokenizer).to(device)
+with torch.no_grad():
+token_ids = generate_text(
+model=model, idx=encoded,
+max_new_tokens=50, context_size=context_size
+)
+decoded_text = token_ids_to_text(token_ids, tokenizer)
+print(decoded_text.replace("\n", " ")) # Compact print format
+model.train() # Back to training model applying all the configurations
+```
+> [!TIP]
+> 学習率を改善するために、**線形ウォームアップ**と**コサイン減衰**と呼ばれるいくつかの関連技術があります。
+>
+> **線形ウォームアップ**は、初期学習率と最大学習率を定義し、各エポックの後に一貫して更新することです。これは、より小さな重みの更新でトレーニングを開始することで、モデルがトレーニングフェーズ中に大きく不安定な更新に遭遇するリスクを減少させるためです。\
+> **コサイン減衰**は、**ウォームアップ**フェーズの後に半コサイン曲線に従って**学習率を徐々に減少させる**技術であり、重みの更新を遅くして**損失の最小値をオーバーシュートするリスクを最小限に抑え**、後のフェーズでのトレーニングの安定性を確保します。
+>
+> _これらの改善は前のコードには含まれていないことに注意してください。_
+
+### トレーニングを開始する
+```python
+import time
+start_time = time.time()
+
+torch.manual_seed(123)
+model = GPTModel(GPT_CONFIG_124M)
+model.to(device)
+optimizer = torch.optim.AdamW(model.parameters(), lr=0.0004, weight_decay=0.1)
+
+num_epochs = 10
+train_losses, val_losses, tokens_seen = train_model_simple(
+model, train_loader, val_loader, optimizer, device,
+num_epochs=num_epochs, eval_freq=5, eval_iter=5,
+start_context="Every effort moves you", tokenizer=tokenizer
+)
+
+end_time = time.time()
+execution_time_minutes = (end_time - start_time) / 60
+print(f"Training completed in {execution_time_minutes:.2f} minutes.")
+```
+### トレーニングの進化を印刷する
+
+次の関数を使用すると、モデルがトレーニングされている間の進化を印刷することができます。
+```python
+import matplotlib.pyplot as plt
+from matplotlib.ticker import MaxNLocator
+import math
+def plot_losses(epochs_seen, tokens_seen, train_losses, val_losses):
+fig, ax1 = plt.subplots(figsize=(5, 3))
+ax1.plot(epochs_seen, train_losses, label="Training loss")
+ax1.plot(
+epochs_seen, val_losses, linestyle="-.", label="Validation loss"
+)
+ax1.set_xlabel("Epochs")
+ax1.set_ylabel("Loss")
+ax1.legend(loc="upper right")
+ax1.xaxis.set_major_locator(MaxNLocator(integer=True))
+ax2 = ax1.twiny()
+ax2.plot(tokens_seen, train_losses, alpha=0)
+ax2.set_xlabel("Tokens seen")
+fig.tight_layout()
+plt.show()
+
+# Compute perplexity from the loss values
+train_ppls = [math.exp(loss) for loss in train_losses]
+val_ppls = [math.exp(loss) for loss in val_losses]
+# Plot perplexity over tokens seen
+plt.figure()
+plt.plot(tokens_seen, train_ppls, label='Training Perplexity')
+plt.plot(tokens_seen, val_ppls, label='Validation Perplexity')
+plt.xlabel('Tokens Seen')
+plt.ylabel('Perplexity')
+plt.title('Perplexity over Training')
+plt.legend()
+plt.show()
+
+epochs_tensor = torch.linspace(0, num_epochs, len(train_losses))
+plot_losses(epochs_tensor, tokens_seen, train_losses, val_losses)
+```
+### モデルを保存する
+
+後でトレーニングを続けたい場合は、モデルとオプティマイザーを保存することができます:
+```python
+# Save the model and the optimizer for later training
+torch.save({
+"model_state_dict": model.state_dict(),
+"optimizer_state_dict": optimizer.state_dict(),
+},
+"/tmp/model_and_optimizer.pth"
+)
+# Note that this model with the optimizer occupied close to 2GB
+
+# Restore model and optimizer for training
+checkpoint = torch.load("/tmp/model_and_optimizer.pth", map_location=device)
+
+model = GPTModel(GPT_CONFIG_124M)
+model.load_state_dict(checkpoint["model_state_dict"])
+optimizer = torch.optim.AdamW(model.parameters(), lr=5e-4, weight_decay=0.1)
+optimizer.load_state_dict(checkpoint["optimizer_state_dict"])
+model.train(); # Put in training mode
+```
+モデルを使用するだけの場合は、
+```python
+# Save the model
+torch.save(model.state_dict(), "model.pth")
+
+# Load it
+model = GPTModel(GPT_CONFIG_124M)
+
+model.load_state_dict(torch.load("model.pth", map_location=device))
+
+model.eval() # Put in eval mode
+```
+## GPT2の重みの読み込み
+
+GPT2の重みをローカルに読み込むための2つの簡単なスクリプトがあります。どちらもリポジトリをローカルにクローンできます [https://github.com/rasbt/LLMs-from-scratch](https://github.com/rasbt/LLMs-from-scratch) その後:
+
+- スクリプト [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/01_main-chapter-code/gpt_generate.py](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/01_main-chapter-code/gpt_generate.py) は、すべての重みをダウンロードし、OpenAIから私たちのLLMが期待する形式に変換します。このスクリプトは、必要な設定とプロンプト「Every effort moves you」を用意しています。
+- スクリプト [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/02_alternative_weight_loading/weight-loading-hf-transformers.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/02_alternative_weight_loading/weight-loading-hf-transformers.ipynb) は、任意のGPT2の重みをローカルに読み込むことを可能にします(`CHOOSE_MODEL`変数を変更するだけです)そして、いくつかのプロンプトからテキストを予測します。
+
+## 参考文献
+
+- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch)
diff --git a/src/AI/AI-llm-architecture/7.0.-lora-improvements-in-fine-tuning.md b/src/AI/AI-llm-architecture/7.0.-lora-improvements-in-fine-tuning.md
index 26252b209..60fa54bb6 100644
--- a/src/AI/AI-llm-architecture/7.0.-lora-improvements-in-fine-tuning.md
+++ b/src/AI/AI-llm-architecture/7.0.-lora-improvements-in-fine-tuning.md
@@ -1,22 +1,22 @@
-# 7.0. LoRAの微調整における改善
+# 7.0. LoRAのファインチューニングにおける改善
## LoRAの改善
> [!TIP]
-> **LoRAは微調整に必要な計算を大幅に削減します**。
+> **LoRAを使用することで、ファインチューニングに必要な計算が大幅に削減されます**。
-LoRAは、モデルの**小さな部分**のみを変更することで、**大規模モデル**を効率的に微調整することを可能にします。これにより、トレーニングに必要なパラメータの数が減り、**メモリ**と**計算リソース**を節約できます。これは以下の理由によります:
+LoRAは、モデルの**小さな部分**のみを変更することで、**大規模モデル**を効率的にファインチューニングすることを可能にします。これにより、トレーニングに必要なパラメータの数が減り、**メモリ**と**計算リソース**が節約されます。これは以下の理由によります:
1. **トレーニング可能なパラメータの数を削減**: モデル内の全体の重み行列を更新する代わりに、LoRAは重み行列を2つの小さな行列(**A**と**B**)に**分割**します。これにより、トレーニングが**速く**なり、更新する必要のあるパラメータが少ないため、**メモリ**も**少なく**て済みます。
-1. これは、レイヤー(行列)の完全な重み更新を計算する代わりに、2つの小さな行列の積に近似するため、計算する更新が減るからです:\
+1. これは、レイヤー(行列)の完全な重み更新を計算する代わりに、2つの小さな行列の積に近似するため、計算する更新が減少するからです:\
2. **元のモデルの重みを変更しない**: LoRAを使用すると、元のモデルの重みをそのままにしておき、**新しい小さな行列**(AとB)だけを更新できます。これは、モデルの元の知識が保持され、必要な部分だけを調整することを意味するため、便利です。
-3. **効率的なタスク特化型微調整**: モデルを**新しいタスク**に適応させたい場合、モデルの残りの部分をそのままにして、**小さなLoRA行列**(AとB)だけをトレーニングすればよいです。これは、モデル全体を再トレーニングするよりも**はるかに効率的**です。
-4. **ストレージ効率**: 微調整後、各タスクのために**新しいモデル全体**を保存する代わりに、**LoRA行列**だけを保存すればよく、これはモデル全体に比べて非常に小さいです。これにより、あまりストレージを使用せずにモデルを多くのタスクに適応させることが容易になります。
+3. **効率的なタスク特化型ファインチューニング**: モデルを**新しいタスク**に適応させたい場合、モデルの残りの部分をそのままにしておき、**小さなLoRA行列**(AとB)だけをトレーニングすればよいです。これは、モデル全体を再トレーニングするよりも**はるかに効率的**です。
+4. **ストレージ効率**: ファインチューニング後、各タスクのために**新しいモデル全体**を保存する代わりに、**LoRA行列**だけを保存すればよく、これはモデル全体に比べて非常に小さいです。これにより、多くのタスクにモデルを適応させる際に、過剰なストレージを使用せずに済みます。
-微調整中にLinearの代わりにLoraLayersを実装するために、ここで提案されているコードがあります [https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb):
+ファインチューニング中にLinearの代わりにLoraLayersを実装するために、ここで提案されているコードがあります [https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb):
```python
import math
diff --git a/src/AI/AI-llm-architecture/7.1.-fine-tuning-for-classification.md b/src/AI/AI-llm-architecture/7.1.-fine-tuning-for-classification.md
new file mode 100644
index 000000000..79ed64b2f
--- /dev/null
+++ b/src/AI/AI-llm-architecture/7.1.-fine-tuning-for-classification.md
@@ -0,0 +1,110 @@
+# 7.1. Fine-Tuning for Classification
+
+## What is
+
+ファインチューニングは、膨大なデータから一般的な言語パターンを学習した**事前学習済みモデル**を取り、それを**特定のタスク**を実行するためやドメイン特有の言語を理解するために**適応させる**プロセスです。これは、モデルのトレーニングを小さなタスク特化型データセットで続けることによって達成され、新しいデータのニュアンスにより適したパラメータに調整しながら、すでに取得した広範な知識を活用します。ファインチューニングにより、モデルは新しいモデルをゼロからトレーニングすることなく、専門的なアプリケーションでより正確で関連性のある結果を提供できるようになります。
+
+> [!TIP]
+> テキストを「理解する」LLMの事前トレーニングは非常に高価であるため、特定のタスクを実行するためにオープンソースの事前学習済みモデルをファインチューニングする方が通常は簡単で安価です。
+
+> [!TIP]
+> このセクションの目的は、すでに事前学習されたモデルをファインチューニングする方法を示すことです。したがって、新しいテキストを生成するのではなく、LLMは**与えられたテキストが各カテゴリに分類される確率を選択します**(例えば、テキストがスパムかどうか)。
+
+## Preparing the data set
+
+### Data set size
+
+もちろん、モデルをファインチューニングするには、LLMを専門化するために使用する構造化データが必要です。[https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb)で提案された例では、GPT2は、[https://archive.ics.uci.edu/static/public/228/sms+spam+collection.zip](https://archive.ics.uci.edu/static/public/228/sms+spam+collection.zip)のデータを使用して、メールがスパムかどうかを検出するようにファインチューニングされています。
+
+このデータセットには「スパムでない」例が「スパム」よりもはるかに多く含まれているため、本書では**「スパムでない」例を「スパム」と同じ数だけのみ使用する**ことを提案しています(したがって、トレーニングデータから余分な例を削除します)。この場合、各747例でした。
+
+次に、**70%**のデータセットが**トレーニング**に、**10%**が**検証**に、**20%**が**テスト**に使用されます。
+
+- **検証セット**は、トレーニングフェーズ中にモデルの**ハイパーパラメータ**をファインチューニングし、モデルアーキテクチャに関する決定を行うために使用され、見えないデータに対するモデルのパフォーマンスに関するフィードバックを提供することで、オーバーフィッティングを防ぐのに役立ちます。これは、最終評価をバイアスせずに反復的な改善を可能にします。
+- これは、このデータセットに含まれるデータが直接トレーニングには使用されないが、最良の**ハイパーパラメータ**を調整するために使用されることを意味します。したがって、このセットはテストセットのようにモデルのパフォーマンスを評価するためには使用できません。
+- 対照的に、**テストセット**は、モデルが完全にトレーニングされ、すべての調整が完了した**後にのみ**使用されます。これは、モデルが新しい見えないデータに一般化する能力を偏りなく評価します。このテストセットでの最終評価は、モデルが実際のアプリケーションでどのように機能するかの現実的な指標を提供します。
+
+### Entries length
+
+トレーニング例は同じ長さのエントリ(この場合はメールテキスト)を期待するため、すべてのエントリを最大のものと同じ大きさにすることに決定し、`<|endoftext|>`のIDをパディングとして追加しました。
+
+### Initialize the model
+
+オープンソースの事前学習済みウェイトを使用してモデルを初期化し、トレーニングを行います。これを以前に行ったことがあり、[https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb)の指示に従えば、簡単に行えます。
+
+## Classification head
+
+この特定の例(テキストがスパムかどうかを予測する)では、GPT2の完全な語彙に基づいてファインチューニングすることには興味がなく、新しいモデルにはメールがスパム(1)かどうか(0)を言わせたいだけです。したがって、語彙の各トークンの確率を提供する最終層を、スパムかどうかの確率のみを提供するものに**変更します**(つまり、2語の語彙のように)。
+```python
+# This code modified the final layer with a Linear one with 2 outs
+num_classes = 2
+model.out_head = torch.nn.Linear(
+
+in_features=BASE_CONFIG["emb_dim"],
+
+out_features=num_classes
+)
+```
+## 調整するパラメータ
+
+迅速にファインチューニングを行うためには、すべてのパラメータを調整するのではなく、最終的なパラメータの一部だけを調整する方が簡単です。これは、下位層が一般的に基本的な言語構造と適用可能な意味論を捉えることが知られているためです。したがって、**最後の層だけをファインチューニングすることが通常は十分であり、より速いです**。
+```python
+# This code makes all the parameters of the model unrtainable
+for param in model.parameters():
+param.requires_grad = False
+
+# Allow to fine tune the last layer in the transformer block
+for param in model.trf_blocks[-1].parameters():
+param.requires_grad = True
+
+# Allow to fine tune the final layer norm
+for param in model.final_norm.parameters():
+
+param.requires_grad = True
+```
+## トレーニングに使用するエントリ
+
+前のセクションでは、LLMは予測されたトークンの損失を減少させることでトレーニングされましたが、ほとんどすべての予測トークンは入力文に含まれていました(実際に予測されたのは最後の1つだけ)ので、モデルが言語をよりよく理解できるようにしました。
+
+この場合、モデルがスパムかどうかを予測できることだけが重要であるため、最後に予測されたトークンのみを考慮します。したがって、以前のトレーニング損失関数を修正して、そのトークンのみを考慮する必要があります。
+
+これは[https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb)で次のように実装されています:
+```python
+def calc_accuracy_loader(data_loader, model, device, num_batches=None):
+model.eval()
+correct_predictions, num_examples = 0, 0
+
+if num_batches is None:
+num_batches = len(data_loader)
+else:
+num_batches = min(num_batches, len(data_loader))
+for i, (input_batch, target_batch) in enumerate(data_loader):
+if i < num_batches:
+input_batch, target_batch = input_batch.to(device), target_batch.to(device)
+
+with torch.no_grad():
+logits = model(input_batch)[:, -1, :] # Logits of last output token
+predicted_labels = torch.argmax(logits, dim=-1)
+
+num_examples += predicted_labels.shape[0]
+correct_predictions += (predicted_labels == target_batch).sum().item()
+else:
+break
+return correct_predictions / num_examples
+
+
+def calc_loss_batch(input_batch, target_batch, model, device):
+input_batch, target_batch = input_batch.to(device), target_batch.to(device)
+logits = model(input_batch)[:, -1, :] # Logits of last output token
+loss = torch.nn.functional.cross_entropy(logits, target_batch)
+return loss
+```
+各バッチについて、**最後に予測されたトークンのロジット**のみに興味があることに注意してください。
+
+## 完全なGPT2ファインチューニング分類コード
+
+GPT2をスパム分類器としてファインチューニングするためのすべてのコードは[https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/load-finetuned-model.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/load-finetuned-model.ipynb)で見つけることができます。
+
+## 参考文献
+
+- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch)
diff --git a/src/AI/AI-llm-architecture/7.2.-fine-tuning-to-follow-instructions.md b/src/AI/AI-llm-architecture/7.2.-fine-tuning-to-follow-instructions.md
index bb9dbac8b..630f76ae4 100644
--- a/src/AI/AI-llm-architecture/7.2.-fine-tuning-to-follow-instructions.md
+++ b/src/AI/AI-llm-architecture/7.2.-fine-tuning-to-follow-instructions.md
@@ -27,7 +27,7 @@ Can you explain what gravity is in simple terms?
<|Assistant|>
Absolutely! Gravity is a force that pulls objects toward each other.
```
-トレーニングデータセットに生のテキストだけでなく、これらの種類のデータセットを使用することで、LLMは受け取る質問に対して具体的な応答を提供する必要があることを理解するのに役立ちます。
+LLMをこれらの種類のデータセットでトレーニングすることは、生のテキストだけでなく、LLMが受け取る質問に対して具体的な応答を提供する必要があることを理解するのに役立ちます。
したがって、リクエストと回答を含むデータセットで最初に行うべきことの1つは、そのデータを希望するプロンプト形式でモデル化することです。例えば:
```python
@@ -49,52 +49,52 @@ desired_response = f"\n\n### Response:\n{data[50]['output']}"
print(model_input + desired_response)
```
-Then, as always, it's needed to separate the dataset in sets for training, validation and testing.
+そのため、常にデータセットをトレーニング、検証、テスト用のセットに分ける必要があります。
-## Batching & Data Loaders
+## バッチ処理とデータローダー
-Then, it's needed to batch all the inputs and expected outputs for the training. For this, it's needed to:
+次に、トレーニング用のすべての入力と期待される出力をバッチ処理する必要があります。これには以下が必要です:
- テキストをトークン化する
-- すべてのサンプルを同じ長さにパディングする(通常、長さはLLMの事前トレーニングに使用されるコンテキストの長さと同じくらい大きくなる)
+- すべてのサンプルを同じ長さにパディングする(通常、長さはLLMの事前トレーニングに使用されるコンテキストの長さと同じくらいになります)
- カスタムコレート関数で入力を1つシフトして期待されるトークンを作成する
-- トレーニング損失から除外するために、いくつかのパディングトークンを-100に置き換える:最初の`endoftext`トークンの後、他のすべての`endoftext`トークンを-100に置き換える(`cross_entropy(...,ignore_index=-100)`を使用することは、-100のターゲットを無視することを意味する)
-- \[オプション\] LLMが回答を生成する方法だけを学ぶように、質問に属するすべてのトークンも-100を使用してマスクする。Apply Alpacaスタイルでは、`### Response:`までのすべてをマスクすることを意味する
+- トレーニング損失から除外するために、一部のパディングトークンを-100に置き換える:最初の`endoftext`トークンの後、他のすべての`endoftext`トークンを-100に置き換えます(`cross_entropy(...,ignore_index=-100)`を使用することで、-100のターゲットを無視します)
+- \[オプション\] LLMが回答を生成する方法のみを学習するように、質問に属するすべてのトークンも-100でマスクします。Alpacaスタイルを適用する場合、これは`### Response:`までのすべてをマスクすることを意味します。
これが作成されたら、各データセット(トレーニング、検証、テスト)のデータローダーを作成する時間です。
-## Load pre-trained LLM & Fine tune & Loss Checking
+## 事前トレーニングされたLLMのロードとファインチューニングおよび損失チェック
-事前トレーニングされたLLMをロードして微調整する必要があります。これは他のページで既に議論されています。次に、以前に使用したトレーニング関数を使用してLLMを微調整することができます。
+ファインチューニングするために、事前トレーニングされたLLMをロードする必要があります。これは他のページで既に議論されています。その後、以前に使用したトレーニング関数を使用してLLMをファインチューニングできます。
-トレーニング中は、エポック中にトレーニング損失と検証損失がどのように変化するかを確認して、損失が減少しているか、過学習が発生しているかを確認することもできます。\
-過学習は、トレーニング損失が減少しているが、検証損失が減少していないか、さらには増加している場合に発生します。これを避けるために、最も簡単な方法は、この挙動が始まるエポックでトレーニングを停止することです。
+トレーニング中、エポックごとにトレーニング損失と検証損失がどのように変化するかを確認して、損失が減少しているか、過学習が発生しているかを確認することも可能です。\
+過学習は、トレーニング損失が減少しているが、検証損失が減少していないか、むしろ増加している場合に発生します。これを避けるために、最も簡単な方法は、この挙動が始まるエポックでトレーニングを停止することです。
-## Response Quality
+## 応答の質
-これは分類の微調整ではなく、損失の変動をより信頼できるため、テストセットの応答の質を確認することも重要です。したがって、生成された応答をすべてのテストセットから収集し、**手動でその質を確認する**ことをお勧めします。間違った回答があるかどうかを確認してください(LLMが応答文の形式と構文を正しく作成することは可能ですが、完全に間違った応答を提供することがあります。損失の変動はこの挙動を反映しません)。\
-生成された応答と期待される応答を**他のLLMに渡して応答を評価するように依頼する**ことでも、このレビューを実施することが可能です。
+これは分類ファインチューニングではないため、損失の変動をより信頼できるわけではありませんが、テストセットの応答の質を確認することも重要です。したがって、生成された応答をすべてのテストセットから収集し、**手動でその質を確認する**ことをお勧めします。間違った回答があるかどうかを確認します(LLMが応答文の形式と構文を正しく作成することは可能ですが、完全に間違った応答を返すことがあります。損失の変動はこの挙動を反映しません)。\
+生成された応答と期待される応答を**他のLLMに渡して応答を評価させる**ことでも、このレビューを行うことが可能です。
応答の質を確認するために実行する他のテスト:
-1. **Measuring Massive Multitask Language Understanding (**[**MMLU**](https://arxiv.org/abs/2009.03300)**):** MMLUは、モデルの知識と問題解決能力を57の科目(人文学、科学など)にわたって評価します。さまざまな難易度レベルの理解を評価するために選択肢形式の質問を使用します。
-2. [**LMSYS Chatbot Arena**](https://arena.lmsys.org): このプラットフォームでは、ユーザーが異なるチャットボットの応答を並べて比較できます。ユーザーはプロンプトを入力し、複数のチャットボットが生成した応答を直接比較できます。
-3. [**AlpacaEval**](https://github.com/tatsu-lab/alpaca_eval)**:** AlpacaEvalは、GPT-4のような高度なLLMがさまざまなプロンプトに対する他のモデルの応答を評価する自動評価フレームワークです。
-4. **General Language Understanding Evaluation (**[**GLUE**](https://gluebenchmark.com/)**):** GLUEは、感情分析、テキストの含意、質問応答など、9つの自然言語理解タスクのコレクションです。
-5. [**SuperGLUE**](https://super.gluebenchmark.com/)**:** GLUEを基にして、SuperGLUEは現在のモデルにとって難しいとされるより挑戦的なタスクを含んでいます。
-6. **Beyond the Imitation Game Benchmark (**[**BIG-bench**](https://github.com/google/BIG-bench)**):** BIG-benchは、推論、翻訳、質問応答などの分野でモデルの能力をテストする200以上のタスクを持つ大規模なベンチマークです。
-7. **Holistic Evaluation of Language Models (**[**HELM**](https://crfm.stanford.edu/helm/lite/latest/)**):** HELMは、精度、堅牢性、公平性など、さまざまな指標にわたる包括的な評価を提供します。
-8. [**OpenAI Evals**](https://github.com/openai/evals)**:** OpenAIによるオープンソースの評価フレームワークで、カスタムおよび標準化されたタスクでAIモデルをテストできます。
-9. [**HumanEval**](https://github.com/openai/human-eval)**:** プログラミング問題のコレクションで、言語モデルのコード生成能力を評価するために使用されます。
-10. **Stanford Question Answering Dataset (**[**SQuAD**](https://rajpurkar.github.io/SQuAD-explorer/)**):** SQuADは、モデルが正確に回答するためにテキストを理解しなければならないWikipedia記事に関する質問で構成されています。
-11. [**TriviaQA**](https://nlp.cs.washington.edu/triviaqa/)**:** トリビアの質問と回答の大規模データセットで、証拠文書も含まれています。
+1. **大規模マルチタスク言語理解(**[**MMLU**](https://arxiv.org/abs/2009.03300)**):** MMLUは、文科、科学など57の科目にわたるモデルの知識と問題解決能力を評価します。さまざまな難易度の選択肢問題を使用して理解を評価します。
+2. [**LMSYSチャットボットアリーナ**](https://arena.lmsys.org):このプラットフォームでは、ユーザーが異なるチャットボットの応答を並べて比較できます。ユーザーがプロンプトを入力すると、複数のチャットボットが応答を生成し、直接比較できます。
+3. [**AlpacaEval**](https://github.com/tatsu-lab/alpaca_eval)**:** AlpacaEvalは、GPT-4のような高度なLLMがさまざまなプロンプトに対する他のモデルの応答を評価する自動評価フレームワークです。
+4. **一般言語理解評価(**[**GLUE**](https://gluebenchmark.com/)**):** GLUEは、感情分析、テキストの含意、質問応答など、9つの自然言語理解タスクのコレクションです。
+5. [**SuperGLUE**](https://super.gluebenchmark.com/)**:** GLUEを基にして、SuperGLUEは現在のモデルにとって難しいとされるより挑戦的なタスクを含んでいます。
+6. **模倣ゲームベンチマークを超えて(**[**BIG-bench**](https://github.com/google/BIG-bench)**):** BIG-benchは、推論、翻訳、質問応答などの分野でモデルの能力をテストする200以上のタスクを持つ大規模なベンチマークです。
+7. **言語モデルの包括的評価(**[**HELM**](https://crfm.stanford.edu/helm/lite/latest/)**):** HELMは、精度、堅牢性、公平性など、さまざまな指標にわたる包括的な評価を提供します。
+8. [**OpenAI Evals**](https://github.com/openai/evals)**:** OpenAIによるオープンソースの評価フレームワークで、カスタムおよび標準化されたタスクでAIモデルをテストできます。
+9. [**HumanEval**](https://github.com/openai/human-eval)**:** コード生成能力を評価するために使用されるプログラミング問題のコレクションです。
+10. **スタンフォード質問応答データセット(**[**SQuAD**](https://rajpurkar.github.io/SQuAD-explorer/)**):** SQuADは、モデルが正確に回答するためにテキストを理解しなければならないWikipedia記事に関する質問で構成されています。
+11. [**TriviaQA**](https://nlp.cs.washington.edu/triviaqa/)**:** トリビアの質問と回答の大規模データセットで、証拠文書も含まれています。
-and many many more
+その他多数
-## Follow instructions fine-tuning code
+## 指示に従ったファインチューニングコード
-You can find an example of the code to perform this fine tuning in [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch07/01_main-chapter-code/gpt_instruction_finetuning.py](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch07/01_main-chapter-code/gpt_instruction_finetuning.py)
+このファインチューニングを実行するためのコードの例は、[https://github.com/rasbt/LLMs-from-scratch/blob/main/ch07/01_main-chapter-code/gpt_instruction_finetuning.py](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch07/01_main-chapter-code/gpt_instruction_finetuning.py)で見つけることができます。
-## References
+## 参考文献
- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch)
diff --git a/src/AI/AI-llm-architecture/README.md b/src/AI/AI-llm-architecture/README.md
index 8aced466f..24f6b1ca5 100644
--- a/src/AI/AI-llm-architecture/README.md
+++ b/src/AI/AI-llm-architecture/README.md
@@ -1,10 +1,10 @@
# LLMトレーニング - データ準備
-**これは非常に推奨される本** [**https://www.manning.com/books/build-a-large-language-model-from-scratch**](https://www.manning.com/books/build-a-large-language-model-from-scratch) **からの私のノートで、いくつかの追加情報が含まれています。**
+**これは非常に推奨される本** [**https://www.manning.com/books/build-a-large-language-model-from-scratch**](https://www.manning.com/books/build-a-large-language-model-from-scratch) **からの私のメモで、いくつかの追加情報が含まれています。**
## 基本情報
-知っておくべき基本概念については、この投稿を読むことから始めるべきです:
+まず、知っておくべき基本概念についてこの投稿を読むべきです:
{{#ref}}
0.-basic-llm-concepts.md
@@ -22,7 +22,7 @@
## 2. データサンプリング
> [!TIP]
-> この第二段階の目標は非常にシンプルです:**入力データをサンプリングし、通常は特定の長さの文にデータセットを分け、期待される応答も生成することでトレーニングフェーズの準備をすること**。
+> この第二段階の目標は非常にシンプルです:**入力データをサンプリングし、通常は特定の長さの文にデータセットを分け、期待される応答も生成することでトレーニング段階の準備をすること**。
{{#ref}}
2.-data-sampling.md
@@ -31,7 +31,7 @@
## 3. トークン埋め込み
> [!TIP]
-> この第三段階の目標は非常にシンプルです:**語彙内の各トークンに対して、モデルをトレーニングするために必要な次元のベクトルを割り当てること**。語彙内の各単語はX次元の空間内の点になります。\
+> この第三段階の目標は非常にシンプルです:**語彙内の各トークンにモデルをトレーニングするために必要な次元のベクトルを割り当てること**。語彙内の各単語はX次元の空間内の点になります。\
> 最初は、各単語の空間内の位置は「ランダムに」初期化され、これらの位置はトレーニング中に改善されるトレーニング可能なパラメータです。
>
> さらに、トークン埋め込み中に**別の埋め込み層が作成され**、これは(この場合)**トレーニング文内の単語の絶対位置を表します**。このように、文内の異なる位置にある単語は異なる表現(意味)を持ちます。
@@ -43,7 +43,7 @@
## 4. アテンションメカニズム
> [!TIP]
-> この第四段階の目標は非常にシンプルです:**いくつかのアテンションメカニズムを適用すること**。これらは、**語彙内の単語と現在トレーニングに使用されている文内の隣接単語との関係を捉えるための多くの**繰り返し層**になります。\
+> この第四段階の目標は非常にシンプルです:**いくつかのアテンションメカニズムを適用すること**。これらは、**語彙内の単語と現在トレーニングに使用されている文内の隣接単語との関係を捉えるための多くの**「繰り返し層」**になります**。\
> これには多くの層が使用されるため、多くのトレーニング可能なパラメータがこの情報を捉えることになります。
{{#ref}}
@@ -64,7 +64,7 @@
## 6. 事前トレーニングとモデルの読み込み
> [!TIP]
-> この第六段階の目標は非常にシンプルです:**ゼロからモデルをトレーニングすること**。これには、定義された損失関数とオプティマイザを使用して、モデルのすべてのパラメータをトレーニングするために、前のLLMアーキテクチャが使用されます。
+> この第六段階の目標は非常にシンプルです:**ゼロからモデルをトレーニングすること**。これには、定義された損失関数とオプティマイザを使用して、モデルのすべてのパラメータをトレーニングするためにデータセットをループする前のLLMアーキテクチャが使用されます。
{{#ref}}
6.-pre-training-and-loading-models.md