Attentionがトークン間の「関係性」を捉えた後、FFN(Feed-Forward Network)が各トークンを個別に処理します。この「個別指導」により、情報の抽象化と強化が行われ、トークンの表現はより深く、より強力なものへと進化します。
2層の全結合ネットワーク(MLP)で構成。各トークンを個別に処理し、①次元を拡張 → ②非線形変換(ReLU等) → ③次元を縮小、という流れで情報を質的に変換します。
Attentionの線形的な処理に対し、非線形変換を加えることでモデル全体の表現力を飛躍的に高めます。これにより、単純な関係性を超えた複雑なデータパターンを学習可能にします。
具体的な情報からより高次の「概念」を抽出(抽象化)し、タスクにとって重要な情報を際立たせ、ノイズを抑制(強化・フィルタリング)します。
前回は、Transformerモデルのまさに「心臓部」とも言えるAttention機構が、まるで言葉のオーケストラの中で各楽器(単語)の役割と他の楽器との調和(文脈)を魔法のように読み解き、一つ一つのトークンに豊かな表情を与える様子を一緒に探求しましたね。Query、Key、Valueという三役者たちが織りなすダイナミックな情報のキャッチボールは、AIが文脈を理解する上でいかに巧妙な仕組みを用いているかを感じさせてくれる、まさに圧巻のステージだったのではないでしょうか。
さて、Attentionが織り成したこの文脈のタペストリー、これだけでも十分に素晴らしい情報が詰まっているように感じられます。ですが、Transformerの物語は、実はここで終わりではないんです。「Attentionが集めてきたこの貴重な情報を、最終的な目的(例えば、より正確な診断支援や、より自然な医療文書の生成、あるいは新しい治療法に繋がる論文の深い理解など)のために、もう一段階、力強く、そして賢く磨き上げることはできないだろうか?」――Transformerの設計者たちは、そう考えました。そこで登場するのが、今回の主役であるFFN(Feed-Forward Network:フィードフォワードネットワーク)、Transformerの世界では特にPosition-wise Feed-Forward Networkと呼ばれる、各トークンを個別に鍛え上げる「専門トレーナー」のような存在です。
この記事では、「なぜAttentionの素晴らしい仕事の後に、さらにFFNというステップが必要なの?」という素朴な疑問から出発し、このFFNが、Attentionから受け取ったバトン(各トークンの表現)をどのようにして「意味の深化」というゴールへと導いていくのか、その秘密のレシピに迫ります。特に、FFNが持つシンプルな2層のMLP(Multi-Layer Perceptron)という構造、そしてそこで行われる「非線形変換」というちょっとした魔法が、なぜ各トークンの表現をより抽象的で強力なものへと変貌させることができるのか、その意義と驚くべき効果を、医療分野でご活躍の皆さんの日常的な感覚にも通じるように、できる限りやさしく、そして直感的にご理解いただけるように、丁寧にお話ししていきたいと思います。さあ、Attentionの次のステージへ、一緒に進んでいきましょう!

1. Attention機構のおさらいとFFNへのバトンパス
さて、前回の冒険では、Transformerモデルの内部で、まるでオーケストラの指揮者のように大活躍するAttention機構、特にSelf-Attentionの素晴らしい働きに光を当てましたね。入力された文章やデータ(トークン列)の中で、それぞれの言葉が他のどの言葉と深い関係にあるのか、その「つながり」の強さをダイナミックに見つけ出し、重み付けをする。そして、その情報を元に、一つ一つの言葉(トークン)に、いわば「文脈の香り」を豊かにまとわせた、新しいベクトル表現を創り上げてくれるのでした。
例えば、医療記録に書かれた「熱」という一言。これだけでは、その背景にある意味は曖昧です。しかし、Attention機構は、その前後の「昨夜からの急な」「39度の高」「悪寒戦慄を伴う」といった言葉たちとの関連性に「注目」することで、この「熱」が単なる体温上昇ではなく、「感染症を強く疑わせる危険な発熱」という、より具体的で切実な意味合いを帯びた情報へと昇華させてくれるイメージです。まさに、一つ一つの言葉が、まるで周囲の状況やニュアンスを敏感に察知するセンサーを備えたかのように、より賢く、より文脈に応じた振る舞いを見せ始める瞬間でした。このAttentionの働きによって、各トークンは「世間を知り、空気を読んだ」状態になったと言えるかもしれませんね。
Attentionがこれほどまでに頑張って、文脈をたっぷり吸い込んだ賢いトークン表現を作り出してくれたわけですが、ここで一つ、ふと疑問が湧いてきませんか? 「なるほど、Attentionの仕事ぶりは見事だ。でも、これでモデルの情報処理は、もう万全なのだろうか? この表現を、最終的なタスク(例えば、より正確な診断名の予測や、患者さん一人ひとりに合わせた治療法の提案など)に役立てるには、もう十分なのだろうか?」と。
確かに、Attentionによって各トークンは、いわば「周囲との関係性を理解した」状態になりました。しかし、Transformerという、より人間の知能に近い働きを目指す上で、その設計者たちは「まだやれることがあるはずだ。この、いわば一次加工された情報を、もっと深くまで、もっと多角的に磨き上げることはできないだろうか?」と考えたようなのです。そして、その「もう一段階上の磨き上げ」を実現するために、さらなる一工夫が加えられました。
ここで、少し想像を翼を広げてみましょう。Attention機構が、まるで超一流の医療リサーチチームだとします。彼らは、ある患者さんの複雑で捉えどころのない病態(これが現在の大きなテーマですね)について、山のようなカルテ記録、膨大な量の検査データ、そして世界中から集められた関連医学文献(これらが文中の他のトークン情報に相当します)を徹底的に調査・分析し、関連性の高い重要な情報を的確にピックアップ。そして、それらを整理・統合して、非常に質の高い中間報告書(これがAttentionによる文脈を考慮したトークン表現、いわば一次的な分析結果です)をまとめ上げてくれました。
この中間報告書、それ自体が素晴らしい価値を持つのは間違いありません。しかし、この報告書に書かれた情報を元にして、例えば「この患者さんに最も効果が期待できる次の一手となる治療法は何か?」とか、「この一見複雑な病態の根本的な原因として、最も確からしい医学的仮説は何か?」といった、より一歩踏み込んだ、深い洞察や具体的な治療戦略、あるいは新たな研究の方向性を練り上げるためには、どうでしょう? その詳細な中間報告書を、今度は各分野のトップスペシャリストたち――例えば、循環器内科医、内分泌代謝内科医、画像診断医、病理医、分子生物学者といった面々――が、それぞれの非常に高度な専門的知識と経験、そして独自の視点からじっくりと読み解き、分析し、時にはチーム内で活発な議論を重ね、情報を多角的に吟味し、新たな知見やこれまで見過ごされてきた可能性へと『昇華』させていく…。そんな、より専門的で深いレベルでの思考プロセスが、きっと必要になってくるのではないでしょうか。
まさに、このリサーチチームの秀逸な中間報告書(Attentionの出力)を受け取り、その報告書に記載された個々の重要な情報(各トークンの表現)に対して、より深いレベルでの「思索」と「意味の再構築」を行う、いわばその道のプロフェッショナル集団、それが次に私たちが一緒に探求していくFFN(Feed-Forward Network)の役割なんです。Attentionが集めてきた、いわば「素材の味を活かした、新鮮で質の高い情報群」に対して、FFNは一つ一つの素材(トークン)に改めて丁寧に向き合い、それぞれに最適な「仕上げの調理」――時には大胆な変換、時には繊細な味付け――を施すことで、全体の情報としての価値をより豊かに、そして本質的な意味をより深みのあるものへと高めていく。そんなイメージで捉えていただけると、FFNの存在意義が少し見えてくるかもしれませんね。さあ、このFFNがどのようにしてその魔法を実現するのか、次のセクションで詳しく見ていくことにしましょう。
2. FFN(Feed-Forward Network)とは何か?– 各トークンの個別「集中治療室」
さて、前のセクションでは、Attention機構という優秀なリサーチチームが、文脈という名の広大な情報源から関連性の高い情報をまとめ上げ、各トークンに「一次分析レポート」とも言える豊かな表現を与えてくれる様子を見ましたね。そして、そのレポートを受け取り、さらに深い洞察を引き出す「専門家集団」の役割を担うのがFFNだとお伝えしました。
では、このFFNとは、具体的にどのような姿形をしていて、どのような魔法の呪文(あるいは、ここでは数式と言った方がしっくりくるかもしれませんね)を使って、各トークンの情報をさらに磨き上げていくのでしょうか?一緒にその正体に迫ってみましょう。
Transformerモデルの中で活躍するFFNは、より正確には「Position-wise Feed-Forward Network」と呼ばれています。この名前、実はFFNの二つの非常に大切な特徴を的確に言い表しているんです。
- Position-wise(位置ごとに): これは、FFNが入力されたトークン列(例えば、文章を単語ごとに区切ったもの)のそれぞれの位置のトークンに対して、個別に、そして独立に適用される、という意味です。思い出してください、Attention機構(特にSelf-Attention)は、トークン同士の関係性、つまり「あっちの単語とこっちの単語がどう関連しているか」という横のつながりを見るのが得意でしたね。そのAttentionが仕事をし終えた後、FFNはバトンを受け取り、今度は各トークンが持つベクトル表現に対して、いわば「一対一の個別指導」を行うのです。あるトークンがFFNで処理されている間、他のトークンはその処理に直接口出ししません。まるで、各トークンが自分専用の「集中治療室」や「個別カウンセリングルーム」に入って、専門家(FFN)による特別なケアを受けるようなイメージでしょうか。
- Identical Network(同一のネットワーク、同じ専門家チーム): もう一つの重要な特徴は、シーケンス内の全てのトークンに対して、全く同じ構造で、全く同じパラメータ(学習によって調整される重みやバイアス)を持つFFNが使われる、という点です。これは、一見すると「え、全員に同じ指導で大丈夫なの?」と思うかもしれません。しかし、ここが巧妙なところで、入力される各トークンのベクトル表現(Attention層から渡される情報)は、既にそのトークン独自の位置や文脈情報を反映して異なっています。そのため、同じFFN(同じ専門家チーム)を適用したとしても、入力が異なれば出力も自然と異なり、各トークンに応じた適切な処理がなされるわけです。そして、同じFFNを使い回すことで、モデル全体のパラメータ数を大幅に抑えることができ、学習効率も向上するという、非常に賢い設計になっているのです。まるで、非常に優秀な専門家チームが、一人ひとりの患者さんの個別データ(各トークンのベクトル)を元に、標準化されつつも質の高い診断プロトコル(FFNの処理)を適用していくのに似ていますね。
では、この「各トークンの個別集中治療室」とも言えるFFNの中では、具体的にどのような「治療(処理)」が行われているのでしょうか?驚くことに、こんなに重要な役割を担うFFNですが、その内部構造自体は、実は意外なほどシンプルなんです。
FFNの構造:2層の全結合ニューラルネットワーク(MLP)
FFNの基本構造は、主に2つの全結合層(Fully Connected Layer、または線形層:Linear Layerとも呼ばれます)と、その間に挟まれた非線形活性化関数から成る、いわゆる2層のMLP(Multi-Layer Perceptron)です。MLPと聞くと、ニューラルネットワークの基本として学んだ記憶がある方もいらっしゃるかもしれませんね。まさに、そのシンプルな構造が、Transformerの中でも重要な役割を担っているのです。
具体的には、以下の2ステップの処理が行われます。
- 第1ステップ(拡張と非線形変換):
- まず、Attention層から渡されてきた各トークンのベクトル表現(次元数を \(d_{model}\) とします。例えば512次元など)が、最初の全結合層(重み行列 \(W_1\) とバイアス \(b_1\) を持つ)によって、より大きな中間次元(\(d_{ff}\) とします。この \(d_{ff}\) は、通常 \(d_{model}\) の4倍程度の大きさに設定されることが多いです。例えば \(d_{model}=512\) なら \(d_{ff}=2048\) といった具合)へと線形変換(アフィン変換)によって「拡張」されます。
- 次に、この拡張されたベクトルに対して、非線形活性化関数(例えば、ReLU関数やGeLU関数など)が要素ごとに適用されます。この活性化関数こそが、FFNに「ただの線形変換」以上の魔法、つまり複雑な情報処理能力を与えるための重要なスパイスなんです。なぜ非線形性が重要なのかは、次のセクション(22.4.3)でじっくりお話ししますね。
- 第2ステップ(縮小):
- 非線形活性化関数を通過した中間表現(次元は \(d_{ff}\))は、次に2番目の全結合層(重み行列 \(W_2\) とバイアス \(b_2\) を持つ)によって、再び元の \(d_{model}\) 次元へと線形変換(アフィン変換)によって「縮小」あるいは「射影」されます。
この一連の処理を数式で表してみましょう。ある一つのトークンに対して、Attention層からの出力をベクトル \(x\)(これは \(d_{model}\) 次元のベクトルです)とすると、FFNの出力 \(\text{FFN}(x)\) は、活性化関数としてReLU(Rectified Linear Unit、\(\text{max}(0, z)\) で定義される関数)を用いた場合、以下のように書けます。
\[ \text{FFN}(x) = \text{max}(0, xW_1 + b_1)W_2 + b_2 \]
この式の各要素が何を意味しているか、少し詳しく見ていきましょう。
- \(x\): FFNへの入力となる、単一トークンのベクトル表現です。その次元(要素数)は \(d_{model}\) です。
- \(W_1\): 第1層の線形変換に使われる重み行列です。入力 \(x\) の次元を \(d_{model}\) から中間層の次元 \(d_{ff}\) へと変換するため、その形状は(\(x\) を行ベクトルとして扱う場合) \((d_{model} \times d_{ff})\) となります。
- \(b_1\): 第1層の線形変換に加算されるバイアスベクトルです。その次元は \(d_{ff}\) です。
- \(\text{max}(0, \cdot)\): ReLU活性化関数を表します。入力された値が0以下であれば0を、0より大きければその値をそのまま出力します。この非常にシンプルな操作が、モデルに非線形な表現力を与えます。最近のTransformerモデルでは、ReLUの代わりにGeLU (Gaussian Error Linear Unit) という、より滑らかな活性化関数が好んで用いられる傾向にあります。
- \(W_2\): 第2層の線形変換に使われる重み行列です。中間層の次元 \(d_{ff}\) から元の次元 \(d_{model}\) へと戻すため、その形状は \((d_{ff} \times d_{model})\) となります。
- \(b_2\): 第2層の線形変換に加算されるバイアスベクトルです。その次元は \(d_{model}\) です。
数字の行列計算がイメージしにくい…という方もいらっしゃるかもしれませんね。ここで、ある一つのトークンベクトル \(x\) がFFNを通過する際の、ベクトルの形状(次元)の変化を追ってみましょう。仮に \(d_{model}=512\)、\(d_{ff}=2048\) としてみます。
入力ベクトル x (形状: 1 × d_model, 例: 1 × 512)
[●, ●, ..., ●] (d_model個の数値)
↓ 第1層の線形変換 (xW_1 + b_1)
重み行列 W_1 (形状: d_model × d_ff, 例: 512 × 2048)
バイアス b_1 (形状: 1 × d_ff, 例: 1 × 2048)
計算結果のベクトル h_expanded (形状: 1 × d_ff, 例: 1 × 2048)
[○, ○, ..., ○] (d_ff個の数値。情報が一時的に広い空間に展開されたイメージ)
↓ 非線形活性化 (例: ReLU(h_expanded))
活性化後のベクトル h_activated (形状: 1 × d_ff, 例: 1 × 2048)
[△, △, ..., △] (d_ff個の数値。ここで非線形な処理が加わる)
↓ 第2層の線形変換 (h_activated * W_2 + b_2)
重み行列 W_2 (形状: d_ff × d_model, 例: 2048 × 512)
バイアス b_2 (形状: 1 × d_model, 例: 1 × 512)
計算結果のベクトル FFN(x) (形状: 1 × d_model, 例: 1 × 512)
[◆, ◆, ..., ◆] (d_model個の数値。元の次元に戻りつつ、情報が質的に変換された)

このように、入力された各トークンのベクトルは、FFNの内部で一度大きな次元空間 (\(d_{ff}\)) へと広げられ、そこで非線形な「味付け」をされた後、再び元の次元 (\(d_{model}\)) に戻ってきます。この「広げて、処理して、戻す」という一連の流れが、情報を豊かにするための秘訣の一つなんですね。
このFFNの構造を、先ほども少しお見せしたブロック図で再確認しておきましょう。
graph TD;
input["入力 x (d_model次元のトークンベクトル)"] --> layer1["第1層: 線形変換 (W_1, b_1)
次元を d_model から d_ff へ「拡張」"];
layer1 --> activation["非線形活性化関数 (例: ReLU, GeLU)
各要素に個別に適用 (ここで非線形性が導入!)"];
activation --> layer2["第2層: 線形変換 (W_2, b_2)
次元を d_ff から d_model へ「縮小」"];
layer2 --> output["出力 FFN(x) (d_model次元の変換されたトークンベクトル)"];
classDef default fill:#f9f9f9,stroke:#333,stroke-width:2px,rx:5px,ry:5px;
class input,output fill:#lightgrey,stroke:#333,stroke-width:2px,rx:5px,ry:5px;
class layer1,activation,layer2 fill:#lightblue,stroke:#333,stroke-width:2px,rx:5px,ry:5px;
そして、繰り返しになりますが、この一連のFFN処理(つまり、重み行列 \(W_1, W_2\) とバイアス \(b_1, b_2\) のセット)は、入力シーケンス中の全てのトークンに対して全く同じものが使われます。しかし、入力となる各トークンのベクトル \(x\) がそれぞれ異なるため(Attentionによって既に文脈情報がエンコードされていますからね!)、FFNを通過した後の出力ベクトルも、トークンごとに異なる、より洗練された表現へと変わっていくのです。これが、Position-wise Feed-Forward Networkの「賢さ」と「効率の良さ」を両立させる設計の妙と言えるでしょう。
3. なぜFFNが必要なのか? 非線形変換がもたらす「意味の深化」という魔法
さて、前のセクションではFFNの構造、特に2層の全結合ニューラルネットワーク(MLP)と、その間に挟まる「非線形活性化関数」という部品があることを見ましたね。Attention機構がトークン間の華麗な連携プレーで文脈情報を集めてくれた後なのに、「なぜわざわざFFNで、しかも各トークンを個別に処理するという、一見地味な一手間を加える必要があるのだろう? Attentionだけでも十分に賢そうだったのに…」と、少し首を傾げている方もいらっしゃるかもしれません。
その疑問、とても良いところに気づかれました!実は、このFFN、特にその心臓部である非線形活性化関数こそが、Transformerが単なる情報整理屋で終わらず、より人間のように「深く考える」ための、決定的な役割を担っているのです。Attentionが集めてきた情報は、いわば「素晴らしい素材」ですが、その素材の味を最大限に引き出し、時には全く新しい風味を生み出すのが、FFNの非線形変換という「魔法のスパイス」なのです。
もう少し詳しく言うと、Attention機構の主な仕事、特にスコアを計算したり、Valueベクトルを重み付けして合計したりする過程は、その多くが「線形的」な操作に基づいています。線形的な操作というのは、ざっくり言えば、入力に対して出力が比例するような、グラフに描くと直線になるような、比較的「素直な」変換です。これはこれで、異なる情報を組み合わせたり、重要度に応じて強弱をつけたりするには非常に有効なのですが、もし世の中の全ての事象が、単純な足し算や比例関係だけで説明できるとしたら、私たちの世界はもっとシンプルで、もしかしたら少し退屈なものになってしまうかもしれませんよね?

実際には、私たちの周りの現象や、特に人間の言葉や思考というのは、もっと複雑で、もっと「ひねくれた」、つまり「非線形」な関係性で満ち溢れています。例えば、医療の現場でも、ある薬の効果が投与量に単純比例するとは限りません。ある量を超えると効果が頭打ちになったり、逆に副作用が急増したりすることもありますよね。あるいは、患者さんの複数の検査値が、それぞれ単独では正常範囲内でも、それらが特定の組み合わせ(非線形な相互作用)を示すことで、初めて重大な疾患のサインとなることもあります。こうした複雑な現実をAIが理解し、対応するためには、線形的な処理能力だけでは限界があるのです。

ここで救世主として登場するのが、FFNの内部に組み込まれた非線形活性化関数(Non-linear Activation Function)、代表的なものにReLU (Rectified Linear Unit) や GeLU (Gaussian Error Linear Unit) があります。これらの関数が、Transformerの表現力を線形の壁を越えて、一気に豊かにしてくれるのです。
線形関数がどこまでもまっすぐ進む一本道だとすれば、非線形関数は途中でカーブしたり、上り坂や下り坂が現れたり、特定の地点で分岐したりする、変化に富んだ道のようなもの、とイメージしてみてください。
この「カクッと曲がる」や「反応の仕方が変わる」といった性質が、AIに新しい能力をもたらします。具体的に、非線形変換がどのように「意味の深化」に貢献するのか、その主なポイントを3つほど見ていきましょう。
より複雑な関数(=関係性)を表現する能力の獲得
これは少し専門的な話になりますが、「普遍性定理(Universal Approximation Theorem)」という、ニューラルネットワークの分野では非常に有名な定理があります。ものすごく簡単に言うと、「ニューラルネットワークに、適切な数のニューロン(計算ユニット)と、少なくとも一層の非線形活性化関数が含まれていれば、理論上、どんなに複雑な形をした関数(つまり、入力と出力の間のどんなに複雑な関係性)でも、ある程度の精度で真似っこできる『万能なモノマネ師』になれる可能性がある」という、ちょっと夢のような話です。
FFNがこの非線形性という「パスポート」を持つことで、Transformer全体として、言葉の裏に隠された人間の感情の機微、文脈によって変化する皮肉のニュアンス、あるいは専門分野特有の非常に込み入った論理関係など、単純な線形的な組み合わせでは到底捉えきれない、より多様で奥深いデータのパターンを学習し、表現する扉が開かれるのです。医療で言えば、複数のバイタルサインや検査値のわずかな変化が、時間経過と共に非線形的に組み合わさって現れる病態の進行パターンなどを捉えるのに役立つかもしれませんね。
特徴量の賢い相互作用と、情報フローの選択的コントロール
非線形関数は、入力された情報(Attentionを経たトークンベクトル内の各要素、つまり特徴量ですね)同士が、単純な足し算や掛け算を超えた、より複雑な形で相互に影響し合うことを可能にします。そして、まるで賢いゲートキーパーのように、情報フローを選択的にコントロールする役割も果たします。
例えば、代表的な非線形活性化関数であるReLU関数を思い出してみましょう。その定義は \( \text{ReLU}(z) = \text{max}(0, z) \) と、驚くほどシンプルです。これは、「入力値 \(z\) がもしマイナスだったら、その情報はシャットアウトして0にする!でも、もしプラスだったら、その情報はそのまま通す!」という、非常に明確な「オン・オフ」のスイッチ(あるいはゲート)のような働きをします。
この「通す/通さない」という判断が、トークンベクトルの各要素に対して行われることで、FFNは「このトークンが今持っている情報のうち、どの側面を特に重要視して活性化させ、どの側面は今は抑えておくべきか」という、状況に応じた情報の取捨選択や強弱付けを、非常に柔軟に行えるようになるのです。これが、トークンごとの意味表現をよりシャープに、そして文脈に合わせて適切に調整するのに貢献します。
表現空間の魔法のような変換(高次元への一時的な旅)
前のセクションで、FFNの多くが \(d_{model} \rightarrow d_{ff} \rightarrow d_{model}\) という、一度次元を大きく広げて(例えば512次元を2048次元に)、その後で元の次元に戻す、という構造を持っていることを見ましたね。この「広げて、処理して、また戻す」という一見不思議な操作にも、非線形性と組み合わせることで大きな意味が生まれます。
これは、情報を一時的に非常に高次元の「広い作業台」のような空間に一度ばらまいてみる、と例えることができるかもしれません。次元が低い状態ではごちゃ混ぜになっていて見分けがつかなかったり、複雑に絡み合っていたりする情報の特徴も、より次元の高い広い空間に射影してみると、それぞれの特徴が互いに離れて見通しが良くなり、より複雑な関係性の発見や、より細かい特徴の分離・抽出がしやすくなる、という考え方です。
そして、その高次元の「広い作業台」の上で、非線形活性化関数という名の特殊な工具を使って情報の取捨選択や変換を施した後、再び元の次元の空間に情報をぎゅっと凝縮して戻します。この一連のプロセスを経ることで、各トークンは不要な情報が削ぎ落とされ、本質的で重要な特徴が強調された、より洗練され、かつ表現力豊かなベクトルへと生まれ変わることができるのです。
FFN内部での表現空間の変換イメージ
テキストベースの図
入力トークンベクトル x (d_model次元: 例 512次元の「比較的狭い」空間)
│
▼
[第1層線形変換 W_1] (d_model → d_ff次元へ「拡張」)
│
▼
中間表現 h (d_ff次元: 例 2048次元の「非常に広い」作業空間)
│ ← この広い空間でなら、複雑な特徴も扱いやすい!
▼
[非線形活性化関数 (ReLU, GeLUなど)] (ここで情報の「彫刻」が行われる)
│
▼
活性化後の中間表現 h' (d_ff次元: 彫刻された情報)
│
▼
[第2層線形変換 W_2] (d_ff → d_model次元へ「縮小・凝縮」)
│
▼
出力トークンベクトル FFN(x) (d_model次元: 洗練され、意味が深化した表現)

4. FFNの効果:トークン表現の「覚醒」と「洗練」 – 抽象化と強化のプロセス
さて、前のセクションでは、FFN(Feed-Forward Network)が2層のMLPと非線形活性化関数という、一見シンプルな道具立てでありながら、各トークンに対して個別の「集中治療」とも言える処理を施す様子を垣間見ましたね。では、その「治療」や「個別指導」の結果として、Attention層からバトンを受け取ったトークンたちは、具体的にどのように「健康に」、つまりより賢く、より表現力豊かに変身を遂げるのでしょうか? FFNがもたらすその素晴らしい効果は、主に「表現の抽象化」と「表現の強化・フィルタリング」という二つの大きな側面から捉えることができると思います。
表現の抽象化:具体的な情報から、より本質的な「概念」へ
まず一つ目の効果、「表現の抽象化」について考えてみましょう。Attention機構は、各トークンに対して周囲の文脈情報を集め、そのトークンがその文脈の中でどのような位置づけにあるのかを教えてくれました。これは非常に重要ですが、多くの場合、それはまだ具体的な情報のレベルに留まっているかもしれません。FFNは、この文脈情報を豊富に含んだトークン表現をさらに処理することで、それらをより高次の、つまりより抽象的な概念や特徴を捉えた表現へと進化させる手助けをするのです。
医療の現場を例にとってみましょう。Attentionが、ある患者さんの電子カルテの中から「昨日から38.5℃の発熱が続いている」「検査結果でCRP値が15.2mg/dLと高い」「血液検査での白血球数が18000/μLに上昇している」といった個々の具体的な情報(これらがそれぞれ文脈を考慮されたトークン表現だとします)を関連付けてきたとします。これらの情報は一つ一つが大切な手がかりですが、FFNはこれらの情報を個別に、しかしその関連性を踏まえた上でさらに深く処理することで、それぞれのトークンが持つベクトル表現の中に、例えば「これは“急性炎症反応”が強く示唆されるパターンである」とか、「もしかしたら“細菌感染症”の可能性が高い」といった、より診断や病態理解に直結するような、一段レベルの高い、抽象化された意味合いを埋め込む働きをするのです。
あるいは、医学論文をAIが読んでいるとしましょう。論文中に「Aという遺伝子の発現量が通常より上昇している」「Bというタンパク質がリン酸化(活性化の一つの形ですね)されている」「Cという種類の細胞が増殖を始めている」といった複数の記述があったとします。Attentionがこれらの記述間の関連性を見抜いた後、FFNがそれぞれの記述(のベクトル表現)を処理することで、これらがバラバラの事象ではなく、「特定の細胞内シグナル伝達経路が活性化している」という、より大きな生物学的なストーリーやメカニズムの一部としてAIに認識されるようになる、といった具合です。
FFNは、各トークンが持つ具体的な情報から、より本質的で、より包括的な「意味」や「概念」を巧みに引き出すお手伝いをしている、とイメージできるのではないでしょうか。
表現の強化とフィルタリング:重要な情報を際立たせ、ノイズを抑える
FFNがもたらすもう一つの重要な効果は、「表現の強化とフィルタリング」です。FFNは、トークンが持つ情報をただ抽象化するだけでなく、その過程で「磨きをかける」作業も行います。具体的には、現在の文脈や、モデルが最終的に解こうとしているタスク(例えば特定の疾患を分類するなど)にとって特に重要な情報を「強化」し、逆に関係の薄い情報やノイズのような余計な情報を「抑制」する、そんな賢いフィルタリング機能も期待できるのです。
この巧妙なフィルタリングの秘密の一端は、やはりFFN内の非線形活性化関数(例えばReLU関数)が持つ「ゲート」のような働きに隠されています。前のセクションで、ReLU関数が入力値に応じて情報を「通す/通さない」を判断するスイッチのようだとお話ししましたね。FFNは、このスイッチのオン・オフを、学習を通じて獲得した重み(\(W_1, W_2, b_1, b_2\))に基づいて巧みにコントロールします。その結果、Attentionが集めてきた様々な情報の中から、「これは今の文脈、そして最終的にAIが達成すべきゴールにとって、絶対に聞き逃せない重要なシグナルだ!」と判断された特徴はさらに力強く増幅され、一方で「うーん、この情報はちょっと今の話とは関係ないかな…」「これはむしろ判断を惑わせるノイズになるかもしれない」と判断された特徴は、そっとその影響力が抑えられるのです。
その結果として何が起こるかというと、各トークンのベクトル表現は、まるで不要な枝葉が丁寧に取り除かれ、栄養が本当に大切な果実だけに集中するように、より「味が濃く」、そして後続の処理(例えば、Transformerモデル内のさらに深い層にある別のAttentionブロックや、最終的な分類や生成タスクのための出力層など)にとって、より識別しやすく、より扱いやすい、まさに「研ぎ澄まされた」情報へと生まれ変わるのです。
まとめ:FFNはトークンにとっての「内省と自己変革」のステージ
このように見てくると、FFNは、Attentionという名の非常に優秀な情報収集家兼ネットワーカーが、世界中から集めてきてくれた貴重な情報(文脈を豊かにまとった各トークンの表現)を、一つ一つ丁寧に吟味し、磨き上げ、そしてそれぞれの情報が秘めている真の価値を最大限に引き出す「熟練の鑑定士」であり、またある時は「自己啓発を促すメンター」のような、奥深い役割を果たしていると言えるのではないでしょうか。
もし、Attention機構が「トークンが他者(他のトークン)との関係性の中で自分自身を理解し、位置づける」プロセスだとすれば、FFNは「その周囲との関係性を踏まえた上で、今度は自分自身の内なる情報や可能性を深く掘り下げ、最大限に開花させる」プロセスと捉えることができるかもしれません。各トークンが、文脈という鏡に映し出された自分自身の姿(Attentionからの出力)を改めて見つめ直し、「私はこの文脈において、一体何者であり、どんな意味を、どんな強さで、どんな側面を主張すべきなのだろうか?」と、いわば深く“内省”し、その結果として自己の表現をより洗練させ、より力強いものへと変えていく…。FFNは、まさしく各トークンがそうした「自己変革」のプロセスを経験するための、非常に重要な「場」を提供しているのです。
このFFNによる「個の力」の徹底的な強化と洗練が、Attentionによる「関係性の把握」と両輪となって、Transformer全体の驚くほど高度な情報処理能力と、人間も納得するような賢い判断を支える、もう一つの大きな柱となっているわけですね。
5. PythonによるFFNの実装例(概念):コードで覗くFFNの舞台裏
さて、ここまでFFNの構造や、それが持つ非線形変換の魔法についてお話ししてきました。「理屈はなんとなく分かったけれど、実際にプログラムとして動いているところをイメージするのは難しいなあ…」と感じている方もいらっしゃるかもしれませんね。百聞は一見に如かず、百見は一触に如かず…というわけで、このセクションでは、FFNがPythonのコードとしてどのように表現され、どのように機能するのか、その骨組みをPyTorchというライブラリを使って一緒に覗いてみることにしましょう!
PyTorchは、ディープラーニングの研究や開発で広く使われている強力なツールの一つです。Pythonの文法に比較的近いため、プログラミング経験がそれほど多くない方にとっても、比較的取り組みやすいかもしれません。もちろん、ここでの目標はプログラミングの達人になることではなく、FFNの「動きのイメージ」を掴むことです。ですから、PythonやPyTorchにまだあまり馴染みのない方も、どうぞ肩の力を抜いて、各コードに添えられたコメントを頼りに、FFNがデータを処理していく雰囲気だけでも感じ取っていただければ嬉しいです。
では、早速FFNの設計図とも言えるクラス定義から見ていきましょう。
import torch # PyTorchライブラリをインポートします。「torch」という名前で使えるようになります。
import torch.nn as nn # PyTorchのニューラルネットワーク関連モジュール(nn)をインポート。「nn」という別名で使います。
# FFNの構造を定義するクラスを作成します。nn.Moduleという「設計図の親玉」を継承します。
class PositionwiseFeedForward(nn.Module):
def __init__(self, d_model, d_ff, dropout=0.1):
"""
FFNの部品を準備する場所 (コンストラクタと言います)
このFFNモジュールが作られる時に一度だけ呼ばれます。
Args:
d_model (int): FFNの入力と出力のベクトルの次元数です。
Transformerモデル全体で統一された基本の次元(例: 512)です。
d_ff (int): FFN内部の中間層(隠れ層)のベクトルの次元数です。
通常、d_modelの4倍程度に設定されます(例: 512 * 4 = 2048)。
情報を一時的に広げるための「作業スペース」の広さと考えられます。
dropout (float): ドロップアウト率。学習中に一部の接続をランダムに「オフ」にする割合です。
過学習(訓練データにだけ強くて未知のデータに弱い状態)を防ぐためのおまじないです。
"""
super(PositionwiseFeedForward, self).__init__() # 親クラスであるnn.Moduleの初期化処理をまず呼び出します (お作法です)
# 第1の全結合層 (Linear layer) を定義します。
# 入力次元d_modelのベクトルを、中間次元d_ffのベクトルへと線形変換します。
# これが数式の xW_1 + b_1 に相当します。
self.linear1 = nn.Linear(d_model, d_ff) # 部品名「linear1」として準備
# 第2の全結合層 (Linear layer) を定義します。
# 中間次元d_ffのベクトルを、出力次元d_modelのベクトルへと線形変換します。
# これが数式の (... )W_2 + b_2 の ( )W_2 + b_2 の部分に相当します。
self.linear2 = nn.Linear(d_ff, d_model) # 部品名「linear2」として準備
# 非線形活性化関数を準備します。ここではReLU (Rectified Linear Unit) を使います。
# 入力が0以下なら0、0より大きければそのまま出力する、というシンプルな関数です。
self.relu = nn.ReLU()
# 最近のモデルではGeLU (Gaussian Error Linear Unit) もよく使われます。
# self.activation = nn.GELU() のように書けばGeLUを使えます。
# ドロップアウト層を準備します。
# 指定された確率(dropout)で、一部のニューロンの出力を0にします(学習時のみ)。
self.dropout = nn.Dropout(dropout)
def forward(self, x):
"""
FFNにデータが入力されたときの、実際の計算の流れを定義する場所 (順伝播処理)
Args:
x (torch.Tensor): FFNへの入力テンソル。
形状は [バッチサイズ, シーケンス長, d_model] を想定しています。
バッチサイズ: 一度に処理する文章(やデータ)の数
シーケンス長: 各文章のトークン(単語など)の数
d_model: 各トークンのベクトル表現の次元数
Returns:
torch.Tensor: FFNからの出力テンソル。入力と同じ形状 [バッチサイズ, シーケンス長, d_model] です。
"""
# 1. 第1層の線形変換を適用し、その後ReLU活性化関数を通します。
# x の形状: [バッチサイズ, シーケンス長, d_model]
# self.linear1(x) の出力形状: [バッチサイズ, シーケンス長, d_ff] (次元がd_ffに拡張される)
# self.relu(...) の出力形状: [バッチサイズ, シーケンス長, d_ff] (形状は変わらず、値が非線形変換される)
out = self.relu(self.linear1(x))
# 2. ドロップアウトを適用します (中間層の活性化後に対して)。
# これは主に学習の安定化や過学習防止のためで、推論時には通常何もしません。
# out の形状: [バッチサイズ, シーケンス長, d_ff] (形状は変わらない)
out = self.dropout(out)
# 3. 第2層の線形変換を適用します。
# self.linear2(out) の出力形状: [バッチサイズ, シーケンス長, d_model] (次元がd_modelに戻る)
out = self.linear2(out)
return out # 最終的な出力テンソルを返します
# --- FFNの動作テスト (ここからは、上で定義したFFNクラスを実際に使ってみるお試しコードです) ---
# まず、モデルのパラメータ(次元数など)を仮に設定してみましょう。
d_model = 512 # Transformerモデルでよく使われる基本のベクトル次元数
d_ff = 2048 # FFNの中間層の次元数。d_modelの4倍 (512 * 4 = 2048) にすることが多いです。
batch_size = 2 # バッチサイズ。ここでは仮に2つの異なるデータ(例: 2つの短い医療メモ)を同時に処理するとします。
seq_len = 10 # シーケンス長。各医療メモが10個のトークン(単語など)で構成されているとします。
# 上で定義した PositionwiseFeedForward クラスのインスタンス(実体)を作成します。
# これで、d_model=512, d_ff=2048 の設定を持つFFNレイヤーが一つ準備できました。
ffn_layer = PositionwiseFeedForward(d_model, d_ff)
# FFNに入力するためのダミーデータ(お試し用のランダムな数値データ)を作成します。
# これは、前のステップであるAttention層から出力されたトークン表現だと仮定しましょう。
# torch.randn() は、平均0、分散1の正規分布に従う乱数を生成します。
# 形状は (バッチサイズ, シーケンス長, d_model) にします。
dummy_input = torch.randn(batch_size, seq_len, d_model)
print(f"FFNへの入力テンソルの形状: {dummy_input.shape}") # f-stringという書き方で、変数の中身を文字と一緒に出力
# 作成したFFNレイヤー (ffn_layer) に、ダミーの入力データ (dummy_input) を渡して、
# FFNの処理(forwardメソッドの計算)を実行し、その結果(出力テンソル)を得ます。
output_tensor = ffn_layer(dummy_input)
print(f"FFNからの出力テンソルの形状: {output_tensor.shape}")
# 注目ポイント:出力テンソルの形状が、入力テンソルの形状と全く同じになっていることを確認しましょう。
# (バッチサイズ, シーケンス長, d_model) → (バッチサイズ, シーケンス長, d_model)
# これは、FFNがシーケンス内の各トークンベクトルを「その場で(position-wiseに)」
# 個別に処理し、ベクトルの内容は更新するものの、全体の構造やトークンごとの次元数は
# 変えずに情報を質的に変換・深化させている、という特徴をよく表していますね。
Pythonコードの実行結果(例):
FFNへの入力テンソルの形状: torch.Size([2, 10, 512])
FFNからの出力テンソルの形状: torch.Size([2, 10, 512])
コードのポイントを振り返ってみましょう:
class PositionwiseFeedForward(nn.Module): これは、PyTorchで独自のニューラルネットワーク部品(モジュール)を作るためのお決まりの書き方です。nn.Moduleという、いわば「部品の設計図の親玉」のようなものを「継承」して、自分だけのFFN部品を作っているイメージです。__init__(self, d_model, d_ff, dropout=0.1): この部分は、FFNという部品が「製造」されるときに一度だけ実行される「初期設定」の工程です。ここで、FFNが内部で使うさらに細かい部品たち(2つの線形変換層、1つのReLU活性化関数、1つのドロップアウト層)を、あらかじめ準備しておきます。self.linear1 = nn.Linear(d_model, d_ff): これが、数式で言う \(xW_1 + b_1\) の計算(バイアス \(b_1\) も内部で自動的に扱われます)を担当する「第一の線形変換エンジン」です。入力ベクトルを \(d_{model}\) 次元から \(d_{ff}\) 次元へと広げます。self.relu = nn.ReLU(): これが、情報を非線形に「曲げる」役割のReLU活性化関数です。GeLUを使いたい場合は、self.activation = nn.GELU()のように定義します。self.dropout = nn.Dropout(dropout): ドロップアウトは、学習中に一部の神経細胞(ニューロン)の働きをランダムにお休みさせることで、モデルが一つの情報経路に頼りすぎるのを防ぎ、より頑健で未知のデータにも強い(汎化性能が高い)モデルを作るための一種の訓練テクニックです。風邪をひかないように普段から色々な栄養を摂るのに似ているかもしれませんね。self.linear2 = nn.Linear(d_ff, d_model): こちらは「第二の線形変換エンジン」で、\(d_{ff}\) 次元に広がった情報を、再び元の \(d_{model}\) 次元へと戻す役割を担います。
forward(self, x): この部分は、FFN部品に実際にデータ(入力テンソル \(x\))が「流れ込んできた」ときに、どのような順番で、どのような計算処理を行うかを定義しています。まさにFFNの「仕事の手順書」ですね。out = self.relu(self.linear1(x)): まず、入力xを第一の線形変換エンジンに通し、その結果をすぐにReLU活性化関数で処理します。これで情報が拡張され、かつ非線形性が与えられます。out = self.dropout(out): 次に、活性化された情報に対してドロップアウトを適用します(これは主にモデルの訓練中に効果を発揮します)。out = self.linear2(out): 最後に、ドロップアウトを経た情報を第二の線形変換エンジンに通し、最終的な出力とします。
- 動作テストとその結果が示すこと: コードの後半では、仮のパラメータ(
d_modelやd_ffなど)を設定し、ランダムな数値で作ったお試し用の入力データ(dummy_input)を、実際にFFNレイヤー(ffn_layer)に通していますね。そして、入力と出力のテンソルの「形状(shape)」を表示しています。注目すべきは、torch.Size([2, 10, 512])という形状が、入力から出力まで変わっていない点です。これは、FFNがバッチ内の各データ(2つ)、各データ内の各トークン(10個)に対して個別に作用し、それぞれのトークンベクトル(512次元)の内容を質的に変換(深化)させるものの、そのトークン自体の次元数を変えたり、トークンの数を変えたりはしない、という「Position-wise」な処理の性質を、非常によく示しています。各トークンが、自分自身の情報を「その場で」より豊かなものにしているイメージです。
このPythonコードは、FFNの最も基本的な構造と動作原理を理解するための一つのシンプルな例です。実際のTransformerモデル(例えば、有名なBERTやGPTなど)では、このFFNブロックの前後に、さらに「残差接続(Residual Connection)」や「層正規化(Layer Normalization)」といった、モデルの学習をより安定させ、より深い層構造の構築を可能にするための重要な「サポート部品」たちが組み合わさって使われています。これらの重要な脇役たちについては、本コースの後のセクション(22.6を予定しています)で、改めてじっくりとスポットライトを当てて解説する予定です。今はまず、FFNの核となるこの「2層のMLPによる非線形変換」という働きと、それが各トークンに対して個別に行われるという点を、しっかりと心に留めておいていただければと思います。
6. 医療分野におけるFFNの役割と示唆
6. 医療分野におけるFFNの役割と示唆:Attentionからの情報を「深化」させる力
さて、前のセクションまでで、Attention機構がトークン間の広大なネットワークの中から重要な関連性を見つけ出し、FFN(Feed-Forward Network)がそのバトンを受けて各トークンの情報を個別に、そして深く磨き上げる、というTransformer内部の見事な連携プレーについて見てきましたね。Attentionが「どの情報が関連しているか」というトークン同士の「横のつながり」を明らかにするのに対し、FFNはその結果を受けて、今度は各トークンが持つ情報を「縦に深く掘り下げる」ように、よりリッチで抽象的な意味合いへと処理していくのでした。
では、このFFNによる「個々の情報の意味を深く掘り下げる」という能力は、私たち医療者が日々向き合っている複雑な課題の解決や、未来の医療の発展に対して、具体的にどんな素敵な可能性を見せてくれるのでしょうか? 一緒にそのポテンシャルを探ってみましょう。
複雑な臨床的特徴量の抽出:患者さんの全体像をより鮮明に
日々の診療で向き合う患者さんのカルテには、症状の細やかな記述、時系列で変化する検査値、過去の投薬履歴や効果の有無など、本当に多様で膨大な情報が、時には断片的に、時には複雑に絡み合いながら記録されていますよね。Attention機構が、これらの情報の中から「お、この症状とあの検査値、そして以前のあの治療は、何か関連がありそうだぞ」と、重要な情報の糸をたぐり寄せてくれたとします。例えば、ある患者さんの記録から「ここ数週間、微熱が続いている」「首のリンパ節が少し腫れているようだ」「原因がはっきりしない体重減少が見られる」という3つの情報が、Attentionによって「これらは単なる偶然ではなく、何か共通の背景があるかもしれない」とピックアップされたとしましょう。
ここでFFNの出番です。FFNは、これらの(既にAttentionによって文脈的なつながりが示唆された)情報を、一つ一つ個別に、しかしその関連性を暗黙のうちに考慮しながら、さらに深く処理していきます。そして、「微熱が続く」というトークンには「単なる風邪とは異なる、持続性のある発熱」という質的な情報を、「リンパ節の軽度腫脹」には「全身性の反応を示唆する所見」というニュアンスを、そして「原因不明の体重減少」には「身体が何らかの消耗状態にあるサイン」という背景を、それぞれFFN内部の非線形変換を通じて、より強く意味づける手助けをするのです。その結果、AIはこれらの情報を統合し、「これはもしかしたら、単純な一過性の不調ではなく、より詳細な検査や鑑別診断が必要な潜在的な全身性疾患(例えば、自己免疫疾患や悪性腫瘍など)の初期兆候かもしれない」といった、個々の情報を超えた、より一段高いレベルでの臨床的な仮説形成や、重要な特徴の抽出に貢献するかもしれません。AIが、まるで経験豊かな臨床医のように、多角的な情報からより本質的な「病像」を捉えようと試みる、そんなイメージに近いかもしれませんね。
診断や予測の精度向上への貢献:データに隠された非線形な「物語」を読み解く
医療データ、特に人間の身体が示す反応や病気の進行というのは、本当に一筋縄ではいかないものです。検査値Aが少し高い、検査値Bも少し高い、というだけでは特に大きな問題とは見なされなくても、AとBが「同時に」、かつ「ある特定のバランスや比率で」高い場合に限って、非常に稀な、しかし重大な疾患Cのリスクが急上昇する…といった、単純な足し算や比例関係では到底説明できない「非線形な関係性」が、実は診断の鍵を握っていたり、治療効果を左右したりすることが少なくありません。
FFNが持つ強力な非線形変換能力は、まさにこうした複雑で捉えどころのないパターンを、膨大なデータの中から学習し、見つけ出すのにうってつけです。Attentionが関連する情報同士を結びつけた後、FFNがそれぞれの情報を非線形に処理することで、それらの情報が組み合わさった時に初めて現れる「創発的」とも言える特徴を捉えることができるようになるのです。これにより、従来の統計モデルや線形的なアプローチでは見逃されがちだった、より微妙で複雑な病気の兆候や、複数の要因が絡み合って生じる疾患の発症リスクなどをAIがより正確に捉え、結果として診断支援の精度が向上したり、個々の患者さんの将来の健康状態(予後)をよりきめ細かく予測したりすることに繋がる可能性があります。それは、病気の超早期発見や、より効果的で副作用の少ない予防戦略の立案に、大きな希望をもたらしてくれるかもしれませんね。
医学論文からの知識発見の深化:膨大な文献の「行間」を読むAIアシスタント
私たちの医療知識は、日々世界中で発表される無数の医学論文によって、絶えず更新され、深化しています。その中には、未来の医療を大きく変える可能性を秘めた、画期的な発見や新しい治療法のヒントが眠っているはずです。しかし、その情報量はまさに圧倒的。Attentionが、ある特定の研究テーマ(例えば「アルツハイマー病の新しい治療ターゲット」)に関連する論文群や、それらの論文中に頻出する重要なキーワード群(例えば「アミロイドβ」「タウタンパク質」「神経炎症」「マイクログリア」など)を結びつけてくれたとしましょう。
次にFFNが活躍します。FFNは、これらのキーワード(それぞれがAttentionによって文脈情報を与えられたベクトル表現になっています)や、それらを含む周囲の文脈のベクトル表現を、さらに深く、そして非線形に処理することで、個々のキーワードが持つ意味合いをより豊かに、そして相互の関係性をより精緻にしていきます。その結果、例えば「マイクログリアの特定の活性化状態が、アミロイドβの蓄積とタウタンパク質の病理的変化の間の、これまで見過ごされてきた重要なリンクになっている可能性があり、これが新たな治療介入のポイントになるかもしれない」といった、単なるキーワードの共起や表面的な関連性を超えた、より深いレベルでの仮説や、これまで繋がっていなかった知識の断片同士の「ミッシングリンク」をAIが示唆し、研究者に新たな視点や実験のインスピレーションを与えてくれるかもしれません。まるで、AIが非常に博識で、かつ独創的な思考を持つ研究パートナーとして、膨大な論文の行間に隠された真実を読み解き、新たな発見の「種」を見つけ出してくれる。そんな頼もしい存在になってくれるかもしれませんね。
個別化医療への布石:一人ひとりの患者さんに最適な「オーダーメイド医療」を目指して
私たちの誰もが、遺伝的な背景も、日々の生活習慣も、そして病気に対する反応や薬の効き方も、驚くほど一人ひとり異なります。そんな個々人の違いをきめ細かく考慮し、それぞれの患者さんにとって本当に最適な医療を提供する「個別化医療(Personalized Medicine)」の実現は、現代医学が目指す大きな目標の一つですよね。
考えてみてください。患者さん一人ひとりの詳細なゲノム情報、日々の活動量や睡眠パターンを記録したウェアラブルデバイスからの膨大なセンサーデータ、詳細な食生活の記録、過去の全ての治療歴とその効果、さらには生活環境や心理社会的背景…。これらの膨大かつ多様な情報(これらが適切にトークン化され、Attentionによって相互の重要な関連性が明らかにされたとします)を、FFNが個別に、かつ深く処理することで、それぞれの情報がその特定の患者さん特有の複雑な文脈の中で持つ「真の意味」や「重み」を、より精緻に、よりパーソナルな形で捉えることができるようになるでしょう。その結果、最終的にその患者さんにとって本当に最適な治療法の選択(例えば、どの抗がん剤が最も効果的で副作用が少ないか)、副作用を最小限に抑えるための薬剤の組み合わせの提案、あるいは将来の特定の疾患への罹患リスクを効果的に低減するための、その人だけの生活習慣改善プランの策定といった、真の個別化医療を実現するための、より質の高く、よりパーソナライズされた特徴量をAIが生成する強力な基盤となることが期待されます。FFNは、まさにそのための「精密な情報部品」作りに、見えないところで貢献しているのです。
このように、FFNはTransformerモデルの中で、Attentionが巧みに捉えてきたトークン間の「関連性」という情報を、今度は各トークンがそれぞれに持つ「意味」という、より深く、より本質的な次元へと昇華させるための、まるで魔法の触媒のような、非常に重要な役割を果たしているのです。
その働きは、Attentionの華々しい連携プレーの陰に隠れて、一見すると少し地味に見えるかもしれません。しかし、FFNによるこの地道で、かつ各トークンに個別最適化された「意味の深化」作業こそが、Transformer全体の高い表現力と、時には人間を唸らせるほどの賢い性能を陰で力強く支える、まさに「なくてはならない存在」と言えるのではないでしょうか。AIがただ情報を繋ぎ合わせるだけでなく、その情報を真に「理解」し、新たな価値を生み出す方向へと近づけるための、静かながらも非常にパワフルな内部エンジン、それがFFNなのです。
7. まとめと次へのステップ
今回は、TransformerモデルにおけるFFN(Feed-Forward Network)、特にPosition-wise Feed-Forward Networkがなぜ必要なのか、そしてそれがどのようにしてトークン表現の意味を深化させるのかについて掘り下げてきました。
FFNは、Attention層から出力された文脈情報をリッチに含んだ各トークン表現に対して、2層のMLPによる非線形変換を独立に施すことで、表現をより抽象的で強力なものへと進化させる役割を担っていることをご理解いただけたかと思います。線形的な処理が主体のAttention機構に対し、FFNが非線形性という「魔法の杖」を振るうことで、モデル全体の表現力が格段に向上し、より複雑なデータパターンを学習できるようになるのです。
まさに、Attentionが「全体を見て、どこに注目すべきか」という大局的な判断を下すのに対し、FFNは「注目した個々の情報を、どう解釈し、どう意味付けるか」という局所的かつ深い思考を促す、という絶妙な分業体制がTransformerの強みの一つと言えるでしょう。
さて、こうしてAttentionとFFNによって磨き上げられたトークン表現は、次にどのように使われていくのでしょうか?特に、Transformerが文章を生成するようなタスク(Decoderの役割)では、これらのリッチな表現から、実際に次に来るべき単語を選び出し、出力していく必要があります。
次回(22.5 Transformer Decoderモデルにおける出力生成の仕組み)は、いよいよTransformerがどのようにして具体的な「言葉」を生み出すのか、その出力生成のメカニズムに焦点を当てます。出力ベクトルがどのようにして個々の単語の確率(logits)に変換され、Softmax関数を経て、最終的にargmaxやサンプリングといった方法で単語が選択されるのか、そしてそれが自己回帰的に繰り返される様子など、興味深いトピックが満載です。
本日のFFNに関する知識が、Transformerという巨大な知性の仕組みを理解する上での、また一つ重要なピースとなれば幸いです。
8. 参考文献
- Vaswani A, Shazeer N, Parmar N, Uszkoreit J, Jones L, Gomez AN, et al. Attention is all you need. In: Advances in Neural Information Processing Systems 30 (NIPS 2017). Curran Associates, Inc.; 2017. p. 5998-6008.
- Devlin J, Chang MW, Lee K, Toutanova K. BERT: Pre-training of deep bidirectional transformers for language understanding. In: Proceedings of the 2019 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies, Volume 1 (Long and Short Papers). Minneapolis, Minnesota: Association for Computational Linguistics; 2019. p. 4171-4186. (BERTモデルでもFFNはTransformer Encoderの重要な構成要素です)
- Ramachandran P, Zoph B, Le QV. Searching for activation functions. arXiv preprint arXiv:1710.05941. 2017 Oct 16. (GeLU活性化関数に関する論文)
- Hendrycks D, Gimpel K. Gaussian error linear units (GeLUs). arXiv preprint arXiv:1606.08415. 2016 Jun 27. (GeLU活性化関数に関する論文)
- Brown T, Mann B, Ryder N, Subbiah M, Kaplan JD, Dhariwal P, et al. Language models are few-shot learners. In: Advances in Neural Information Processing Systems 33 (NeurIPS 2020). Curran Associates, Inc.; 2020. p. 1877-1901. (GPT-3モデルにおけるTransformerのFFNの役割を示唆)
ご利用規約(免責事項)
当サイト(以下「本サイト」といいます)をご利用になる前に、本ご利用規約(以下「本規約」といいます)をよくお読みください。本サイトを利用された時点で、利用者は本規約の全ての条項に同意したものとみなします。
第1条(目的と情報の性質)
- 本サイトは、医療分野におけるAI技術に関する一般的な情報提供および技術的な学習機会の提供を唯一の目的とします。
- 本サイトで提供されるすべてのコンテンツ(文章、図表、コード、データセットの紹介等を含みますが、これらに限定されません)は、一般的な学習参考用であり、いかなる場合も医学的な助言、診断、治療、またはこれらに準ずる行為(以下「医行為等」といいます)を提供するものではありません。
- 本サイトのコンテンツは、特定の製品、技術、または治療法の有効性、安全性を保証、推奨、または広告・販売促進するものではありません。紹介する技術には研究開発段階のものが含まれており、その臨床応用には、さらなる研究と国内外の規制当局による正式な承認が別途必要です。
- 本サイトは、情報提供を目的としたものであり、特定の治療法を推奨するものではありません。健康に関するご懸念やご相談は、必ず専門の医療機関にご相談ください。
第2条(法令等の遵守)
利用者は、本サイトの利用にあたり、医師法、医薬品、医療機器等の品質、有効性及び安全性の確保等に関する法律(薬機法)、個人情報の保護に関する法律、医療法、医療広告ガイドライン、その他関連する国内外の全ての法令、条例、規則、および各省庁・学会等が定める最新のガイドライン等を、自らの責任において遵守するものとします。これらの適用判断についても、利用者が自ら関係各所に確認するものとし、本サイトは一切の責任を負いません。
第3条(医療行為における責任)
- 本サイトで紹介するAI技術・手法は、あくまで研究段階の技術的解説であり、実際の臨床現場での診断・治療を代替、補助、または推奨するものでは一切ありません。
- 医行為等に関する最終的な判断、決定、およびそれに伴う一切の責任は、必ず法律上その資格を認められた医療専門家(医師、歯科医師等)が負うものとします。AIによる出力を、資格を有する専門家による独立した検証および判断を経ずに利用することを固く禁じます。
- 本サイトの情報に基づくいかなる行為によって利用者または第三者に損害が生じた場合も、本サイト運営者は一切の責任を負いません。実際の臨床判断に際しては、必ず担当の医療専門家にご相談ください。本サイトの利用によって、利用者と本サイト運営者の間に、医師と患者の関係、またはその他いかなる専門的な関係も成立するものではありません。
第4条(情報の正確性・完全性・有用性)
- 本サイトは、掲載する情報(数値、事例、ソースコード、ライブラリのバージョン等)の正確性、完全性、網羅性、有用性、特定目的への適合性、その他一切の事項について、何ら保証するものではありません。
- 掲載情報は執筆時点のものであり、予告なく変更または削除されることがあります。また、技術の進展、ライブラリの更新等により、情報は古くなる可能性があります。利用者は、必ず自身で公式ドキュメント等の最新情報を確認し、自らの責任で情報を利用するものとします。
第5条(AI生成コンテンツに関する注意事項)
本サイトのコンテンツには、AIによる提案を基に作成された部分が含まれる場合がありますが、公開にあたっては人間による監修・編集を経ています。利用者が生成AI等を用いる際は、ハルシネーション(事実に基づかない情報の生成)やバイアスのリスクが内在することを十分に理解し、その出力を鵜呑みにすることなく、必ず専門家による検証を行うものとします。
第6条(知的財産権)
- 本サイトを構成するすべてのコンテンツに関する著作権、商標権、その他一切の知的財産権は、本サイト運営者または正当な権利を有する第三者に帰属します。
- 本サイトのコンテンツを引用、転載、複製、改変、その他の二次利用を行う場合は、著作権法その他関連法規を遵守し、必ず出典を明記するとともに、権利者の許諾を得るなど、適切な手続きを自らの責任で行うものとします。
第7条(プライバシー・倫理)
本サイトで紹介または言及されるデータセット等を利用する場合、利用者は当該データセットに付随するライセンス条件および研究倫理指針を厳格に遵守し、個人情報の匿名化や同意取得の確認など、適用される法規制に基づき必要とされるすべての措置を、自らの責任において講じるものとします。
第8条(利用環境)
本サイトで紹介するソースコードやライブラリは、執筆時点で特定のバージョンおよび実行環境(OS、ハードウェア、依存パッケージ等)を前提としています。利用者の環境における動作を保証するものではなく、互換性の問題等に起因するいかなる不利益・損害についても、本サイト運営者は責任を負いません。
第9条(免責事項)
- 本サイト運営者は、利用者が本サイトを利用したこと、または利用できなかったことによって生じる一切の損害(直接損害、間接損害、付随的損害、特別損害、懲罰的損害、逸失利益、データの消失、プログラムの毀損等を含みますが、これらに限定されません)について、その原因の如何を問わず、一切の法的責任を負わないものとします。
- 本サイトの利用は、学習および研究目的に限定されるものとし、それ以外の目的での利用はご遠慮ください。
- 本サイトの利用に関連して、利用者と第三者との間で紛争が生じた場合、利用者は自らの費用と責任においてこれを解決するものとし、本サイト運営者に一切の迷惑または損害を与えないものとします。
- 本サイト運営者は、いつでも予告なく本サイトの運営を中断、中止、または内容を変更できるものとし、これによって利用者に生じたいかなる損害についても責任を負いません。
第10条(規約の変更)
本サイト運営者は、必要と判断した場合、利用者の承諾を得ることなく、いつでも本規約を変更することができます。変更後の規約は、本サイト上に掲載された時点で効力を生じるものとし、利用者は変更後の規約に拘束されるものとします。
第11条(準拠法および合意管轄)
本規約の解釈にあたっては、日本法を準拠法とします。本サイトの利用および本規約に関連して生じる一切の紛争については、東京地方裁判所を第一審の専属的合意管轄裁判所とします。
For J³, may joy follow you.

