<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>AI &gt; 深層学習 on M1KE BL0G</title><link>https://www.m1ke.org/categories/ai_dl/</link><description>Recent content in AI &gt; 深層学習 on M1KE BL0G</description><generator>Hugo -- gohugo.io</generator><language>ja-jp</language><copyright>mike</copyright><atom:link href="https://www.m1ke.org/categories/ai_dl/index.xml" rel="self" type="application/rss+xml"/><item><title>Reservoir Computingとコネクトームで、実際にハエを動かしてみた</title><link>https://www.m1ke.org/p/reservoir-computing%E3%81%A8%E3%82%B3%E3%83%8D%E3%82%AF%E3%83%88%E3%83%BC%E3%83%A0%E3%81%A7%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%83%8F%E3%82%A8%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/</link><pubDate>Wed, 09 Sep 2026 12:00:00 +0900</pubDate><guid>https://www.m1ke.org/p/reservoir-computing%E3%81%A8%E3%82%B3%E3%83%8D%E3%82%AF%E3%83%88%E3%83%BC%E3%83%A0%E3%81%A7%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%83%8F%E3%82%A8%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/</guid><description>&lt;img src="https://www.m1ke.org/p/reservoir-computing%E3%81%A8%E3%82%B3%E3%83%8D%E3%82%AF%E3%83%88%E3%83%BC%E3%83%A0%E3%81%A7%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%83%8F%E3%82%A8%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/image.png" alt="Featured image of post Reservoir Computingとコネクトームで、実際にハエを動かしてみた" /&gt;&lt;h2 id="背景"&gt;背景&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;XでコネクトームをReservoir Computingで移植している人がいた&lt;/li&gt;
&lt;li&gt;「生物の神経結合構造を、機械学習の計算基盤として流用する」という研究分野が存在する&lt;/li&gt;
&lt;li&gt;これは、攻殻機動隊的な「人間の脳をまるごとサイバー化する電脳化」とは別の話ではある&lt;/li&gt;
&lt;li&gt;ここでは、Reservoir Computingの基本と、その延長線上にあるコネクトームベースの研究を整理した&lt;/li&gt;
&lt;li&gt;また、簡易的にハエのシミュレーターでハエの幼虫の脳を接続してみた&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="reservoir-computing"&gt;Reservoir Computing&lt;/h2&gt;
&lt;h3 id="reservoirとは"&gt;Reservoirとは&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;リザバー（reservoir）は、「貯水池」の意味
&lt;ul&gt;
&lt;li&gt;命名の由来は、入力された情報をいったん受け止めて、内部に複雑な状態として蓄えておく“大きな器”に近い&lt;/li&gt;
&lt;li&gt;典型的な説明でも多数のニューロンがつながった内部ネットワークを「pool」や「reservoir」と呼ぶから&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Reservoir Computingにおける固定された再帰結合部分のこと&lt;/li&gt;
&lt;li&gt;入力を受け取り、内部で高次元・非線形な力学系として反応させる層&lt;/li&gt;
&lt;li&gt;ランダムに初期化された結合を持ち、学習では一切更新されない&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="reservoirの名前の由来"&gt;Reservoirの名前の由来&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;リザバーコンピューティングは、次の別々に提案された枠組みをまとめられるためにつけられた
&lt;ul&gt;
&lt;li&gt;Liquid State Machine（LSM）&lt;/li&gt;
&lt;li&gt;Echo State Network（ESN）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;LSMは液体に石を落としたときの波紋のように、入力が内部状態へ複雑に広がっていくイメージを持つ&lt;/li&gt;
&lt;li&gt;他方、ESNは入力の影響が「echo＝残響」のように内部へ残ることを表している&lt;/li&gt;
&lt;li&gt;後に、こうした「入力を受け止め、時間的な情報を内部状態として保持・変換する部分」を reservoir（貯水池） と呼んだ&lt;/li&gt;
&lt;li&gt;そして、それらを総称して Reservoir Computing と呼ぶようになった&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="reservoir-computingとは"&gt;Reservoir Computingとは&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;内部の再帰結合（リザバー）はランダムに固定したまま、出力層の線形結合だけを学習する枠組み&lt;/li&gt;
&lt;li&gt;大きく重み付き和で学習する通常のニューラルネットと違い、&lt;/li&gt;
&lt;li&gt;リザバー自体は学習せず、入力を高次元の非線形な力学系の軌道に変換する役割だけを担う&lt;/li&gt;
&lt;li&gt;学習対象がリザバーではなく出力層の線形回帰だけになるため、通常のRNNに比べて学習コストが大幅に小さい&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/reservoir-computing%E3%81%A8%E3%82%B3%E3%83%8D%E3%82%AF%E3%83%88%E3%83%BC%E3%83%A0%E3%81%A7%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%83%8F%E3%82%A8%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/rc.png"
width="685"
height="349"
srcset="https://www.m1ke.org/p/reservoir-computing%E3%81%A8%E3%82%B3%E3%83%8D%E3%82%AF%E3%83%88%E3%83%BC%E3%83%A0%E3%81%A7%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%83%8F%E3%82%A8%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/rc_hu_4a90caa5c7f79fa5.png 480w, https://www.m1ke.org/p/reservoir-computing%E3%81%A8%E3%82%B3%E3%83%8D%E3%82%AF%E3%83%88%E3%83%BC%E3%83%A0%E3%81%A7%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%83%8F%E3%82%A8%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/rc_hu_9d5d41ea84f89a55.png 1024w"
loading="lazy"
alt="Reservoir Computetingの構造"
class="gallery-image"
data-flex-grow="196"
data-flex-basis="471px"
&gt;&lt;/p&gt;
&lt;h3 id="reservoir-computingの源流"&gt;Reservoir Computingの源流&lt;/h3&gt;
&lt;p&gt;Reservoir Computingには、大きく2つの源流がある:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Echo State Network（ESN）:
&lt;ul&gt;
&lt;li&gt;Herbert Jaegerが2001年に提案（&lt;code&gt;The &amp;quot;echo state&amp;quot; approach to analysing and training recurrent neural networks&lt;/code&gt;, GMD Report 148）&lt;/li&gt;
&lt;li&gt;実数値のリカレントニューラルネットをリザバーとして使う&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Liquid State Machine（LSM）:
&lt;ul&gt;
&lt;li&gt;Wolfgang Maass, Thomas Natschläger, Henry Markramが2002年に提案（&lt;code&gt;Real-time computing without stable states: A new framework for neural computation based on perturbations&lt;/code&gt;, Neural Computation 14(11), 2531-2560）&lt;/li&gt;
&lt;li&gt;スパイキングニューロンをリザバーとして使う、より生物学的に妥当なモデル&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;いずれも「リザバーは固定・訓練するのは読み出し層のみ」という設計思想は共通している。&lt;/p&gt;
&lt;h2 id="リザバーとしてのコネクトーム"&gt;リザバーとしての「コネクトーム」&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;コネクトームとは、脳内のニューロン間の結合構造（構造的結合）を網羅的に記述したもの&lt;/li&gt;
&lt;li&gt;通常のESN・LSMでは、リザバー内部の結合はランダムな行列として初期化される&lt;/li&gt;
&lt;li&gt;コネクトームベースのReservoir Computingは、このランダム行列の代わりに、実在の生物から得られたコネクトーム由来の結合行列をそのままリザバーの結合構造として使う、という発想&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;つまり「配線図をランダムに作る」代わりに「実物の脳の配線図を借りてくる」ことで、リザバーを構成する。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/reservoir-computing%E3%81%A8%E3%82%B3%E3%83%8D%E3%82%AF%E3%83%88%E3%83%BC%E3%83%A0%E3%81%A7%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%83%8F%E3%82%A8%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/Connectome.jpg"
width="964"
height="720"
srcset="https://www.m1ke.org/p/reservoir-computing%E3%81%A8%E3%82%B3%E3%83%8D%E3%82%AF%E3%83%88%E3%83%BC%E3%83%A0%E3%81%A7%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%83%8F%E3%82%A8%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/Connectome_hu_d6c6ec79cbf7a98f.jpg 480w, https://www.m1ke.org/p/reservoir-computing%E3%81%A8%E3%82%B3%E3%83%8D%E3%82%AF%E3%83%88%E3%83%BC%E3%83%A0%E3%81%A7%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%83%8F%E3%82%A8%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/Connectome_hu_4910c420c054b147.jpg 1024w"
loading="lazy"
alt="コネクトーム"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="321px"
&gt;&lt;/p&gt;
&lt;h2 id="conn2resツールボックス"&gt;conn2resツールボックス&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Suárez, Mihalik, Milisav, Marshall, Li, Vértes, Lajoie, Misicによる&lt;code&gt;Connectome-based reservoir computing with the conn2res toolbox&lt;/code&gt;（Nature Communications, 2024, &lt;a class="link" href="https://www.nature.com/articles/s41467-024-44900-4" target="_blank" rel="noopener"
&gt;doi:10.1038/s41467-024-44900-4&lt;/a&gt;）が、この分野の代表的なツールキット&lt;/li&gt;
&lt;li&gt;束追跡（tract tracing）や拡散MRIなど、複数の手法で再構成されたコネクトームを入力として受け付けるモジュール設計&lt;/li&gt;
&lt;li&gt;リザバー内部のダイナミクスも、スパイキングニューロンからメムリスタ的な力学系まで、複数の選択肢を差し替えられる&lt;/li&gt;
&lt;li&gt;実装されたコネクトームに、認知タスクを解かせるという形で評価する&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="具体的な研究例"&gt;具体的な研究例&lt;/h2&gt;
&lt;h3 id="ショウジョウバエのコネクトームを使う研究"&gt;ショウジョウバエのコネクトームを使う研究&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Jacob Morra, Mark Daleyによる&lt;code&gt;Imposing Connectome-Derived Topology on an Echo State Network&lt;/code&gt;（&lt;a class="link" href="https://arxiv.org/abs/2201.09359" target="_blank" rel="noopener"
&gt;arXiv:2201.09359&lt;/a&gt;）
&lt;ul&gt;
&lt;li&gt;ショウジョウバエのコネクトーム由来の結合行列で、ESNのリザバー層をそのまま置き換えたモデル（Fruit Fly ESN, FFESN）を提案&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Leone Costi, Alexander Hadjiivanov, Dominik Dold, Zachary F. Hale, Dario Izzoによる&lt;code&gt;The Drosophila Connectome as a Computational Reservoir for Time-Series Prediction&lt;/code&gt;（Biomimetics, 2025, &lt;a class="link" href="https://pmc.ncbi.nlm.nih.gov/articles/PMC12109256/" target="_blank" rel="noopener"
&gt;PMC12109256&lt;/a&gt;）
&lt;ul&gt;
&lt;li&gt;ショウジョウバエのコネクトームをリザバーとして、時系列予測タスクを解かせている&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="人間の脳のコネクトームを使う研究"&gt;人間の脳のコネクトームを使う研究&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Accessing the topological properties of human brain functional sub-circuits in Echo State Networks&lt;/code&gt;（&lt;a class="link" href="https://arxiv.org/abs/2412.14999" target="_blank" rel="noopener"
&gt;arXiv:2412.14999&lt;/a&gt;）
&lt;ul&gt;
&lt;li&gt;人間の脳の機能的結合から抽出したサブサーキットの構造をESNに組み込む研究&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Using Connectome Features to Constrain Echo State Networks&lt;/code&gt;（&lt;a class="link" href="https://arxiv.org/abs/2206.02094" target="_blank" rel="noopener"
&gt;arXiv:2206.02094&lt;/a&gt;）
&lt;ul&gt;
&lt;li&gt;コネクトームから抽出した特徴量（次数分布やモジュール性など）を、リザバーの構成に制約として使う研究&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;人間の完全な構造的コネクトーム（シナプスレベルの全結線図）は、2026年現在も完全なマッピングには至っていないため、人間を対象とした研究の多くは、拡散MRI由来の構造的結合や機能的結合のデータを使っている。&lt;/p&gt;
&lt;h2 id="なぜ実際の配線構造を使うのか"&gt;なぜ実際の配線構造を使うのか&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ランダムな結合と、実際の生物の結合構造とで、リザバーとしての性能（記憶容量やタスク精度）に違いが出るかを調べるのが主な動機&lt;/li&gt;
&lt;li&gt;生物の脳が、進化の過程で計算に有利な結合構造を獲得してきたのかどうかを、機械学習の評価指標を使って検証できる&lt;/li&gt;
&lt;li&gt;逆に、リザバーとしての性能という切り口から、コネクトームの構造そのものへの理解を深めるという、神経科学側からの動機もある&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="電脳化との違い"&gt;電脳化との違い&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;「電脳化」は、人間の意識・記憶をまるごとサイバネティックな基盤へ移し替えるSF的な概念&lt;/li&gt;
&lt;li&gt;一方、ここで扱ったコネクトームベースのReservoir Computingは、脳の意識や記憶を移植しているわけではなく、あくまで結合構造（配線図）だけを、機械学習の計算資源として流用している&lt;/li&gt;
&lt;li&gt;対象も、現状ではショウジョウバエや線虫といった、コネクトームが比較的解明されている小規模な生物が中心で、人間の全脳を対象にした研究はまだ限定的&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="実際にコネクトームでハエを動かしてみた"&gt;実際にコネクトームでハエを動かしてみた&lt;/h2&gt;
&lt;p&gt;理論の紹介だけで終わらせず、実際に手元で動かして確かめてみた。&lt;/p&gt;
&lt;h3 id="使ったデータと環境"&gt;使ったデータと環境&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;コネクトームには、幼虫ショウジョウバエの全脳（Winding et al. 2023, Science、2952ニューロン、約548,000シナプス）を使用&lt;/li&gt;
&lt;li&gt;ログイン不要で取得できる&lt;code&gt;brain-networks/larval-drosophila-connectome&lt;/code&gt;というミラーリポジトリのデータをそのまま利用&lt;/li&gt;
&lt;li&gt;身体側には、成体ショウジョウバエの生体力学モデルをMuJoCo上でシミュレートするflygym（NeuroMechFly v2、EPFL Ramdya lab）を使用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;幼虫の脳と成体の身体を組み合わせるのは解剖学的には矛盾しているが、「まずパイプライン自体を動かす」ことを優先して割り切った。&lt;/p&gt;
&lt;h3 id="全体の構成"&gt;全体の構成&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;コネクトームの&lt;code&gt;annotations.csv&lt;/code&gt;から、&lt;code&gt;sensory&lt;/code&gt;（感覚ニューロン）と&lt;code&gt;DN-VNC&lt;/code&gt;（下行性ニューロン、脳から運動系への出口）を、それぞれ左右の半球ごとに取り出す&lt;/li&gt;
&lt;li&gt;左右の感覚ニューロンを刺激入力とし、コネクトームの結合行列をそのままリザバーとして信号を伝播させる&lt;/li&gt;
&lt;li&gt;左右のDN-VNCの活動を読み出し、flygymの旋回コントローラー（&lt;code&gt;HybridTurningController&lt;/code&gt;）が受け取る2次元の&lt;code&gt;descending_signal&lt;/code&gt;（左右の駆動信号）にそのまま変換する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="flyのコネクトーム"&gt;flyのコネクトーム&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/reservoir-computing%E3%81%A8%E3%82%B3%E3%83%8D%E3%82%AF%E3%83%88%E3%83%BC%E3%83%A0%E3%81%A7%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%83%8F%E3%82%A8%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/The_connectome_of_an_insect_brain.jpg"
width="4330"
height="2627"
srcset="https://www.m1ke.org/p/reservoir-computing%E3%81%A8%E3%82%B3%E3%83%8D%E3%82%AF%E3%83%88%E3%83%BC%E3%83%A0%E3%81%A7%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%83%8F%E3%82%A8%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/The_connectome_of_an_insect_brain_hu_22e073b37b9f53.jpg 480w, https://www.m1ke.org/p/reservoir-computing%E3%81%A8%E3%82%B3%E3%83%8D%E3%82%AF%E3%83%88%E3%83%BC%E3%83%A0%E3%81%A7%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%83%8F%E3%82%A8%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/The_connectome_of_an_insect_brain_hu_55f320c51f76f272.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="164"
data-flex-basis="395px"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sensory neurons（SN）-&amp;gt; 脳内の interneurons -&amp;gt; DN^VNCという整理の図&lt;/li&gt;
&lt;li&gt;Sensory は、匂い・味・温度・機械刺激などを外界から脳へ持ってくる入力ニューロン&lt;/li&gt;
&lt;li&gt;一方、DN^VNC は Descending Neurons to Ventral Nerve Cord の意味で、脳で処理された情報を腹側神経索（VNC）へ送り、歩行などの行動につなげる出力ニューロン&lt;/li&gt;
&lt;li&gt;food odor -&amp;gt; sensory neurons -&amp;gt; 幼虫の脳コネクトーム -&amp;gt; DN-VNC / DN-SEZ -&amp;gt; 仮想の身体という流れを作る&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="つまずいた点-スペクトル半径正規化"&gt;つまずいた点: スペクトル半径正規化&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;最初は、Echo State Networkの定石通り、リザバー全体のスペクトル半径を1未満（0.9）に正規化していた&lt;/li&gt;
&lt;li&gt;ところがこの方法だと、DN-VNCの活動がほぼゼロに埋もれてしまい、左右の刺激に対して意味のある差が全く出なかった&lt;/li&gt;
&lt;li&gt;原因は、キノコ体のような密な再帰結合を持つ部分がスペクトル半径の大部分を支配していて、感覚ニューロンからDN-VNCまでの数ホップの経路の信号まで、まとめて桁違いに縮小されていたこと&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そこで、各ニューロンの出力側の重み合計を一定値に正規化する方式（row normalization）に切り替えた。全体を1つの係数で縮小するのではなく、ニューロンごとに正規化することで、密な再帰部分に信号が引きずられずに、数ホップ先まで伝わるようになった。&lt;/p&gt;
&lt;h3 id="結果-対側性の効果"&gt;結果: 対側性の効果&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;左の感覚ニューロンを刺激すると、左右のDN-VNCの活動はほぼ同程度（差はわずか）&lt;/li&gt;
&lt;li&gt;右の感覚ニューロンを刺激すると、なぜか&lt;strong&gt;左側&lt;/strong&gt;のDN-VNCの方が明確に強く反応した&lt;/li&gt;
&lt;li&gt;これは、昆虫の感覚運動経路が体の正中線を交差しているという、実際の解剖学とも符合する結果&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;もちろん、入力の強さや正規化の度合いといったパラメータは、この効果が見えるように手で調整したものであり、生理学的に検証された値ではない。それでも、実際のコネクトームの配線を信号が通った結果として、こうした対側性の効果が現れたのは興味深い。&lt;/p&gt;
&lt;h3 id="リアルタイムで見る"&gt;リアルタイムで見る&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;オフラインで動画として書き出す版に加えて、MuJoCoのインタラクティブビューアでリアルタイムに動きを見られる版も作った&lt;/li&gt;
&lt;li&gt;最初はビューアのカメラ位置を手探りで調整していたが、地面に対してハエ本体が小さすぎてうまく合わせられなかった&lt;/li&gt;
&lt;li&gt;最終的に、flygymが標準で用意している&lt;code&gt;fly.add_tracking_camera()&lt;/code&gt;をビューアの固定カメラとしてそのまま使う方式に切り替えたところ、一発で解決した&lt;/li&gt;
&lt;/ul&gt;
&lt;video controls width="100%"&gt;
&lt;source src="video.mp4" type="video/mp4"&gt;
Your browser does not support the video tag.
&lt;/video&gt;
&lt;h2 id="まとめ"&gt;まとめ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Reservoir Computingは、リザバー部分を固定し出力層だけを学習する枠組みで、Echo State Network（Jaeger, 2001）とLiquid State Machine（Maass et al., 2002）が源流&lt;/li&gt;
&lt;li&gt;コネクトームベースのReservoir Computingは、リザバーのランダムな結合行列を、実在の生物のコネクトーム由来の結合構造に置き換える研究分野&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conn2res&lt;/code&gt;ツールボックス（Suárez et al., 2024, Nature Communications）が代表的な実装で、ショウジョウバエや人間の脳のデータに対応している&lt;/li&gt;
&lt;li&gt;ショウジョウバエのコネクトームをそのままリザバーとして使う研究（Morra &amp;amp; Daley 2022, Costi et al. 2025）や、人間の脳の機能的結合を使う研究がある&lt;/li&gt;
&lt;li&gt;「電脳化」のような意識の移植ではなく、あくまで配線構造を計算基盤として借用するという話&lt;/li&gt;
&lt;li&gt;実際に幼虫コネクトーム＋flygymで試したところ、スペクトル半径正規化では信号が埋もれてしまい、row normalizationに切り替えることで、左右刺激に対する対側性の効果が観察できた&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Jaeger, H. (2001). &amp;ldquo;The &amp;rsquo;echo state&amp;rsquo; approach to analysing and training recurrent neural networks.&amp;rdquo; GMD Report 148.&lt;/li&gt;
&lt;li&gt;Maass, W., Natschläger, T., Markram, H. (2002). &amp;ldquo;Real-time computing without stable states: A new framework for neural computation based on perturbations.&amp;rdquo; Neural Computation, 14(11), 2531-2560.&lt;/li&gt;
&lt;li&gt;Suárez, L.E., Mihalik, A., Milisav, F., Marshall, K., Li, M., Vértes, P.E., Lajoie, G., Misic, B. (2024). &amp;ldquo;Connectome-based reservoir computing with the conn2res toolbox.&amp;rdquo; Nature Communications, 15. &lt;a class="link" href="https://www.nature.com/articles/s41467-024-44900-4" target="_blank" rel="noopener"
&gt;doi:10.1038/s41467-024-44900-4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Morra, J., Daley, M. (2022). &amp;ldquo;Imposing Connectome-Derived Topology on an Echo State Network.&amp;rdquo; &lt;a class="link" href="https://arxiv.org/abs/2201.09359" target="_blank" rel="noopener"
&gt;arXiv:2201.09359&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Costi, L., Hadjiivanov, A., Dold, D., Hale, Z.F., Izzo, D. (2025). &amp;ldquo;The Drosophila Connectome as a Computational Reservoir for Time-Series Prediction.&amp;rdquo; Biomimetics. &lt;a class="link" href="https://pmc.ncbi.nlm.nih.gov/articles/PMC12109256/" target="_blank" rel="noopener"
&gt;PMC12109256&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Accessing the topological properties of human brain functional sub-circuits in Echo State Networks.&amp;rdquo; &lt;a class="link" href="https://arxiv.org/abs/2412.14999" target="_blank" rel="noopener"
&gt;arXiv:2412.14999&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Using Connectome Features to Constrain Echo State Networks.&amp;rdquo; &lt;a class="link" href="https://arxiv.org/abs/2206.02094" target="_blank" rel="noopener"
&gt;arXiv:2206.02094&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Winding, M. et al. (2023). &amp;ldquo;The connectome of an insect brain.&amp;rdquo; Science, 379(6636), eadd9330.&lt;/li&gt;
&lt;li&gt;Wang-Chen, S. et al. (2024). &amp;ldquo;NeuroMechFly v2: simulating embodied sensorimotor control in adult Drosophila.&amp;rdquo; Nature Methods. &lt;a class="link" href="https://www.nature.com/articles/s41592-024-02497-y" target="_blank" rel="noopener"
&gt;doi:10.1038/s41592-024-02497-y&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.ipa.go.jp/jinzai/mitou/koubo/topics/reservoircomputing-explanation.html" target="_blank" rel="noopener"
&gt;Reservoir Computing in 5 minutes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>論理ゲート型ニューラルネットワークで、MNISTを解いてみた</title><link>https://www.m1ke.org/p/%E8%AB%96%E7%90%86%E3%82%B2%E3%83%BC%E3%83%88%E5%9E%8B%E3%83%8B%E3%83%A5%E3%83%BC%E3%83%A9%E3%83%AB%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%A7mnist%E3%82%92%E8%A7%A3%E3%81%84%E3%81%A6%E3%81%BF%E3%81%9F/</link><pubDate>Tue, 08 Sep 2026 12:00:00 +0900</pubDate><guid>https://www.m1ke.org/p/%E8%AB%96%E7%90%86%E3%82%B2%E3%83%BC%E3%83%88%E5%9E%8B%E3%83%8B%E3%83%A5%E3%83%BC%E3%83%A9%E3%83%AB%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%A7mnist%E3%82%92%E8%A7%A3%E3%81%84%E3%81%A6%E3%81%BF%E3%81%9F/</guid><description>&lt;img src="https://www.m1ke.org/p/%E8%AB%96%E7%90%86%E3%82%B2%E3%83%BC%E3%83%88%E5%9E%8B%E3%83%8B%E3%83%A5%E3%83%BC%E3%83%A9%E3%83%AB%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%A7mnist%E3%82%92%E8%A7%A3%E3%81%84%E3%81%A6%E3%81%BF%E3%81%9F/panda.webp" alt="Featured image of post 論理ゲート型ニューラルネットワークで、MNISTを解いてみた" /&gt;&lt;h2 id="背景"&gt;背景&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Xで論理ゲート型ニューラルネットワークがタイムラインに流れてきた&lt;/li&gt;
&lt;li&gt;気になったので、AIに調べてもらってMNISTで試してみた&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="仕組み"&gt;仕組み&lt;/h2&gt;
&lt;h3 id="論理ゲート型ニューラルネットワークdifferentiable-logic-gate-networksとは"&gt;論理ゲート型ニューラルネットワーク（Differentiable Logic Gate Networks）とは&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;通常のニューラルネットは、重み付き和と活性化関数の組み合わせでニューロンを構成する&lt;/li&gt;
&lt;li&gt;一方、論理ゲート型ニューラルネットワークは、AND・XORといった実際の論理ゲートそのものをニューロンとして使う設計&lt;/li&gt;
&lt;li&gt;推論時には本物のブール回路として動作するため、浮動小数点演算が不要になり、圧倒的に高速・省電力な推論が可能になるというのが最大の魅力&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="通常のニューロンとの違い"&gt;通常のニューロンとの違い&lt;/h3&gt;
&lt;p&gt;違い:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;通常のニューロン:
&lt;ul&gt;
&lt;li&gt;入力$x$に対して$y=f(w\cdot x+b)$（重み付き和＋活性化関数）を計算する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;論理ゲート型のニューロン:
&lt;ul&gt;
&lt;li&gt;2つの入力$a,b$（0か1の値）に対して、AND・OR・XORなどの論理ゲートをそのまま適用する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;つまり、学習によって最適化される対象が「重み$w$の値」ではなく「どの論理ゲートを使うか」に変わる。&lt;/p&gt;
&lt;h3 id="16種類の2入力論理ゲート"&gt;16種類の2入力論理ゲート&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;2値の入力$a,b$の組み合わせは$(0,0),(0,1),(1,0),(1,1)$の4通りある&lt;/li&gt;
&lt;li&gt;それぞれに0か1を割り当てる関数は$2^4=16$通り存在する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;全16種類論理ゲート:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AND・OR・XOR・NAND・NOR・XNOR&lt;/li&gt;
&lt;li&gt;TRUE（常に1）・FALSE（常に0）&lt;/li&gt;
&lt;li&gt;$A$・$B$&lt;/li&gt;
&lt;li&gt;$\lnot A$・$\lnot B$&lt;/li&gt;
&lt;li&gt;さらに4つの非対称なゲート（$A \land \lnot B$等）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="微分可能な緩和"&gt;微分可能な緩和&lt;/h3&gt;
&lt;p&gt;離散的な論理ゲートはそのままでは微分できず、勾配降下法で学習できない。そこで、実数値$[0,1]$上のファジー論理（t-norm/t-conorm）を使って各ゲートを連続的に緩和する。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\mathrm{AND}(a,b) = ab$&lt;/li&gt;
&lt;li&gt;$\mathrm{OR}(a,b) = a+b-ab$&lt;/li&gt;
&lt;li&gt;$\mathrm{XOR}(a,b) = a+b-2ab$&lt;/li&gt;
&lt;li&gt;$\mathrm{NAND}(a,b) = 1-ab$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;といった形で、16種類全てのゲートに実数値の緩和版を用意する。各ニューロンは、この16種類のゲートに対する学習可能な重みベクトル$w\in\mathbb{R}^{16}$を持ち、ソフトマックスで確率分布$p=\mathrm{softmax}(w)$に変換する。ニューロンの出力は、16個の緩和ゲート出力$f_i(a,b)$の確率加重和として計算される。&lt;/p&gt;
$$
y = \sum_{i=1}^{16} p_i \, f_i(a,b)
$$&lt;p&gt;これにより、ゲートの選択そのものが確率分布として微分可能になり、通常の誤差逆伝播で学習できるようになる。&lt;/p&gt;
&lt;h3 id="学習と離散化"&gt;学習と離散化&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;まず、このソフトな（確率的な）ネットワークを通常の勾配降下法で学習する&lt;/li&gt;
&lt;li&gt;学習後、各ニューロンは最も確率の高いゲート（$\arg\max_i p_i$）に離散化され、接続も固定される&lt;/li&gt;
&lt;li&gt;結果として、実際に動作するブール回路（本物のAND・XOR等の組み合わせ）が得られる&lt;/li&gt;
&lt;li&gt;元の提案論文では、ソフトな状態での精度と、離散化後の精度の差は0.1%未満に収まると報告されている&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ネットワーク構造"&gt;ネットワーク構造&lt;/h3&gt;
&lt;p&gt;論理ゲート型ネットワークは全結合ではなく、疎な結合を持つ。各ニューロンは前の層のちょうど2つのニューロン（または入力）にランダムに接続され、この配線は初期化時に決まり学習中は変化しない。学習によって最適化されるのは、あくまで各ニューロンのゲート選択の重みだけになる。&lt;/p&gt;
&lt;h2 id="研究の系譜"&gt;研究の系譜&lt;/h2&gt;
&lt;h3 id="deep-differentiable-logic-gate-networksneurips-2022"&gt;Deep Differentiable Logic Gate Networks（NeurIPS 2022）&lt;/h3&gt;
&lt;p&gt;この設計を提案した最初の論文が、Felix Petersen, Christian Borgelt, Hilde Kuehne, Oliver Deussenによる&lt;code&gt;Deep Differentiable Logic Gate Networks&lt;/code&gt;（&lt;a class="link" href="https://arxiv.org/abs/2210.08277" target="_blank" rel="noopener"
&gt;arXiv:2210.08277&lt;/a&gt;）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MNISTにおいて、単一のCPUコア上で1秒間に100万枚以上の画像を処理できる推論速度を報告している&lt;/li&gt;
&lt;li&gt;UCIのAdultやBreast Cancerのような表形式データでも、ロジスティック回帰や小型ニューラルネットに匹敵する精度を、ナノ秒オーダーの推論時間で達成している&lt;/li&gt;
&lt;li&gt;一方、CIFAR-10については、この時点では畳み込み構造を持たない小規模なネットワークしか試されておらず、精度はCNNに遠く及ばない水準に留まっていた&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="convolutional-differentiable-logic-gate-networksneurips-2024-oral"&gt;Convolutional Differentiable Logic Gate Networks（NeurIPS 2024, Oral）&lt;/h3&gt;
&lt;p&gt;続く論文&lt;code&gt;Convolutional Differentiable Logic Gate Networks&lt;/code&gt;（Petersen, Kuehne, Borgelt, Welzel, Ermon、&lt;a class="link" href="https://arxiv.org/abs/2411.04732" target="_blank" rel="noopener"
&gt;arXiv:2411.04732&lt;/a&gt;）では、論理ゲート型ネットワークに畳み込み構造を導入している。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;論理ゲートを木構造に組み合わせた畳み込みカーネル&lt;/li&gt;
&lt;li&gt;通常のmaxプーリングに相当する、微分可能な緩和版の論理ORプーリング&lt;/li&gt;
&lt;li&gt;深い層でも学習が安定するような、恒等写像に近い初期化&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらにより、CIFAR-10において&lt;strong&gt;86.29%の精度を、わずか6,100万個の論理ゲートで達成&lt;/strong&gt;したと報告されている。これは、同等の精度を持つXNOR-Net（2値化ニューラルネットの代表的手法）と比べて、&lt;strong&gt;29倍小さい&lt;/strong&gt;構成だとしている。&lt;/p&gt;
&lt;h3 id="実装"&gt;実装&lt;/h3&gt;
&lt;p&gt;Petersen自身が公開しているPyTorchベースのライブラリ&lt;code&gt;difflogic&lt;/code&gt;（&lt;a class="link" href="https://github.com/Felix-Petersen/difflogic" target="_blank" rel="noopener"
&gt;GitHub&lt;/a&gt;、MITライセンス）が、上記の手法の公式実装として利用できる。&lt;/p&gt;
&lt;h3 id="限界課題"&gt;限界・課題&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;緩和されたブール演算を何層も重ねると、勾配が消失しやすくなる&lt;/li&gt;
&lt;li&gt;ソフトマックスの温度に敏感で、低すぎると数値が不安定になり、高すぎると勾配の信号が弱くなる&lt;/li&gt;
&lt;li&gt;ソフトな学習時と、離散化した推論時との間のギャップ（discretization gap）が、設定によっては完全には解消しない場合がある&lt;/li&gt;
&lt;li&gt;各ニューロンで16種類のゲート関数を毎回評価する必要があるため、通常のネットワークより学習コスト自体は高くなりやすい&lt;/li&gt;
&lt;li&gt;単純に層を深くするだけでは精度が向上しないという「深さのスケーラビリティ」の問題が、2025〜2026年の後続研究でも指摘されており、まだ解決していない課題として残っている&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="実際にmnistで論理ゲートcnnを作ってみた"&gt;実際にMNISTで論理ゲートCNNを作ってみた&lt;/h2&gt;
&lt;p&gt;理論の紹介だけで終わらせず、実際に手元で学習させて、回路にまで変換してみた。&lt;/p&gt;
&lt;h3 id="前提知識"&gt;前提知識&lt;/h3&gt;
&lt;h4 id="fpgaとは"&gt;FPGAとは&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Field-Programmable Gate Arrayの略で、製造後に内部の論理回路を何度でも書き換えられる集積回路&lt;/li&gt;
&lt;li&gt;基本単位はLUT（後述）で、これを大量に組み合わせて任意の論理回路を実現する&lt;/li&gt;
&lt;li&gt;配線を固定して製造するASIC（特定用途向け集積回路）と違い、量産前の検証や、少量生産、頻繁な設計変更が必要な用途に向く&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="lutlook-up-tableとは"&gt;LUT（Look-Up Table）とは&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;FPGAの中で実際に論理演算を行う、最小単位の回路&lt;/li&gt;
&lt;li&gt;入力の組み合わせパターンに対して、あらかじめ設定しておいた出力を返す、小さなメモリのようなもの&lt;/li&gt;
&lt;li&gt;一般的なFPGAでは4入力LUTが基本単位で、これを大量に組み合わせることで複雑な回路を実現する&lt;/li&gt;
&lt;li&gt;FPGAの規模は、このLUTを何個持っているかでおおまかに表される（例: 数千LUT程度の小型FPGAから、数十万LUT級の大型FPGAまで）&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="risc-vとは"&gt;RISC-Vとは&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;カリフォルニア大学バークレー校で開発された、オープンでロイヤリティフリーの命令セットアーキテクチャ（ISA）&lt;/li&gt;
&lt;li&gt;ARMやx86と違い、誰でも自由に実装・改変・製造できる&lt;/li&gt;
&lt;li&gt;PicoRV32のような、FPGA上にLUTの組み合わせとして実装できる、軽量な「ソフトコア」実装も複数公開されている&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="verilogとは"&gt;Verilogとは&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;デジタル回路の構造や動作を記述するための、ハードウェア記述言語（HDL）の一つ&lt;/li&gt;
&lt;li&gt;記述したVerilogコードは、Yosysのような論理合成ツールによって、FPGAやASIC向けの実際の回路（ゲートの接続情報）に変換される&lt;/li&gt;
&lt;li&gt;論理ゲート型ニューラルネットワークは、学習後にそのまま本物の論理回路になるため、このVerilogへの変換と相性が良い&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="使ったライブラリ"&gt;使ったライブラリ&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;論文の公式実装&lt;code&gt;difflogic&lt;/code&gt;には、実はConvolutional版（2024年論文）のコードは含まれていない&lt;/li&gt;
&lt;li&gt;代わりに、&lt;code&gt;difflogic&lt;/code&gt;を拡張した&lt;code&gt;torchlogix&lt;/code&gt;（&lt;a class="link" href="https://github.com/ligerlac/torchlogix" target="_blank" rel="noopener"
&gt;ligerlac/torchlogix&lt;/a&gt;、MITライセンス）を使用。&lt;code&gt;LogicConv2d&lt;/code&gt;・&lt;code&gt;OrPooling2d&lt;/code&gt;・&lt;code&gt;LogicDense&lt;/code&gt;・&lt;code&gt;GroupSum&lt;/code&gt;といった、畳み込み版に必要な部品が揃っている&lt;/li&gt;
&lt;li&gt;学習済みモデルを、そのまま&lt;code&gt;C&lt;/code&gt;や&lt;code&gt;Verilog&lt;/code&gt;のコードにコンパイルできる&lt;code&gt;Circuit&lt;/code&gt;という仕組みも内蔵している&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="実験結果"&gt;実験結果&lt;/h3&gt;
&lt;p&gt;3種類の構成でMNISTを学習させ、離散化した状態（discrete、実際の回路と同じ精度）での結果を比較した。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;構成&lt;/th&gt;
&lt;th style="text-align: right"&gt;クラス数&lt;/th&gt;
&lt;th style="text-align: right"&gt;イテレーション数&lt;/th&gt;
&lt;th style="text-align: right"&gt;ゲート数（simplify後）&lt;/th&gt;
&lt;th style="text-align: right"&gt;精度（discrete）&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;カーネル4・隠れ層100&lt;/td&gt;
&lt;td style="text-align: right"&gt;2（0 vs 1）&lt;/td&gt;
&lt;td style="text-align: right"&gt;600&lt;/td&gt;
&lt;td style="text-align: right"&gt;973&lt;/td&gt;
&lt;td style="text-align: right"&gt;99.27%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;カーネル8・隠れ層400&lt;/td&gt;
&lt;td style="text-align: right"&gt;10（0〜9）&lt;/td&gt;
&lt;td style="text-align: right"&gt;3,000&lt;/td&gt;
&lt;td style="text-align: right"&gt;2,961&lt;/td&gt;
&lt;td style="text-align: right"&gt;66.9%（頭打ち）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;カーネル16・隠れ層4,000×2&lt;/td&gt;
&lt;td style="text-align: right"&gt;10（0〜9）&lt;/td&gt;
&lt;td style="text-align: right"&gt;30,000&lt;/td&gt;
&lt;td style="text-align: right"&gt;12,207&lt;/td&gt;
&lt;td style="text-align: right"&gt;94.85%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;2クラスの最小構成は、973ゲートという小さい回路で99.27%まで到達できた&lt;/li&gt;
&lt;li&gt;同じ発想のまま10クラスに拡張すると、隠れ層400ゲートでは66.9%で頭打ちになった。原因は最終層の「投票権」不足で、400ゲートを10クラスで分け合うと1クラスあたり平均40ゲート程度しか使えない&lt;/li&gt;
&lt;li&gt;論文のデフォルトに近い規模（カーネル16枚・隠れ層4,000ゲート×2層）まで増やすと94.85%まで伸びた（論文の元の学習では、学習率スケジュールを使ったさらに長時間の学習で精度を詰めている）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;つまり、少ないゲート数で済ませようとすると、クラス数が増えるほど精度が頭打ちになりやすい。&lt;/p&gt;
&lt;h3 id="verilogへの変換とfpgaとの相性"&gt;Verilogへの変換とFPGAとの相性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;torchlogix&lt;/code&gt;の&lt;code&gt;Circuit&lt;/code&gt;は、学習済みモデルをそのまま&lt;code&gt;get_verilog_code()&lt;/code&gt;で実際のVerilogコードに変換できる&lt;/li&gt;
&lt;li&gt;0 vs 1モデルの973ゲートという規模は、Lattice iCE40 UltraPlus（2,800〜5,280 LUT）のような小型FPGAに、RISC-Vソフトコア（PicoRV32など）と同居させられる可能性がある規模&lt;/li&gt;
&lt;li&gt;一方、10クラスモデルの12,207ゲートは、この小型FPGAには収まらない規模になる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="考察"&gt;考察&lt;/h2&gt;
&lt;h3 id="パラメータ数と効率の関係"&gt;パラメータ数と効率の関係&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;同じ精度を出すのに必要なゲート数は、通常のニューラルネットの重みの数より多くなりやすい&lt;/li&gt;
&lt;li&gt;一見非効率に思えるが、1つの論理ゲートは2入力・16種類のどれかを選ぶだけの最小単位の回路である一方、通常のニューラルネットの1つの重みは、実際にハードウェア化すると乗算器・加算器を必要とする、桁違いに高コストな回路になる&lt;/li&gt;
&lt;li&gt;CIFAR-10の86.29%・6,100万ゲートという構成が、同等精度のXNOR-Net（2値化ニューラルネット）より29倍小さいという結果は、この「1ユニットあたりのコストの差」が「ユニット数の差」を上回ることを示している&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="大規模モデルへの適用の限界"&gt;大規模モデルへの適用の限界&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;数十億パラメータ級の大規模言語モデルをこの手法で論理ゲート化できないか、という話も出たが、現実的ではないという結論になった&lt;/li&gt;
&lt;li&gt;理由は規模だけでなく、Attention（可変長系列に対するsoftmaxでの重み付け）やLayerNormのような、固定サイズの2入力論理ゲートでは表現しづらい演算が中心にあるため&lt;/li&gt;
&lt;li&gt;今のところこの手法が実証されているのは、畳み込み＋全結合で表現できる、固定サイズの分類問題に限られる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="まとめ"&gt;まとめ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;論理ゲート型ニューラルネットワークは、重み付き和ではなく実際の論理ゲートをニューロンとして使う設計&lt;/li&gt;
&lt;li&gt;学習時は16種類のゲートを確率的に混合する微分可能な緩和を使い、学習後は最も確率の高いゲートに離散化して本物のブール回路にする&lt;/li&gt;
&lt;li&gt;推論時は浮動小数点演算が不要になるため、MNISTでは単一CPUコアで毎秒100万枚以上という圧倒的な速度を達成している&lt;/li&gt;
&lt;li&gt;畳み込み構造を導入したConvolutional版では、CIFAR-10でも86.29%という実用的な精度に、XNOR-Net比29倍小さい構成で到達している&lt;/li&gt;
&lt;li&gt;実際に&lt;code&gt;torchlogix&lt;/code&gt;でMNISTの2クラス識別を試したところ、973ゲートで99.27%を達成できた一方、10クラス全部では小さい構成だと精度が頭打ちになり、クラス数とゲート数のトレードオフを実感した&lt;/li&gt;
&lt;li&gt;一方で、深さのスケーラビリティや学習の不安定性、Attentionのような演算への非対応など、まだ発展途上の課題も残っている&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Petersen, F., Borgelt, C., Kuehne, H., Deussen, O. (2022). &amp;ldquo;Deep Differentiable Logic Gate Networks.&amp;rdquo; NeurIPS 2022. &lt;a class="link" href="https://arxiv.org/abs/2210.08277" target="_blank" rel="noopener"
&gt;arXiv:2210.08277&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Petersen, F., Kuehne, H., Borgelt, C., Welzel, J., Ermon, S. (2024). &amp;ldquo;Convolutional Differentiable Logic Gate Networks.&amp;rdquo; NeurIPS 2024 (Oral). &lt;a class="link" href="https://arxiv.org/abs/2411.04732" target="_blank" rel="noopener"
&gt;arXiv:2411.04732&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/Felix-Petersen/difflogic" target="_blank" rel="noopener"
&gt;difflogic - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/pdf/2506.07500" target="_blank" rel="noopener"
&gt;&amp;ldquo;Mind the Gap: Removing the Discretization Gap in Differentiable Logic Gate Networks&amp;rdquo;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/abs/2607.21633" target="_blank" rel="noopener"
&gt;&amp;ldquo;On the Depth Scalability of Logic Gate Networks&amp;rdquo;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/ligerlac/torchlogix" target="_blank" rel="noopener"
&gt;torchlogix - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Mean PoolingとAttention Poolingなどについて</title><link>https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/</link><pubDate>Sat, 08 Aug 2026 21:53:32 +0900</pubDate><guid>https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/</guid><description>&lt;img src="https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/attention.png" alt="Featured image of post Mean PoolingとAttention Poolingなどについて" /&gt;&lt;h2 id="背景"&gt;背景&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;これまで特徴量をぼかすにはMean Poolingを使っていた&lt;/li&gt;
&lt;li&gt;しかし、今回のモデルの精度向上のため、meanプールからattention poolingへ変更した&lt;/li&gt;
&lt;li&gt;それは、特徴量ごとの重要度を学習しながら集約する事が必要だったから&lt;/li&gt;
&lt;li&gt;ちなみに、mean poolingからmulth-head attention poolingに変更したらかなり精度が向上した&lt;/li&gt;
&lt;li&gt;そのため、Attention Poolingを理解するためのAttention自体の整理を行った&lt;/li&gt;
&lt;li&gt;また、Multi-Head Attention系も必要だったのでそれの理解も載せる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="convとpool"&gt;ConvとPool&lt;/h2&gt;
&lt;h3 id="convとpoolの理解"&gt;ConvとPoolの理解&lt;/h3&gt;
&lt;p&gt;自分の理解だと前提として、普段よく使うConvとPoolは次の理解は以下になる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Conv
&lt;ul&gt;
&lt;li&gt;translation equivariant な性質&lt;/li&gt;
&lt;li&gt;入力を平行移動すると、特徴マップも対応して平行移動&lt;/li&gt;
&lt;li&gt;局所特徴を抽出する役割&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pool
&lt;ul&gt;
&lt;li&gt;特徴量を圧縮・集約する役割&lt;/li&gt;
&lt;li&gt;Max Poolingなどは一般に非可逆&lt;/li&gt;
&lt;li&gt;Global Poolingでは位置に対するinvarianceを得られる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mean-poolingの理解"&gt;Mean Poolingの理解&lt;/h3&gt;
&lt;p&gt;例えば、Mean Poolingでは、入力特徴量の平均による集約という役割。&lt;/p&gt;
$$
z = \frac{1}{N}\sum_{i=1}^{N}x_i
$$&lt;p&gt;WHere:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$x_i$ が各位置の特徴量&lt;/li&gt;
&lt;li&gt;$N$ が特徴量の個数&lt;/li&gt;
&lt;li&gt;$z$ が集約後の特徴量&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;つまり、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;すべての位置に同じ重み $\frac{1}{N}$&lt;/li&gt;
&lt;li&gt;学習されない重み&lt;/li&gt;
&lt;li&gt;特徴量の重要度を区別しない集約&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例：3個の特徴量を集約する場合&lt;/p&gt;
$$
z = \frac{x_1+x_2+x_3}{3}
$$&lt;ul&gt;
&lt;li&gt;$x_1$ が重要でも $x_3$ が重要でも同じ扱い&lt;/li&gt;
&lt;li&gt;「全部を平等に見る」という仮定となる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="attentionの仕組み"&gt;Attentionの仕組み&lt;/h2&gt;
&lt;h3 id="querykeyvalue"&gt;Query・Key・Value&lt;/h3&gt;
&lt;p&gt;Attentionの中心となるのは、Query、Key、Valueで、Q、K、V と表記されるベクトル。&lt;/p&gt;
&lt;p&gt;それぞれの意味:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Query
&lt;ul&gt;
&lt;li&gt;「何を探しているか」を表すベクトル&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Key
&lt;ul&gt;
&lt;li&gt;「検索対象がどのような特徴を持つか」を表すベクトル&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Value
&lt;ul&gt;
&lt;li&gt;実際に取得する情報を表すベクトル&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;QueryとKeyの比較による関連度の計算、そして、関連度を使ったValueの重み付き和。&lt;/p&gt;
&lt;h3 id="なぜqueryとkeyを分けるのか"&gt;なぜQueryとKeyを分けるのか&lt;/h3&gt;
&lt;p&gt;単純な特徴量同士の類似度だけではなく、「何を探すための表現か」と「検索されるための表現か」の分離をしたいから。&lt;/p&gt;
&lt;p&gt;また、同じ入力でも異なる役割を持たせるための線形変換となっている（これは検索も検索対象も同じXから作るのでself-attention）:&lt;/p&gt;
$$
Q = XW_Q
$$&lt;p&gt;
&lt;/p&gt;
$$
K = XW_K
$$&lt;p&gt;
&lt;/p&gt;
$$
V = XW_V
$$&lt;p&gt;それぞれ、以下を意味する。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$W_Q$によるQuery用の表現への変換&lt;/li&gt;
&lt;li&gt;$W_K$によるKey用の表現への変換&lt;/li&gt;
&lt;li&gt;$W_V$によるValue用の表現への変換&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;つまり、Attentionする情報も、$W_q, W_k, W_v$ですべて学習可能になっているということ。&lt;/p&gt;
&lt;h3 id="attentionの処理"&gt;Attentionの処理&lt;/h3&gt;
&lt;p&gt;Transformerなどで使われる代表的なAttentionの仕組み（Scaled Dot-Product Attention）。&lt;/p&gt;
$$
\mathrm{Attention}(Q,K,V) = \mathrm{softmax}
\left(
\frac{QK^\top}{\sqrt{d_k}}
\right)V
$$&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$QK^\top$
&lt;ul&gt;
&lt;li&gt;Queryと Keyの内積&lt;/li&gt;
&lt;li&gt;Queryと各Keyの相性の計算&lt;/li&gt;
&lt;li&gt;つまり、1つのQueryに注目した場合、&lt;code&gt;Query:Key = 1:N&lt;/code&gt;で計算を行う&lt;/li&gt;
&lt;li&gt;値が大きいほど高い関連度&lt;/li&gt;
&lt;li&gt;「このQueryに対して、どのKeyが関係しているか」というスコア&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;$\sqrt{d_k}$ による除算
&lt;ul&gt;
&lt;li&gt;Key の次元数を $d_k$ としたときのスケーリング&lt;/li&gt;
&lt;li&gt;次元数が大きくなることで内積の値が大きくなりやすい問題への対処&lt;/li&gt;
&lt;li&gt;Softmaxの出力が極端になることを抑えるための処理&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Softmax
&lt;ul&gt;
&lt;li&gt;スコアから Attention Weight への変換
$$
\alpha_i = \frac{\exp(s_i)}
{\sum_j\exp(s_j)}
$$&lt;/li&gt;
&lt;li&gt;$s_i$ が Query と各 Key の関連度&lt;/li&gt;
&lt;li&gt;$\alpha_i$ が変換後の Attention Weight&lt;/li&gt;
&lt;li&gt;重みの合計が1になる性質&lt;/li&gt;
&lt;li&gt;「どこをどれくらい見るか」を表す割合&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Valueとの積
&lt;ul&gt;
&lt;li&gt;Attention Weight を使った Value の重み付き和
$$
z = \sum_i\alpha_iV_i
$$&lt;/li&gt;
&lt;li&gt;関連度の高い Value を強く反映した出力&lt;/li&gt;
&lt;li&gt;Query に応じて変化する集約結果&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="self-attention"&gt;Self-Attention&lt;/h2&gt;
&lt;h3 id="self-attentionとは"&gt;Self-Attentionとは&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;最も一般的なAttentionがself-attetion&lt;/li&gt;
&lt;li&gt;これは&lt;code&gt;I have a pen&lt;/code&gt;みたいな文章のattentionに使われている&lt;/li&gt;
&lt;li&gt;例えば、&lt;code&gt;have&lt;/code&gt;と 4つ（&lt;code&gt;I&lt;/code&gt;, &lt;code&gt;have&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;pen&lt;/code&gt;）の関連性を取るため&lt;/li&gt;
&lt;li&gt;（ちなみに、この場合は、&lt;code&gt;have&lt;/code&gt;と&lt;code&gt;pen&lt;/code&gt;が高いattention weightになると思う）&lt;/li&gt;
&lt;/ul&gt;
$$
Q = XW_Q
$$&lt;p&gt;
&lt;/p&gt;
$$
K = XW_K
$$&lt;p&gt;
&lt;/p&gt;
$$
V = XW_V
$$&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$X$は元々の行列（&lt;code&gt;i have a pen&lt;/code&gt;なら、4つのベクトルを持つ行列）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="self-attentionの次元"&gt;Self Attentionの次元&lt;/h3&gt;
&lt;p&gt;入力が $N$ 個の特徴量の場合：
&lt;/p&gt;
$$
X \in \mathbb{R}^{N \times D}
$$&lt;p&gt;Self-Attention 後も基本的には $N$ 個の特徴量がある。
&lt;/p&gt;
$$
N \times D
\rightarrow
N \times D
$$&lt;h3 id="cnnととself-attentionの違い"&gt;CNNととself-attentionの違い&lt;/h3&gt;
&lt;p&gt;特徴を取るのに一般的に使われるのはCNN系のカーネル。&lt;/p&gt;
&lt;p&gt;そのCNN系とself-Attentionの違いは以下:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CNN
&lt;ul&gt;
&lt;li&gt;近傍を重視する構造&lt;/li&gt;
&lt;li&gt;その近傍のサイズはKernel sizeによって決まる&lt;/li&gt;
&lt;li&gt;また、inductive biasが強み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Attention
&lt;ul&gt;
&lt;li&gt;Attentionは「どこと関係が強いか」を重視する構造&lt;/li&gt;
&lt;li&gt;Attention機構によって重要視する所も学習が可能&lt;/li&gt;
&lt;li&gt;つまり、関係性をデータから学習する柔軟性が強み&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="cnnのinductive-bias"&gt;CNNのInductive bias&lt;/h3&gt;
&lt;p&gt;画像なので、以下の前提が、CNNアーキにはあるということ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;近くの画素同士は関係が強いはず、という局所性&lt;/li&gt;
&lt;li&gt;同じ特徴検出器を画像全体で使い回すというweight sharing&lt;/li&gt;
&lt;li&gt;位置がずれても同じ特徴を検出できるというtranslation equivariance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これは全体をくまなく見るAttentionとは違うbiasがかかっている。&lt;/p&gt;
&lt;h2 id="multi-head-attention"&gt;Multi-Head Attention&lt;/h2&gt;
&lt;h3 id="multi-head-attentionとは"&gt;Multi-Head Attentionとは&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Attention を1回だけではなく複数並列に実行する仕組み&lt;/li&gt;
&lt;li&gt;わかりやすく言えば、QKVの重みがn個あるということ&lt;/li&gt;
&lt;li&gt;それだけ別々の特徴を取れるということ&lt;/li&gt;
&lt;/ul&gt;
$$
\mathrm{head}_i = \mathrm{Attention}
(
QW_i^Q,
KW_i^K,
VW_i^V
)
$$&lt;p&gt;特徴:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Head ごとに異なる変換&lt;/li&gt;
&lt;li&gt;Head ごとに異なる Attention&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;各 Head の出力を結合する処理は以下となる。&lt;/p&gt;
$$
\mathrm{MultiHead}(Q,K,V) = \mathrm{Concat}
(
\mathrm{head}_1,
\dots,
\mathrm{head}_h
)W^O
$$&lt;p&gt;つまり、1つのAttentionだけに限定しない関係性の捉え方。&lt;/p&gt;
&lt;h3 id="multi-head-attentionのイメージ"&gt;multi-head attentionのイメージ&lt;/h3&gt;
&lt;p&gt;例えば画像の場合だと、以下を別々に学習するようなイメージ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;形状に反応&lt;/li&gt;
&lt;li&gt;テクスチャに反応&lt;/li&gt;
&lt;li&gt;特定領域に反応&lt;/li&gt;
&lt;li&gt;離れた領域同士の関係に反応&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;人がHeadごとに役割を定義するわけではなく、複数の表現空間から同じ入力を見る仕組み。&lt;/p&gt;
&lt;h2 id="attention-pooling"&gt;Attention Pooling&lt;/h2&gt;
&lt;h3 id="query-attention-pooling"&gt;Query Attention Pooling&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Attention Poolingのよく使われる実装方法の一つがQuery attention pooling&lt;/li&gt;
&lt;li&gt;これはPooling用のQueryを用意する方法&lt;/li&gt;
&lt;li&gt;ただし、Self Attentionとは違い、入力XからQueryは作らない&lt;/li&gt;
&lt;li&gt;そして、ある1個のQueryから複数の特徴量を参照する構造&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;入力特徴量:&lt;/p&gt;
$$
X = [x_1,x_2,\dots,x_N]
$$&lt;p&gt;Pooling用Query（Xから作っていないのがミソ）:&lt;/p&gt;
$$
Q = q_{pool} W_p
$$&lt;p&gt;入力からself-attentionと同じようにKeyとValueを生成する:&lt;/p&gt;
$$
K = XW_K
$$&lt;p&gt;
&lt;/p&gt;
$$
V = XW_V
$$&lt;p&gt;QueryとKeyの関連度を計算する:&lt;/p&gt;
$$
s = \frac{QK^\top}{\sqrt{d_k}}
$$&lt;p&gt;Attention Weightを算出する:&lt;/p&gt;
$$
\alpha = \mathrm{softmax}(s)
$$&lt;p&gt;self=attentionのように、Valueの重み付き和を出す:&lt;/p&gt;
$$
z = \alpha V
$$&lt;p&gt;最終的に1個のベクトルを得るというpooling構造:&lt;/p&gt;
$$
N \times D
\rightarrow
1 \times D
$$&lt;h3 id="query-attention-poolの特徴"&gt;Query Attention Poolの特徴&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;大きな違いは、qがxから生成されないということ&lt;/li&gt;
&lt;li&gt;そして、次元が1次元かに圧縮されるということ&lt;/li&gt;
&lt;li&gt;これはflatten（$N \times D$）ではなく、圧縮（$1 \times D$）となっている&lt;/li&gt;
&lt;li&gt;（ゆえにPoolingということ）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="self-attentionとquery-attention-poolのqueryの違い"&gt;Self AttentionとQuery Attention PoolのQueryの違い&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Self-AttentionとQuery Attention Poolingの違いとしては、Queryの数&lt;/li&gt;
&lt;li&gt;Self-Attentionでは各入力位置に対応する複数のQuery
&lt;ul&gt;
&lt;li&gt;例えば、&lt;code&gt;I have a pen&lt;/code&gt;なら、4つのqueryができるはず&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;他方、Query Attention Poolingでは1個の学習可能なQueryを使う構成&lt;/li&gt;
&lt;li&gt;つまり、Pooling用Query自体をモデルのパラメータとして学習する方法&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;学習可能なQueryの直感的な意味:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;「このタスクを解くために、入力からどのような情報を集めたいか」を表すベクトル&lt;/li&gt;
&lt;li&gt;学習によって更新される検索条件&lt;/li&gt;
&lt;li&gt;入力ごとに異なるKeyと比較される共通のQuery&lt;/li&gt;
&lt;li&gt;Query自体は同じでも入力ごとに変わるAttention Weight&lt;/li&gt;
&lt;li&gt;Keyが入力から生成されることによる動的なPooling&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="multi-head-attention-pooling"&gt;Multi-Head Attention Pooling&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Attention PoolingをMulti-Head化したもの&lt;/li&gt;
&lt;li&gt;複数の観点から特徴量を集約する仕組み&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ヘッドの数による違い:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1つの Head
&lt;ul&gt;
&lt;li&gt;1つの表現空間でのQueryとKeyの比較&lt;/li&gt;
&lt;li&gt;1種類のAttention Weight&lt;/li&gt;
&lt;li&gt;1つの観点からの特徴集約&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;複数の Head
&lt;ul&gt;
&lt;li&gt;複数の表現空間での比較&lt;/li&gt;
&lt;li&gt;Head ごとに異なる Attention Weight&lt;/li&gt;
&lt;li&gt;複数の観点から得られる集約結果&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Multi-healの意味:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;各Head の出力を結合した最終表現&lt;/li&gt;
&lt;li&gt;単一の重要度だけでは表現しにくい情報への対応&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mean-pooling-とのイメージ上の違い"&gt;Mean Pooling とのイメージ上の違い&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Mean Pooling：全員の意見を同じ重さで平均&lt;/li&gt;
&lt;li&gt;Attention Pooling：必要そうな人の意見を強く反映&lt;/li&gt;
&lt;li&gt;Multi-Head Attention Pooling：複数の観点から重要な意見を集めて最後に統合&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="attentionの意味"&gt;Attentionの意味&lt;/h2&gt;
&lt;h3 id="attention-poolingのコア"&gt;Attention Poolingのコア&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Attention Poolingのコアは「どこを見るか」という考え方&lt;/li&gt;
&lt;li&gt;つまり、入力を均等に扱うのではなく、重要な部分に大きな重みを与える仕組み&lt;/li&gt;
&lt;li&gt;Mean Pooling における固定値 $1/N$ を、入力から計算した重みに置き換えるイメージ&lt;/li&gt;
&lt;/ul&gt;
$$
z = \sum_{i=1}^{N}\alpha_i x_i
$$&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\alpha_i$ が各特徴量に対する重みで、Attention Weight と呼ばれる値&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;多くの場合に満たす条件:
&lt;/p&gt;
$$
\sum_i \alpha_i = 1
$$&lt;p&gt;Mean PoolingとAttention Poolingの違い:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mean Pooling も一種の重み付き和&lt;/li&gt;
&lt;li&gt;Mean Pooling ではすべての $\alpha_i = 1/N$&lt;/li&gt;
&lt;li&gt;Attention Poolingでは入力に応じて変化する $\alpha_i$&lt;/li&gt;
&lt;li&gt;「何を見るべきか」をモデルが決める仕組み&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これがAttention Poolingのコア。&lt;/p&gt;
&lt;h3 id="mean-poolとattention-poolの違い"&gt;Mean PoolとAttention Poolの違い&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Mean Pooling
&lt;ul&gt;
&lt;li&gt;全部を均等に見る Pooling&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Attention Pooling
&lt;ul&gt;
&lt;li&gt;入力に応じて見る場所を変える Pooling&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="attentionで実際に学習されるもの"&gt;Attentionで実際に学習されるもの&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Softmax 自体には基本的に学習パラメータなし&lt;/li&gt;
&lt;li&gt;内積自体にも学習パラメータなし&lt;/li&gt;
&lt;li&gt;主な学習対象となる Q、K、V の射影&lt;/li&gt;
&lt;/ul&gt;
$$
W_Q, W_K, W_V
$$&lt;ul&gt;
&lt;li&gt;Multi-Head Attention における Head ごとに異なる射影&lt;/li&gt;
&lt;li&gt;Head を結合した後の出力変換&lt;/li&gt;
&lt;/ul&gt;
$$
W_O
$$&lt;ul&gt;
&lt;li&gt;Attention Pooling で学習可能なQueryを使う場合のQuery自体&lt;/li&gt;
&lt;li&gt;学習によって変化する関連度を測るための空間&lt;/li&gt;
&lt;li&gt;学習によって変化する「何を見るか」の基準&lt;/li&gt;
&lt;li&gt;Attention Weight 自体を直接パラメータとして保存する仕組みではない点&lt;/li&gt;
&lt;li&gt;入力と学習済みパラメータから毎回計算されるAttention Weight&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="lllama上のattentionの例"&gt;Lllama上のAttentionの例&lt;/h2&gt;
&lt;h3 id="attentionの仕組み-1"&gt;Attentionの仕組み&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/01.png"
width="2192"
height="938"
srcset="https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/01_hu_d71cde3430c261fb.png 480w, https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/01_hu_6b8f661ca9411fcd.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="233"
data-flex-basis="560px"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;まずは、KとQの内積を求める&lt;/li&gt;
&lt;li&gt;内積のスカラーは次元数が大きくなるほど大きな値を取りやすいため、$\sqrt{d_k}$ で除する&lt;/li&gt;
&lt;li&gt;scale調整ということ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/02.png"
width="2270"
height="1640"
srcset="https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/02_hu_614d2df5a41116b5.png 480w, https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/02_hu_ca4c9003032babd1.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="138"
data-flex-basis="332px"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;入力は&lt;code&gt;Thinking Machines&lt;/code&gt;で、それぞれembeddingして、$x_1$と$x_2$にしている&lt;/li&gt;
&lt;li&gt;$X=[x_1, x_2]^T$ということ&lt;/li&gt;
&lt;li&gt;それぞれ、QKVを計算する
&lt;ul&gt;
&lt;li&gt;$q_i = x_i W_q$&lt;/li&gt;
&lt;li&gt;$k_i = x_i W_k$&lt;/li&gt;
&lt;li&gt;$v_i = x_i W_v$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;その後、Attentionをかける
&lt;ul&gt;
&lt;li&gt;$q_1$ を、Thinking自身の $k_1$ だけでなく、Machinesの $k_2$ とも比較する&lt;/li&gt;
&lt;li&gt;（この例の場合は、thinkingの$q_1$を更新したい）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;つまり、次を計算している
&lt;ul&gt;
&lt;li&gt;$q_1 \cdot k_1$: Thinkingから見たThinkingとの関連度&lt;/li&gt;
&lt;li&gt;$q_1 \cdot k_2$: Thinkingから見たMachinesとの関連度&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;そして、softmaxをかけて、$[14, 12]$を確率と変換している&lt;/li&gt;
&lt;li&gt;つまりThinkingのQueryは以下となったということ
&lt;ul&gt;
&lt;li&gt;Thinking自身へのAttention → $0.88$&lt;/li&gt;
&lt;li&gt;MachineへのAttention → $0.12$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;これらの$a_i=[0.88, 0.12]$がthinkingのattention（αttention weightになる）&lt;/li&gt;
&lt;li&gt;Vは$v_i$として学習済みなので最終的に以下になる&lt;/li&gt;
&lt;li&gt;$z_i = a_i V$&lt;/li&gt;
&lt;li&gt;つまり，$z_1= 0.88 v_1 + 0.12 v_2$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;なお、attention weightの定義は以下となる。&lt;/p&gt;
$$
\Alpha = \mathrm{softmax}
\left(
\frac{QK^\top}{\sqrt{d_k}}
\right)
$$$$
\mathrm{Attention}(Q,K,V) = \Alpha V
$$&lt;p&gt;&lt;img src="https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/03.png"
width="2458"
height="1302"
srcset="https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/03_hu_5a294856ded4d301.png 480w, https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/03_hu_87688ab43e88e766.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="188"
data-flex-basis="453px"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;最後に、$Z_i$をconcatして、それを学習するためのoutput重み$W_o$で行列積をする&lt;/li&gt;
&lt;li&gt;結果$Z_o = Z W$を得る（Multi-Head Self-Attention outputの意味）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="attentionのパターン"&gt;Attentionのパターン&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/04.png"
width="2476"
height="870"
srcset="https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/04_hu_7c7f04bd953bff9f.png 480w, https://www.m1ke.org/p/mean-pooling%E3%81%A8attention-pooling%E3%81%AA%E3%81%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/04_hu_e38703fba322f669.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="284"
data-flex-basis="683px"
&gt;&lt;/p&gt;
&lt;p&gt;今回のはMHAだったが、他にもパターンがある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MHA
&lt;ul&gt;
&lt;li&gt;表現力を多く持たせやすい&lt;/li&gt;
&lt;li&gt;KV Cacheが大きい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;GQA
&lt;ul&gt;
&lt;li&gt;複数のQ HeadでK/Vを共有&lt;/li&gt;
&lt;li&gt;表現力と効率の中間&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MQA
&lt;ul&gt;
&lt;li&gt;全Q HeadでK/Vを共有&lt;/li&gt;
&lt;li&gt;KV Cacheを大きく削減&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="llamaの実際のコード"&gt;LLamaの実際のコード&lt;/h3&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/meta-llama/llama/blob/689c7f261b9c5514636ecc3c5fefefcbb3e6eed7/llama/model.py#L176" target="_blank" rel="noopener"
&gt;https://github.com/meta-llama/llama/blob/689c7f261b9c5514636ecc3c5fefefcbb3e6eed7/llama/model.py#L176&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;実際は、(batch_size, sequence_length, number_of_heads, head_dimension)$みたいな形で処理されている。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt; 10
&lt;/span&gt;&lt;span class="lnt"&gt; 11
&lt;/span&gt;&lt;span class="lnt"&gt; 12
&lt;/span&gt;&lt;span class="lnt"&gt; 13
&lt;/span&gt;&lt;span class="lnt"&gt; 14
&lt;/span&gt;&lt;span class="lnt"&gt; 15
&lt;/span&gt;&lt;span class="lnt"&gt; 16
&lt;/span&gt;&lt;span class="lnt"&gt; 17
&lt;/span&gt;&lt;span class="lnt"&gt; 18
&lt;/span&gt;&lt;span class="lnt"&gt; 19
&lt;/span&gt;&lt;span class="lnt"&gt; 20
&lt;/span&gt;&lt;span class="lnt"&gt; 21
&lt;/span&gt;&lt;span class="lnt"&gt; 22
&lt;/span&gt;&lt;span class="lnt"&gt; 23
&lt;/span&gt;&lt;span class="lnt"&gt; 24
&lt;/span&gt;&lt;span class="lnt"&gt; 25
&lt;/span&gt;&lt;span class="lnt"&gt; 26
&lt;/span&gt;&lt;span class="lnt"&gt; 27
&lt;/span&gt;&lt;span class="lnt"&gt; 28
&lt;/span&gt;&lt;span class="lnt"&gt; 29
&lt;/span&gt;&lt;span class="lnt"&gt; 30
&lt;/span&gt;&lt;span class="lnt"&gt; 31
&lt;/span&gt;&lt;span class="lnt"&gt; 32
&lt;/span&gt;&lt;span class="lnt"&gt; 33
&lt;/span&gt;&lt;span class="lnt"&gt; 34
&lt;/span&gt;&lt;span class="lnt"&gt; 35
&lt;/span&gt;&lt;span class="lnt"&gt; 36
&lt;/span&gt;&lt;span class="lnt"&gt; 37
&lt;/span&gt;&lt;span class="lnt"&gt; 38
&lt;/span&gt;&lt;span class="lnt"&gt; 39
&lt;/span&gt;&lt;span class="lnt"&gt; 40
&lt;/span&gt;&lt;span class="lnt"&gt; 41
&lt;/span&gt;&lt;span class="lnt"&gt; 42
&lt;/span&gt;&lt;span class="lnt"&gt; 43
&lt;/span&gt;&lt;span class="lnt"&gt; 44
&lt;/span&gt;&lt;span class="lnt"&gt; 45
&lt;/span&gt;&lt;span class="lnt"&gt; 46
&lt;/span&gt;&lt;span class="lnt"&gt; 47
&lt;/span&gt;&lt;span class="lnt"&gt; 48
&lt;/span&gt;&lt;span class="lnt"&gt; 49
&lt;/span&gt;&lt;span class="lnt"&gt; 50
&lt;/span&gt;&lt;span class="lnt"&gt; 51
&lt;/span&gt;&lt;span class="lnt"&gt; 52
&lt;/span&gt;&lt;span class="lnt"&gt; 53
&lt;/span&gt;&lt;span class="lnt"&gt; 54
&lt;/span&gt;&lt;span class="lnt"&gt; 55
&lt;/span&gt;&lt;span class="lnt"&gt; 56
&lt;/span&gt;&lt;span class="lnt"&gt; 57
&lt;/span&gt;&lt;span class="lnt"&gt; 58
&lt;/span&gt;&lt;span class="lnt"&gt; 59
&lt;/span&gt;&lt;span class="lnt"&gt; 60
&lt;/span&gt;&lt;span class="lnt"&gt; 61
&lt;/span&gt;&lt;span class="lnt"&gt; 62
&lt;/span&gt;&lt;span class="lnt"&gt; 63
&lt;/span&gt;&lt;span class="lnt"&gt; 64
&lt;/span&gt;&lt;span class="lnt"&gt; 65
&lt;/span&gt;&lt;span class="lnt"&gt; 66
&lt;/span&gt;&lt;span class="lnt"&gt; 67
&lt;/span&gt;&lt;span class="lnt"&gt; 68
&lt;/span&gt;&lt;span class="lnt"&gt; 69
&lt;/span&gt;&lt;span class="lnt"&gt; 70
&lt;/span&gt;&lt;span class="lnt"&gt; 71
&lt;/span&gt;&lt;span class="lnt"&gt; 72
&lt;/span&gt;&lt;span class="lnt"&gt; 73
&lt;/span&gt;&lt;span class="lnt"&gt; 74
&lt;/span&gt;&lt;span class="lnt"&gt; 75
&lt;/span&gt;&lt;span class="lnt"&gt; 76
&lt;/span&gt;&lt;span class="lnt"&gt; 77
&lt;/span&gt;&lt;span class="lnt"&gt; 78
&lt;/span&gt;&lt;span class="lnt"&gt; 79
&lt;/span&gt;&lt;span class="lnt"&gt; 80
&lt;/span&gt;&lt;span class="lnt"&gt; 81
&lt;/span&gt;&lt;span class="lnt"&gt; 82
&lt;/span&gt;&lt;span class="lnt"&gt; 83
&lt;/span&gt;&lt;span class="lnt"&gt; 84
&lt;/span&gt;&lt;span class="lnt"&gt; 85
&lt;/span&gt;&lt;span class="lnt"&gt; 86
&lt;/span&gt;&lt;span class="lnt"&gt; 87
&lt;/span&gt;&lt;span class="lnt"&gt; 88
&lt;/span&gt;&lt;span class="lnt"&gt; 89
&lt;/span&gt;&lt;span class="lnt"&gt; 90
&lt;/span&gt;&lt;span class="lnt"&gt; 91
&lt;/span&gt;&lt;span class="lnt"&gt; 92
&lt;/span&gt;&lt;span class="lnt"&gt; 93
&lt;/span&gt;&lt;span class="lnt"&gt; 94
&lt;/span&gt;&lt;span class="lnt"&gt; 95
&lt;/span&gt;&lt;span class="lnt"&gt; 96
&lt;/span&gt;&lt;span class="lnt"&gt; 97
&lt;/span&gt;&lt;span class="lnt"&gt; 98
&lt;/span&gt;&lt;span class="lnt"&gt; 99
&lt;/span&gt;&lt;span class="lnt"&gt;100
&lt;/span&gt;&lt;span class="lnt"&gt;101
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Attention&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ModelArgs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_kv_heads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_heads&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_kv_heads&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_kv_heads&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;model_parallel_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fs_init&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_model_parallel_world_size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_local_heads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_heads&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;model_parallel_size&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_local_kv_heads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_kv_heads&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;model_parallel_size&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_rep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_local_heads&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_local_kv_heads&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head_dim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_heads&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ColumnParallelLinear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_heads&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gather_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;init_method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ColumnParallelLinear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_kv_heads&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gather_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;init_method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ColumnParallelLinear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_kv_heads&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gather_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;init_method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RowParallelLinear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_heads&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;input_is_parallel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;init_method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_batch_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_local_kv_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cuda&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_batch_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_local_kv_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cuda&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;start_pos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;freqs_cis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bsz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seqlen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;xq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;xq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xq&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bsz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seqlen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_local_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;xk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bsz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seqlen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_local_kv_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;xv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bsz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seqlen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_local_kv_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;xq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apply_rotary_emb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;freqs_cis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;freqs_cis&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_k&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;bsz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_pos&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;start_pos&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;seqlen&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xk&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_v&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;bsz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_pos&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;start_pos&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;seqlen&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_k&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;bsz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;start_pos&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;seqlen&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache_v&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;bsz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;start_pos&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;seqlen&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# repeat k/v heads if n_kv_heads &amp;lt; n_heads&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repeat_kv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_rep&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# (bs, cache_len + seqlen, n_local_heads, head_dim)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repeat_kv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n_rep&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# (bs, cache_len + seqlen, n_local_heads, head_dim)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;xq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xq&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# (bs, n_local_heads, seqlen, head_dim)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# (bs, n_local_heads, cache_len + seqlen, head_dim)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# (bs, n_local_heads, cache_len + seqlen, head_dim)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;matmul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt; &lt;span class="c1"&gt;# (bs, n_local_heads, seqlen, cache_len + seqlen)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;type_as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;matmul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# (bs, n_local_heads, seqlen, head_dim)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contiguous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bsz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seqlen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="その他"&gt;その他&lt;/h2&gt;
&lt;h3 id="attentionの種類の違い"&gt;Attentionの種類の違い&lt;/h3&gt;
&lt;p&gt;Attention:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Self-Attention
&lt;ul&gt;
&lt;li&gt;QとKとVが同じ入力から作られる&lt;/li&gt;
&lt;li&gt;例えば、ある文章の中で単語の繋がりなどの関連性が大切などのとき&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cross-Attention
&lt;ul&gt;
&lt;li&gt;QueryとKey / Valueの出どころが異なるAttention&lt;/li&gt;
&lt;li&gt;$Q$は入力$X$、$K,V$は別の入力$Y$から作られる&lt;/li&gt;
&lt;li&gt;例えば文章から画像特徴を参照する場合など&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Attention Pooling
&lt;ul&gt;
&lt;li&gt;Attention を使って複数の特徴を集約する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="attentionとpoolingのサイズの違い"&gt;AttentionとPoolingのサイズの違い&lt;/h3&gt;
&lt;p&gt;Attention:
&lt;/p&gt;
$$
N \times D
\rightarrow
N \times D
$$&lt;ul&gt;
&lt;li&gt;複数の特徴量から複数の特徴量への変換&lt;/li&gt;
&lt;li&gt;特徴量同士の関係を使った各特徴量の更新&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pooling:
&lt;/p&gt;
$$
N \times D
\rightarrow
1 \times D
$$&lt;ul&gt;
&lt;li&gt;複数の特徴量から1個の特徴量への集約&lt;/li&gt;
&lt;li&gt;特徴量の個数を減らす処理&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="attentionの直感的な理解"&gt;Attentionの直感的な理解&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Attentionの本質としての検索&lt;/li&gt;
&lt;li&gt;Query
&lt;ul&gt;
&lt;li&gt;欲しい情報を表す検索条件&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Key
&lt;ul&gt;
&lt;li&gt;検索対象を表す見出し&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Query × Key
&lt;ul&gt;
&lt;li&gt;欲しい情報との一致度&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Softmax
&lt;ul&gt;
&lt;li&gt;一致度から参照割合への変換&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Value
&lt;ul&gt;
&lt;li&gt;実際に取得する中身&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Attention
&lt;ul&gt;
&lt;li&gt;Queryに合ったValueを集める処理&lt;/li&gt;
&lt;li&gt;QueryとKeyによる「どこを見るか」の決定&lt;/li&gt;
&lt;li&gt;Valueによる「何を取り出すか」の決定&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;そして、QKVは学習することによって形を変える&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="まとめ"&gt;まとめ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Mean PoolingからAttention Poolingへの変更は、「情報の集約方法を学習可能にする」ということ&lt;/li&gt;
&lt;li&gt;具体的な例がないとイメージはつきにくい&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://hasgeek.com/simrathanspal/the-llama3-guide/sub/decoding-llama3-part-5-grouped-query-attention-HcTT9kcU91JaaLi5YdYSpV" target="_blank" rel="noopener"
&gt;Decoding Llama3: Part 5 - Grouped Query Attention – Decoding Llama3: An explainer for tinkerers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/meta-llama/llama/tree/689c7f261b9c5514636ecc3c5fefefcbb3e6eed7" target="_blank" rel="noopener"
&gt;meta-llama/llama at 689c7f261b9c5514636ecc3c5fefefcbb3e6eed7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/abs/1706.03762" target="_blank" rel="noopener"
&gt;Attention Is All You Need&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/abs/1810.00825" target="_blank" rel="noopener"
&gt;Set Transformer: A Framework for Attention-based Permutation-Invariant Neural Networks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/abs/1911.02150" target="_blank" rel="noopener"
&gt;Fast Transformer Decoding: One Write-Head is All You Need&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/abs/2305.13245" target="_blank" rel="noopener"
&gt;GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/meta-llama/llama3/blob/main/llama/model.py" target="_blank" rel="noopener"
&gt;Meta Llama 3 - model.py&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>TransformerのPositional Encodingの解釈</title><link>https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/</link><pubDate>Thu, 30 Nov 2023 19:57:51 +0900</pubDate><guid>https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/</guid><description>&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/positional_encoding.png" alt="Featured image of post TransformerのPositional Encodingの解釈" /&gt;&lt;h2 id="概要"&gt;概要&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;TransformerはGPTやBERTにも使用されるNLPのモデルのアーキテクチャ&lt;/li&gt;
&lt;li&gt;TransformerはAttention / Self-Attention機構やスケーラビリティが特徴的&lt;/li&gt;
&lt;li&gt;ただ今回は、TokenのPositional Encodingについての解釈メモ&lt;/li&gt;
&lt;li&gt;ある程度Transformerの知識がある前提でPositional Encodingについて説明する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;NOTE:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;便宜上形式的に単語=tokenの同義としている&lt;/li&gt;
&lt;li&gt;サブワードなどの処理については説明は行わない&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="transformer"&gt;Transformer&lt;/h2&gt;
&lt;h3 id="そもそもtransformerとは"&gt;そもそもTransformerとは&lt;/h3&gt;
&lt;p&gt;ざっくり言うと次となる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2017年にGoogleの研究者によって紹介されたアーキテクチャ&lt;/li&gt;
&lt;li&gt;Transformerは、NLPの分野で使用される&lt;/li&gt;
&lt;li&gt;多くのNLPタスクで卓越した性能を示す&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="positional-encodingの場所"&gt;Positional Encodingの場所&lt;/h3&gt;
&lt;p&gt;先にTransformerの全体図とPositional Encodingの場所を示す。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-2.png"
width="1500"
height="925"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-2_hu_76b68a715785dbd.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-2_hu_df869e5551891272.png 1024w"
loading="lazy"
alt="Transformerの図（赤枠がPositional Encoding）"
class="gallery-image"
data-flex-grow="162"
data-flex-basis="389px"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;全体でみると、Positional Encodingは、Attention機構（図中のMulti-Head Attention）の前に、Inputを加工するために行われる&lt;/li&gt;
&lt;li&gt;図中の太陽十字はelement wise sumを意味し、tokenのembeddingのベクトルとPositional Encodingのベクトルを加算することを意味する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="そもそもpositional-encodingとは何か"&gt;そもそもPositional Encodingとは何か&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;下図にPositional Encodingとtokenの関係を示す&lt;/li&gt;
&lt;li&gt;文字（token）はi am a robotだが、そのtoken毎にpositional encodingとしてベクトルがある&lt;/li&gt;
&lt;li&gt;このベクトルがPositional Encoding&lt;/li&gt;
&lt;li&gt;なお、図中の$d$はtokenの埋め込みの次元数を意味している&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-1.png"
width="1634"
height="870"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-1_hu_254e3767b3df64d5.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-1_hu_5a8b2c4f25821d14.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="187"
data-flex-basis="450px"
&gt;&lt;/p&gt;
&lt;p&gt;このように、Positional Encodingはtokenの埋め込み次元分作成し、tokenの埋め込みベクトルに対して加算することで、positionをtokenに加算し、表現する仕組みである。&lt;/p&gt;
&lt;h3 id="transformer全体で見たときの意味"&gt;Transformer全体で見たときの意味&lt;/h3&gt;
&lt;p&gt;では、Transformer全体で見たときの、Positional Encodingの意味とは何か？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;もちろん、tokenの文中の位置である&lt;/li&gt;
&lt;li&gt;ただ、なぜ位置が重要かと言うと、実はTransformerのコアであるAttention機構では位置を考慮しないからである&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="attention機構の概略"&gt;Attention機構の概略&lt;/h3&gt;
&lt;p&gt;下図にAttention機構の概略を示す。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;シンプルに図解すると、下図のような処理をattention機構では行っている&lt;/li&gt;
&lt;li&gt;あくまでトークンとトークンの関係のみを考慮して、どのトークンに注目するのかを決定している&lt;/li&gt;
&lt;li&gt;故に、attention機構だけでは文字の場所を考慮していない仕組みとなっている&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-21.png"
width="1366"
height="1024"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-21_hu_55e565fd5f453aa6.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-21_hu_74c06062c21e4dcc.png 1024w"
loading="lazy"
alt="Attention Mechanism"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
&gt;&lt;/p&gt;
&lt;h3 id="attentionの前に使われていた機構"&gt;Attentionの前に使われていた機構&lt;/h3&gt;
&lt;p&gt;Attentionが流行る前はRNNやLSTMがNLPのデファクトスタンダードだった。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;例えば、Transformerの前に使われていたRNNやLSTMでは、Positional Encodingが不要だった&lt;/li&gt;
&lt;li&gt;なぜなら、入力シーケンスを順序通りに処理し、各時点での隠れ層で時系列を考慮できたから&lt;/li&gt;
&lt;li&gt;つまり、RNNなどでは、時系列データの文脈を隠れ層で捉えていた&lt;/li&gt;
&lt;li&gt;他方、TransformerはAttentionを使うが、Attentionはシーケンスを考慮しない&lt;/li&gt;
&lt;li&gt;故に、Positional Encodingが重要になってくる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image.png"
width="1377"
height="580"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image_hu_6e91896450f7e0d7.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image_hu_dfc59e5811e8b41.png 1024w"
loading="lazy"
alt="RNN Mechanism"
class="gallery-image"
data-flex-grow="237"
data-flex-basis="569px"
&gt;&lt;/p&gt;
&lt;p&gt;上図にRNNのメカニズムを示す。&lt;br&gt;
ちなみに、ここで、各文字列は次を示す。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$W_{xh}$: input(x)から隠れ層への重み&lt;/li&gt;
&lt;li&gt;$W$: 隠れ層から隠れ層への重み&lt;/li&gt;
&lt;li&gt;$W_{hy}$: 隠れ層からoutput(y)への重み&lt;/li&gt;
&lt;li&gt;$a$: アクティベーションレイヤー&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="positional-encodingの詳解"&gt;Positional Encodingの詳解&lt;/h2&gt;
&lt;h3 id="単語のベクトル表現"&gt;単語のベクトル表現&lt;/h3&gt;
&lt;h4 id="単語のベクトル表現方法"&gt;単語のベクトル表現方法&lt;/h4&gt;
&lt;p&gt;まず、Positional Encodingを加算される前の、単語のembeddingを次に示す。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-10.png"
width="888"
height="435"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-10_hu_dc2768324faa2095.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-10_hu_3e4489a6c377a358.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="204"
data-flex-basis="489px"
&gt;&lt;/p&gt;
&lt;p&gt;上図の通り、単語に対して、3次元の埋め込み空間を用意し、単語のembedding表現をしている。&lt;br&gt;
Vは単語の埋め込みベクトル、Pは単語のPositional Encodingである。&lt;/p&gt;
&lt;h4 id="単語のベクトル表現への位置の追加"&gt;単語のベクトル表現への位置の追加&lt;/h4&gt;
&lt;p&gt;そして、それを単語のベクトル空間に落とすと次のようなイメージになる。&lt;br&gt;
赤、青、緑の線分が単語のベクトル表現を示す。&lt;br&gt;
これに対して、Positional Encodingを加算しているのが、緑の線分である。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-11.png"
width="899"
height="451"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-11_hu_f9094087953ea48b.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-11_hu_2cebee5f1e40d491.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="199"
data-flex-basis="478px"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;つまり、単語空間に対して位置を加算する事によって、位置情報も付与するという事である&lt;/li&gt;
&lt;li&gt;緑のベクトルはPositional Encodingを加算後にベクトルの向きが変わっている&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これがシンプルに言う、tokenへのPositional Encodingの追加と言う事。&lt;/p&gt;
&lt;h3 id="ポジションの値の決め方"&gt;ポジションの値の決め方&lt;/h3&gt;
&lt;h4 id="位置を値にする"&gt;位置を値にする&lt;/h4&gt;
&lt;p&gt;では、何をPositional Encodingの値とするのか？&lt;br&gt;
最もシンプルなのは、下図のようにtokenのpositionを埋め込む事。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-5.png"
width="426"
height="378"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-5_hu_f2259f39c4280929.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-5_hu_7e9762c37a138de5.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="112"
data-flex-basis="270px"
&gt;&lt;/p&gt;
&lt;p&gt;100 token目のPositional Encodingの値は100になると言う事。&lt;/p&gt;
&lt;h4 id="値域を制限して位置を値にする"&gt;値域を制限して位置を値にする&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;ただ、上の方法は、文が長いと際限なく値が大きくなる&lt;/li&gt;
&lt;li&gt;つまり、元々のtokenの埋め込みに大きすぎる影響を与えてしまう事を意味する&lt;/li&gt;
&lt;li&gt;そうすると、元々のtokenの埋め込みの意味がつぶれてしまう&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そこで、次のように抑制する。&lt;br&gt;
ここで、$pos$はtokenの位置を示す。&lt;/p&gt;
$$
\text{position value} = \frac{1}{pos−1}
$$&lt;ul&gt;
&lt;li&gt;例えば、位置が100 token目だった場合は$\frac{1}{99}$となる&lt;/li&gt;
&lt;li&gt;この手法では、文の長さに関係なく、Positional Encodingの最大値を1に制限できる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-12.png"
width="885"
height="443"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-12_hu_a4ef4403cc819f3.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-12_hu_c38b605f3b436c86.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="199"
data-flex-basis="479px"
&gt;&lt;/p&gt;
&lt;p&gt;例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;4個のtokenを持つ文の1つ目のtokenのposition値
&lt;ul&gt;
&lt;li&gt;1/3 = 0.33&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;10個のtokenを持つ文の1つ目のtokenのposition値
&lt;ul&gt;
&lt;li&gt;1/9 = 0.11&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上図は5 tokenある文の、それぞれに、一定のPositional Encodingの値を付与している。&lt;/p&gt;
&lt;h4 id="sin関数で埋め込む方法"&gt;sin関数で埋め込む方法&lt;/h4&gt;
&lt;p&gt;ただ、上の手法でも次の問題があった。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;テキスト、コーパス全体で同じ埋め込み値を持つ必要がある&lt;/li&gt;
&lt;li&gt;また、表現が豊かではない事、関数のsmoothさなど&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そこで、周波数ベースの位置埋め込みが発案された。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-3.png"
width="1083"
height="432"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-3_hu_c77f796c99f18eb1.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-3_hu_fab5cd91adf26d54.png 1024w"
loading="lazy"
alt="Sin curve"
class="gallery-image"
data-flex-grow="250"
data-flex-basis="601px"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;なお、三角関数の他には&lt;code&gt;[0, 1]&lt;/code&gt;を取るsigmoidなどがあるが、端に行くほど変化が鈍化してしまう欠点があった&lt;/li&gt;
&lt;li&gt;その点三角関数はpositionが大きくなってもvalueを変化させられて表現が豊かである&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="周波数を考慮してsin関数で埋め込む方法"&gt;周波数を考慮してsin関数で埋め込む方法&lt;/h4&gt;
&lt;p&gt;しかし、上記の方法は、次の問題があった。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;周期関数なので、positionが変化しても同じvalueの値が返される&lt;/li&gt;
&lt;li&gt;これは近傍のトークン間の違いは表せても遠くのトークンの違いを表現できない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そこで最大の文章量が来てもvalueが繰り返されないほど低い周波数も与えた。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-6.png"
width="886"
height="258"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-6_hu_e3ba731a6ea5ed4a.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-6_hu_9d30d19b9309049c.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="343"
data-flex-basis="824px"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;これで長い文章が来ても位置情報を個別に割り振れた&lt;/li&gt;
&lt;li&gt;つまり、低周波は近くのtokenとの関係を、高周波は遠くのtokenの関係を表現できると言う事&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="sinとcosを組み合わせて周波数を考慮して埋め込む方法"&gt;sinとcosを組み合わせて周波数を考慮して埋め込む方法&lt;/h4&gt;
&lt;p&gt;ただ上記の方法でも、次の問題があった。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;なぜなら低周波数にしたため、positionが小さいとき（例えば1, 2の場合）値がほとんど変化しない&lt;/li&gt;
&lt;li&gt;イメージは下の図の感じである&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-7.png"
width="927"
height="434"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-7_hu_9cfed083745e75d7.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-7_hu_78b0fab914a815e7.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="213"
data-flex-basis="512px"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;故に、90度ずれるsinとcosを組み合わせて利用する&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="最終的な要件"&gt;最終的な要件&lt;/h4&gt;
&lt;p&gt;つまり、表現の豊かさ、値域の制限、スケーラビリティなどを考慮して、最低必要なのは次の要素だった。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;トークンのpositionに応じて変化させる&lt;/li&gt;
&lt;li&gt;sin / cosを組み合わせて位置を埋め込む&lt;/li&gt;
&lt;li&gt;低周波と高周波を組み合わせて、近傍と遠くの関係を表現する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-22.png"
width="687"
height="386"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-22_hu_f50e264334c04a59.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-22_hu_ee0516061ce66101.png 1024w"
loading="lazy"
alt="sin(n/10000)とsin(n/1000)のグラフ"
class="gallery-image"
data-flex-grow="177"
data-flex-basis="427px"
&gt;&lt;/p&gt;
&lt;h4 id="position-encodingの数式"&gt;Position encodingの数式&lt;/h4&gt;
&lt;p&gt;結果、それらをまとめると次になる。&lt;/p&gt;
$$
{PE\left( pos,2i\right) =\sin \left( \dfrac{pos}{10000^{2i/d_{model}}}\right)
}
$$$$
{PE\left( pos,2i+1\right) =\cos \left( \dfrac{pos}{10000^{2i/d_{model}}}\right)
}
$$&lt;p&gt;ここで変数は次を示す。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;「pos」は、文中の特定のtokenの位置&lt;/li&gt;
&lt;li&gt;「d」は、文中の特定のtokenを表すベクトルの最大長/次元&lt;/li&gt;
&lt;li&gt;「i」は、各位置埋め込み次元のインデックス&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、2i+1の意味は次である。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;偶数番目（2n）の場合はsinを、奇数番目（2n+1）の場合はcosの関数を利用する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、PEとtokenの埋め込みベクトルの関係を示すと次のようになる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-20.png"
width="496"
height="238"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-20_hu_e3bc46380de306e7.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-20_hu_6ab63fde9a36315f.png 1024w"
loading="lazy"
alt="PEとベクトルの対応"
class="gallery-image"
data-flex-grow="208"
data-flex-basis="500px"
&gt;&lt;/p&gt;
&lt;h4 id="positional-encodingの可視化"&gt;Positional Encodingの可視化&lt;/h4&gt;
&lt;p&gt;それを可視化すると次になる。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-14.png"
width="894"
height="448"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-14_hu_b8dc14dfa73c03fa.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-14_hu_f125b30f70c37628.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="199"
data-flex-basis="478px"
&gt;&lt;/p&gt;
&lt;p&gt;つまり上図から次が言える。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;次元のindexが低いほど、高周波&lt;/li&gt;
&lt;li&gt;次元のindexが高いほど、低周波&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-13.png"
width="2048"
height="878"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-13_hu_5fee3f48866b9a80.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-13_hu_9615cf57a7217a95.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="233"
data-flex-basis="559px"
&gt;&lt;/p&gt;
&lt;p&gt;position=3の場合の計算の例。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;i=0 の場合
&lt;ul&gt;
&lt;li&gt;PE(3,0) = sin(3/10000^2(0)/3)&lt;/li&gt;
&lt;li&gt;PE(3,0) = sin(3/1)&lt;/li&gt;
&lt;li&gt;PE(3,0) = 0.14&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;i=1 の場合
&lt;ul&gt;
&lt;li&gt;PE(3,1) = cos(3/10000^2(1)/3)&lt;/li&gt;
&lt;li&gt;PE(3,1) = cos(3/436)&lt;/li&gt;
&lt;li&gt;PE(3,1) = 0.99&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;i=2 の場合
&lt;ul&gt;
&lt;li&gt;PE(3,2) = sin(3/10000^2(2)/3)&lt;/li&gt;
&lt;li&gt;PE(3,2) = sin(3/1.4)&lt;/li&gt;
&lt;li&gt;PE(3,2) = 0.03&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;tokenの埋め込みベクトルと位置埋め込みの関係を次に示す。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-15.png"
width="825"
height="612"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-15_hu_7a32ad0eddcfbb85.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-15_hu_894c75eb90561e47.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="134"
data-flex-basis="323px"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;下図のように、tokenのembeddingのi番目の値が周波数のi番目によって加算される&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-16.png"
width="905"
height="606"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-16_hu_51158dc8760c56e8.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-16_hu_982444b2eb6a9bc.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="149"
data-flex-basis="358px"
&gt;&lt;/p&gt;
&lt;p&gt;つまり次が言える。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;高周波（i=0）の時はpositionのlocal featureが表れる
&lt;ul&gt;
&lt;li&gt;なぜなら周期が早いので、近くのtoken間の差が大きく出るから&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;低周波（i=2）の時はpositionのglobal featureが表れる
&lt;ul&gt;
&lt;li&gt;なぜなら振幅が遅いので、全体的に差が出るように周期するから&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-17.png"
width="870"
height="418"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-17_hu_24441f692d5d9a4b.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-17_hu_6e476fabcc88151e.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="208"
data-flex-basis="499px"
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;つまり、別の言い方をすると、位置情報を全体と部分の振幅をもつ周波数に分解してそれぞれの埋め込み次元に適用している&lt;/li&gt;
&lt;li&gt;これは、おそらく周波数の合成をできるフーリエ変換をバラして適用している感じと捉えられる&lt;/li&gt;
&lt;li&gt;つまり、高周波と低周波をミックスすると、位置ごとに別々の表現にちゃんとなっているだろうということ&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="positional-encodingの可視化-1"&gt;Positional Encodingの可視化&lt;/h2&gt;
&lt;h3 id="positionとdimensionとsincosの等高線"&gt;positionとdimensionとsin/cosの等高線&lt;/h3&gt;
&lt;p&gt;次にpositionとdimensionとsin/cosの等高線を示す。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dimensionが低いと（encoding vectorの最初の方のindexの要素）は、高周波で、要素の番数が大きくなるほど、低周波になる&lt;/li&gt;
&lt;li&gt;これは、低次元と高次元を表現できることを意味する。なお、20番目以降ぐらいからは収束する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-8.png"
width="2421"
height="1180"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-8_hu_aaac8820a106b7a3.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-8_hu_3146b104185e5ce3.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="205"
data-flex-basis="492px"
&gt;&lt;/p&gt;
&lt;h3 id="encodingが取りうる値"&gt;encodingが取りうる値&lt;/h3&gt;
&lt;p&gt;次にencodingが取りうる値を2次元にして示す。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pos=10での位置埋め込みの値、横軸は埋め込みベクトルの次元jを表し、縦軸は位置埋め込みの値を示している&lt;/li&gt;
&lt;li&gt;jが縦に入れ替わっているのは、cos/sinの入れ替わりがあるから&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-9.png"
width="1746"
height="1101"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-9_hu_522ccd016715fa33.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-9_hu_6e444411167cf1f.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="158"
data-flex-basis="380px"
&gt;&lt;/p&gt;
&lt;h3 id="高周波と低周波の組み合わせの可視化"&gt;高周波と低周波の組み合わせの可視化&lt;/h3&gt;
&lt;p&gt;位置埋め込みで内積を取ったグラフを示す。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;同位相の波は強く干渉している&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-19.png"
width="786"
height="632"
srcset="https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-19_hu_c861832c3d43fe83.png 480w, https://www.m1ke.org/p/transformer%E3%81%AEpositional-encoding%E3%81%AE%E8%A7%A3%E9%87%88/image-19_hu_24c33140adee1ca1.png 1024w"
loading="lazy"
alt="異なる位置の位置符号間での内積の可視化"
class="gallery-image"
data-flex-grow="124"
data-flex-basis="298px"
&gt;&lt;/p&gt;
&lt;h2 id="その他"&gt;その他&lt;/h2&gt;
&lt;h3 id="encodingとembeddingとは"&gt;EncodingとEmbeddingとは&lt;/h3&gt;
&lt;p&gt;EncodingとEmbeddingを説明する。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Encodingは変数のベクトル表現のこと&lt;/li&gt;
&lt;li&gt;例えば、リンゴ、オレンジ、チンパンジーを表現するとする&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;one-hot encodingで、バイナリで表現する方法は次となる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;リンゴ：&lt;code&gt;[0, 1, 0]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;オレンジ：&lt;code&gt;[0, 1, 0]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;チンパンジー：&lt;code&gt;[0, 0, 1]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;つまり、1次元目がリンゴ、2次元目がオレンジ、3次元目がチンパンジーのbitと言う事である。&lt;br&gt;
ただし、これらの内積をとっても、類似性を考慮できない。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;理由は内積が全て0になるからである&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;明らかにリンゴとオレンジは意味が近く、リンゴとチンパンジーはそれと比較して意味が遠い。&lt;br&gt;
そこでtokenの埋め込み（Embedding）を行う。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;リンゴ：&lt;code&gt;[0.1, 0,9, 0.1]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;オレンジ：&lt;code&gt;[0.2, 0,9, 0.1]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;チンパンジー：&lt;code&gt;[-0.9, 0,4, -0.9]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;すると、cos類似度などで近似性をとれる。&lt;br&gt;
リンゴとオレンジは1に違い値となるが、リンゴとチンパンジーは-1に近い値となる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;単純に言うと、これがembedding&lt;/li&gt;
&lt;li&gt;つまり、embeddingとは、高次元（上述の例では3次元）に意味埋め込むという事&lt;/li&gt;
&lt;li&gt;内積やcos類似度は埋め込み空間でのベクトルの向きの一致度（ベクトルの類似度）を示している&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="encodingとembeddingの違い"&gt;EncodingとEmbeddingの違い&lt;/h3&gt;
&lt;p&gt;埋め込みや表現では境界線が曖昧だが、両者には明確な違いがある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;encodingは符号化&lt;/li&gt;
&lt;li&gt;embeddingは埋め込み&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、Trainingの視点だと次の違いがある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Encodingは学習しない（つまり、static）&lt;/li&gt;
&lt;li&gt;Embeddingは学習する（つまり、dynamic）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="なぜ三角関数で上手くpoistional-encodingができるのか"&gt;なぜ三角関数で上手くPoistional Encodingができるのか&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;We chose this function because we hypothesized it would allow the model to easily learn to attend by relative positions, since for any fixed offset k, PEpos+k can be represented as a linear function of PEpos.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;上が元々の論文での説明。
つまり、固定オフセットの場合、モデルが相対位置による学習を簡単に学習できるという仮説があったと言う事。&lt;/p&gt;
&lt;p&gt;実は絶対位置より相対位置（Relative Positioning）の方が重要であり、機械学習は内積の集積なので、線形変換ができる事=学習の容易さを示す。
例えば、I have a pen. だと、絶対的な4番目のpenの位置という情報より、aをoffsetとしたpenの位置が重要。&lt;/p&gt;
&lt;h3 id="相対位置で線形変換ができる事の証明"&gt;相対位置で線形変換ができる事の証明&lt;/h3&gt;
&lt;p&gt;全てのsine-cosine pairの$\omega_k$に対する、以下の式を満たす$M \in \mathbb{R}^{2\times2}$(ｔからは独立)が存在するという事。&lt;/p&gt;
$$
\newcommand{\br}{\\\\}
M\begin{bmatrix}
\sin(\omega_k . t) \br
\cos(\omega_k . t)
\end{bmatrix}
= \begin{bmatrix}
\sin(\omega_k . (t + \phi)) \br
\cos(\omega_k . (t + \phi))
\end{bmatrix}
$$&lt;p&gt;ここで、それぞれ次を意味する。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$k$ はPositional Encodingのindex（最小は0、最大は$=\frac{d_{model}}{2} $）&lt;/li&gt;
&lt;li&gt;$\phi$はoffset（元々の数式で言うpos）&lt;/li&gt;
&lt;li&gt;$t$は欲しいtokenのoffsetからの相対pos&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;線形変換されるベクトルは次のように$i$番目のindexから$k$を場合分けで算出する。&lt;/p&gt;
$$
\newcommand{\br}{\\\\}
\begin{align}
\vec{p_t}^{(i)} = f(t)^{(i)} &amp; :=
\begin{cases}
\sin({\omega_k} . t), &amp; \text{if}\ i = 2k \br
\cos({\omega_k} . t), &amp; \text{if}\ i = 2k + 1
\end{cases}
\end{align} %]]&gt;
$$&lt;p&gt;Mを$2 \times 2$の行列とし、次の$u_1, v_1, u_2, v_2$を探す。&lt;/p&gt;
$$
\newcommand{\br}{\\\\}
\begin{bmatrix}
u_1 &amp; v_1 \br
u_2 &amp; v_2
\end{bmatrix}
\begin{bmatrix}
\sin(\omega_k . t) \br
\cos(\omega_k . t)
\end{bmatrix} =
\begin{bmatrix}
\sin(\omega_k . (t + \phi)) \br
\cos(\omega_k . (t + \phi))
\end{bmatrix}
$$&lt;p&gt;加法定理より、右辺を展開すると次になる。&lt;/p&gt;
$$
\newcommand{\br}{\\\\}
\begin{bmatrix}
u_1 &amp; v_1 \br
u_2 &amp; v_2
\end{bmatrix} .\begin{bmatrix}
\sin(\omega_k . t) \br
\cos(\omega_k . t)
\end{bmatrix} = \begin{bmatrix}
\sin(\omega_k . t)\cos(\omega_k .\phi) + \cos(\omega_k . t)\sin(\omega_k .\phi) \br
\cos(\omega_k . t)\cos(\omega_k .\phi) - \sin(\omega_k . t)\sin(\omega_k . \phi)
\end{bmatrix}
$$&lt;p&gt;その結果、次の方程式が成り立つ。&lt;/p&gt;
$$
\newcommand{\br}{\\\\}
\small
\begin{align}
u_1 \sin(\omega_k . t) + v_1 \cos(\omega_k . t) = &amp; \ \ \ \ \cos(\omega_k .\phi)\sin(\omega_k . t) + \sin(\omega_k .\phi)\cos(\omega_k . t) \br
u_2 \sin(\omega_k . t) + v_2 \cos(\omega_k . t) = &amp; - \sin(\omega_k . \phi)\sin(\omega_k . t) + \cos(\omega_k .\phi)\cos(\omega_k . t)
\end{align}
$$&lt;p&gt;上を解くと次を得る。&lt;/p&gt;
$$
\newcommand{\br}{\\\\}
\begin{align}
u_1 = \ \ \ \cos(\omega_k .\phi) &amp; \ \ \ v_1 = \sin(\omega_k .\phi) \br
u_2 = - \sin(\omega_k . \phi) &amp; \ \ \ v_2 = \cos(\omega_k .\phi)
\end{align}
$$&lt;p&gt;結果、行列の$M$は次となる。&lt;/p&gt;
$$
\newcommand{\br}{\\\\}
M_{\phi,k} = \begin{bmatrix}
\cos(\omega_k .\phi) &amp; \sin(\omega_k .\phi) \br
- \sin(\omega_k . \phi) &amp; \cos(\omega_k .\phi)
\end{bmatrix}
$$&lt;p&gt;上のMは$t$に依存しない行列であり、任意のoffset（$\phi$）からの$t$番目のtokenのPositional Encodingについて、
$t$なしで、$M_{\phi,k}$の線形変換で得られる事を意味する。つまり、$\vec{p_{t+\phi}}$を$\vec{p_t}$から表現できる事を意味する。
行列の中身はいわゆるCVのローテーションマトリックスとほぼ同じである。
また、ベクトルが2次元では無い時は、対角行列を使えば同じ結果となる。&lt;/p&gt;
&lt;h3 id="三角関数の周波数frequencyの意味"&gt;三角関数の周波数（Frequency）の意味&lt;/h3&gt;
&lt;p&gt;前述で次のように各tokenのposition encodingを定義したが、三角関数の内部の式の意味を説明する。&lt;/p&gt;
$$
\newcommand{\br}{\\\\}
\vec{p}(pos) :=
\begin{bmatrix}
\sin\left(\frac{pos}{f_1}\right) \br
\cos\left(\frac{pos}{f_1}\right) \br
\sin\left(\frac{pos}{f_2}\right) \br
\cos\left(\frac{pos}{f_2}\right) \br
\vdots \br
\sin\left(\frac{pos}{f_d}\right) \br
\cos\left(\frac{pos}{f_d}\right) \br
\end{bmatrix}
$$&lt;p&gt;ここで、$f_d$は$f_{\frac{d_\text{model}}{2}}$を示す。
なぜ、$d_{model}$に対して2で割るかと言うと、偶数奇数でsin/cosを使っているので、最大で$\frac{d_{model}}{2}$分のrangeを使うため。&lt;/p&gt;
&lt;p&gt;さらに、あるposition番目のtokenではpositionは定数の為、逆数であれば良く、あるi番目のfrequencyは波長$\lambda$を使い、次のように表せる。&lt;/p&gt;
$$
f_i = \frac{1}{\lambda_{i}} := 10000 ^ {\frac{2i}{d_{model}}}
$$&lt;p&gt;なお、基数の$10000$はハイパーパラメータとなる。
これがPositional Encodingの数式の意味となる。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://erdem.pl/2021/05/understanding-positional-encoding-in-transformers" target="_blank" rel="noopener"
&gt;Understanding Positional Encoding in Transformers - Blog by Kemal Erdem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kazemnejad.com/blog/transformer_architecture_positional_encoding/" target="_blank" rel="noopener"
&gt;Transformer Architecture: The Positional Encoding - Amirhossein Kazemnejad&amp;rsquo;s Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://qiita.com/snsk871/items/93aba7ad74cace4abc62" target="_blank" rel="noopener"
&gt;Positional Encodingを理解したい #DeepLearning - Qiita&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hackernoon.com/ja/Transformer-%E3%83%8B%E3%83%A5%E3%83%BC%E3%83%A9%E3%83%AB-%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AE%E7%B2%BE%E5%BA%A6%E3%81%AE%E8%83%8C%E5%BE%8C%E3%81%AB%E3%81%82%E3%82%8B%E7%A7%98%E5%AF%86%E3%82%92%E4%BD%8D%E7%BD%AE%E3%81%AB%E5%9F%8B%E3%82%81%E8%BE%BC%E3%82%80" target="_blank" rel="noopener"
&gt;位置埋め込み: Transformer Neural Networks の精度の背後にある秘密 | HackerNoon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kazemnejad.com/blog/transformer_architecture_positional_encoding/" target="_blank" rel="noopener"
&gt;Transformer Architecture: The Positional Encoding - Amirhossein Kazemnejad&amp;rsquo;s Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;大規模言語モデル入門&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learnopencv.com/attention-mechanism-in-transformer-neural-networks/" target="_blank" rel="noopener"
&gt;Understanding Attention Mechanism in Transformer Neural Networks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://pub.towardsai.net/introduction-to-the-architecture-of-recurrent-neural-networks-rnns-a277007984b7" target="_blank" rel="noopener"
&gt;Introduction to the Architecture of Recurrent Neural Networks (RNNs) | by Manish Nayak | Towards AI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://machinelearningmastery.com/a-gentle-introduction-to-positional-encoding-in-transformer-models-part-1/" target="_blank" rel="noopener"
&gt;A Gentle Introduction to Positional Encoding in Transformer Models, Part 1 - MachineLearningMastery.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kazemnejad.com/blog/transformer_architecture_positional_encoding/" target="_blank" rel="noopener"
&gt;Transformer Architecture: The Positional Encoding - Amirhossein Kazemnejad&amp;rsquo;s Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.timodenk.com/linear-relationships-in-the-transformers-positional-encoding/" target="_blank" rel="noopener"
&gt;Linear Relationships in the Transformer’s Positional Encoding - Timo Denk&amp;rsquo;s Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/abs/1706.03762" target="_blank" rel="noopener"
&gt;[1706.03762] Attention Is All You Need&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.timodenk.com/trigonometric-functions-formulary/" target="_blank" rel="noopener"
&gt;Trigonometric Functions Formulary - Timo Denk&amp;rsquo;s Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>