Neural Turing Machine(NTM)完全ガイド:AIが「メモ帳」を使って考える仕組み
はじめに
**Neural Turing Machine(NTM、ニューラル・チューリング・マシン)**は、2014年にDeepMind社(『AlphaGo』を作った会社)が発表した革命的なAIアーキテクチャです。
一言で言うと、**「ニューラルネットワークに外部メモリ(メモ帳)を持たせて、読み書きできるようにしたもの」**です。
なぜNTMが必要だったのか?
従来のニューラルネットワークの問題
まず、NTM以前のニューラルネットワークの限界を理解しましょう。
例:人間が暗算で計算する場合
問題: 27 × 34 = ?
あなたの頭の中:
「えーと、7×4=28、2を覚えて...」
「次に7×3=21に2を足して23、3を覚えて...」
「あれ、さっきの数字なんだっけ?」
人間でも暗算には限界があります。それは脳のワーキングメモリ(作業記憶)が限られているからです。
従来のニューラルネットワークも同じ問題を抱えていました:
入力 → [ニューラルネットワーク] → 出力
(固定サイズの内部状態)
- 内部状態のサイズは固定
- 複雑な計算の途中結果を覚えておけない
- 長い系列データの処理が苦手
人間はどう解決しているか?
人間は複雑な計算をするとき、紙とペンを使います!
27
× 34
----
108 (27 × 4)
810 (27 × 3, 一桁左にシフト)
----
918
メモ:
- 繰り上がり: 2, 3
- 途中結果: 108, 810
これが「外部メモリ」の本質です。脳の限界を、外部の記録媒体で補うのです。
チューリングマシンとは?
NTMを理解するには、まずチューリングマシンを知る必要があります。
チューリングマシンの基本構造
アラン・チューリングが1936年に提案した理論上の計算機です。
[読み書きヘッド]
↓
[... |a|b|c|d|e| ...] ← 無限に長いテープ(メモリ)
↑
現在の位置
構成要素:
- 無限に長いテープ: 情報を書き込める
- 読み書きヘッド: テープを読んだり書いたりする
- 状態レジスタ: 現在の状態を記憶
- 命令テーブル: 「この状態でこの記号を見たら、こうする」というルール
基本動作:
1. 現在の位置のテープを読む
2. 状態と読んだ記号に基づいて:
- 新しい記号を書く
- ヘッドを左か右に移動
- 状態を変更する
3. 繰り返す
簡単な例:二進数の加算
初期状態: テープに "101" と "011" が書かれている
目標: 足し算の結果 "1000" を得る
ステップ1: 右端から読む (1 + 1 = 10)
→ "0"を書いて、繰り上がり"1"を記憶
ステップ2: 次の桁 (0 + 1 + 繰り上がり1 = 10)
→ "0"を書いて、繰り上がり"1"を記憶
ステップ3: 次の桁 (1 + 0 + 繰り上がり1 = 10)
→ "0"を書いて、繰り上がり"1"を記憶
ステップ4: 最後の繰り上がり
→ "1"を書く
結果: "1000"
チューリングマシンの重要性
チューリングマシンは計算可能性の基礎です:
チューリングの定理: アルゴリズムで計算できるものは、すべてチューリングマシンで計算できる
つまり、どんなコンピュータでも、理論的にはチューリングマシンと同じことしかできません。
Neural Turing Machineの誕生
発想:「ニューラルネットワーク + チューリングマシン」
DeepMindの研究者たちは考えました:
「チューリングマシンのように外部メモリを使えて、しかもニューラルネットワークのように学習できるシステムを作れないか?」
これがNTMの出発点です。
NTMの全体構造
[コントローラ]
(ニューラルネットワーク)
↓
読み書きの制御信号を出力
↓
┌─────────────────┐
│ メモリマトリックス │
│ [行1: 0.2, 0.5, ...] │
│ [行2: 0.1, 0.9, ...] │
│ [行3: 0.7, 0.3, ...] │
│ ... │
└─────────────────┘
↑
読み取った内容を入力として受け取る
↓
[コントローラ]
主要コンポーネント:
- コントローラ: 通常のニューラルネットワーク(LSTM、FFNNなど)
- メモリマトリックス: 情報を保存する場所(N行 × M列の行列)
- 読み取りヘッド: メモリから情報を読む
- 書き込みヘッド: メモリに情報を書く
NTMの革新的な仕組み
1. メモリマトリックス
従来のチューリングマシンと違い、NTMのメモリは行列です。
メモリ = N個の場所 × M次元のベクトル
例: 100個の場所 × 50次元
[
[0.2, 0.5, 0.1, ..., 0.8], ← メモリ位置1
[0.7, 0.1, 0.9, ..., 0.3], ← メモリ位置2
[0.4, 0.6, 0.2, ..., 0.5], ← メモリ位置3
...
[0.1, 0.3, 0.7, ..., 0.9] ← メモリ位置100
]
各メモリ位置には、複数の数値(ベクトル)を保存できます。
2. 注目重み(Attention Weights):NTMの核心
ここがNTMの最も革新的な部分です!
従来のチューリングマシンは「位置3を読む」のように離散的でしたが、NTMはすべての位置を確率的に読み書きします。
注目重み(Attention Weights)の例:
メモリ位置: 1 2 3 4 5
読み取り重み: [0.1, 0.05, 0.7, 0.1, 0.05]
↑
ここに最も注目
読み取り動作:
読み取り結果 = Σ(重み[i] × メモリ[i])
= 0.1 × [0.2, 0.5, ...] +
0.05 × [0.7, 0.1, ...] +
0.7 × [0.4, 0.6, ...] + ← 主にこれが読まれる
0.1 × [0.1, 0.3, ...] +
0.05 × [0.9, 0.2, ...]
= [0.35, 0.49, ...] ← これが読み取り結果
なぜこれが重要?
- 微分可能: すべての操作が滑らかなので、勾配降下法で学習できる!
- ソフトな選択: 複数の場所を同時に参照できる
- 曖昧さを許容: 「だいたいこの辺」という柔軟な読み書きが可能
3. アドレッシング機構(Addressing Mechanisms)
「どのメモリ位置に注目するか」を決める仕組みです。NTMには2種類のアドレッシングがあります。
(A) コンテンツベース・アドレッシング
「似ている内容を探す」方法
探したい内容: [0.5, 0.3, 0.8]
メモリ:
位置1: [0.4, 0.2, 0.7] ← 類似度: 0.95
位置2: [0.9, 0.1, 0.1] ← 類似度: 0.3
位置3: [0.5, 0.3, 0.8] ← 類似度: 1.0 (完全一致!)
位置4: [0.1, 0.9, 0.2] ← 類似度: 0.2
→ 位置3に最も高い重みを割り当てる
計算方法(コサイン類似度):
類似度 = (キー · メモリ[i]) / (||キー|| × ||メモリ[i]||)
鋭さパラメータβで集中度を調整:
重み[i] = exp(β × 類似度[i]) / Σ exp(β × 類似度[j])
β = 1: 柔らかい分布
β = 10: 鋭い集中
(B) ロケーションベース・アドレッシング
「前回の位置を基準に移動する」方法
これにより、順序的なアクセス(リストを順番に読むなど)が可能になります。
3つのメカニズム:
1. Interpolation(補間):
コンテンツベースとロケーションベースを混ぜる
新しい重み = g × コンテンツベース重み + (1-g) × 前回の重み
g = 1.0: 完全にコンテンツベース
g = 0.0: 完全に前回の位置
g = 0.5: 半々
2. Convolutional Shift(畳み込みシフト):
重みを左右にシフトする
シフト前: [0.1, 0.1, 0.7, 0.1, 0.0]
↑
シフト分布: [-1: 0.1, 0: 0.8, +1: 0.1]
(左へ そのまま 右へ)
シフト後: [0.08, 0.18, 0.57, 0.15, 0.02]
↑ 少し右に動いた
これにより「次の位置」「前の位置」に移動できます。
3. Sharpening(鋭化):
注目を一点に集中させる
シャープ前: [0.2, 0.3, 0.3, 0.2] ← 分散している
γ = 3で鋭化
シャープ後: [0.08, 0.33, 0.33, 0.26] ← より集中
4. 読み取りと書き込み
読み取り(Read)
シンプルです:
読み取りベクトル = Σ(重み[i] × メモリ[i])
複数の読み取りヘッドを持つことも可能です。
書き込み(Write)
書き込みは2段階で行われます:
ステップ1: Erase(消去)
消去ベクトル e = [0.9, 0.1, 0.5, ...] ← どれくらい消すか
各メモリ位置について:
メモリ[i] = メモリ[i] × (1 - 重み[i] × e)
例:
重み[3] = 0.8, e = [1.0, 0.0, 1.0, ...]
メモリ[3] = [0.5, 0.7, 0.3, ...]
新しいメモリ[3] = [0.5×(1-0.8×1.0), 0.7×(1-0.8×0.0), 0.3×(1-0.8×1.0), ...]
= [0.1, 0.7, 0.06, ...]
↑ 80%消去 ↑ そのまま ↑ 80%消去
ステップ2: Add(追加)
追加ベクトル a = [0.6, 0.3, 0.9, ...] ← 何を書くか
各メモリ位置について:
メモリ[i] = メモリ[i] + 重み[i] × a
この2段階方式により、選択的に情報を更新できます。
NTMの具体的な動作例
タスク:数列のコピー
入力: [3, 1, 4, 1, 5]
出力: [3, 1, 4, 1, 5] ← 入力と同じ
NTMの動作:
フェーズ1: 入力の読み込み
ステップ1: "3"を受け取る
→ メモリ位置1に [3に対応するベクトル] を書き込む
→ ポインタを次の位置へ移動
ステップ2: "1"を受け取る
→ メモリ位置2に [1に対応するベクトル] を書き込む
→ ポインタを次の位置へ移動
... (続く)
フェーズ2: 出力の生成
ステップ1: ポインタをメモリ位置1に戻す
→ メモリ位置1を読む → "3"を出力
→ ポインタを次の位置へ移動
ステップ2: メモリ位置2を読む
→ "1"を出力
→ ポインタを次の位置へ移動
... (続く)
メモリの様子:
時刻0 (初期状態):
メモリ: [空, 空, 空, 空, 空]
重み: [0.2, 0.2, 0.2, 0.2, 0.2] ← 均等
時刻1 (最初の入力後):
メモリ: [[3], 空, 空, 空, 空]
重み: [0.0, 0.9, 0.1, 0.0, 0.0] ← 位置2に移動
時刻2:
メモリ: [[3], [1], 空, 空, 空]
重み: [0.0, 0.0, 0.9, 0.1, 0.0] ← さらに右へ
... (入力完了後)
メモリ: [[3], [1], [4], [1], [5]]
重み: [0.0, 0.0, 0.0, 0.0, 1.0]
出力フェーズ (ポインタを先頭に戻す):
重み: [0.9, 0.1, 0.0, 0.0, 0.0] ← 位置1に戻る
読み取り → "3"を出力
NTMの学習方法
エンドツーエンド学習
NTMの素晴らしい点は、全体を一緒に学習できることです!
入力 → [NTM全体] → 出力
↓
損失関数
↓
バックプロパゲーション
↓
すべてのパラメータを更新
学習されるパラメータ:
- コントローラのニューラルネットワークの重み
- アドレッシングの制御パラメータ
- 読み書きヘッドのパラメータ
なぜ学習できる?
すべての操作が微分可能(微分できる)だからです:
- メモリの読み書き → 重み付き和(微分可能)
- アドレッシング → softmax、コサイン類似度(微分可能)
- シフト → 畳み込み(微分可能)
学習の流れ
1. タスクを与える(例:数列コピー)
2. ランダムな初期パラメータでNTMを実行
→ 最初はデタラメな出力
3. 正解との誤差を計算
4. バックプロパゲーション
→ どのパラメータをどう変えればよいか計算
5. パラメータを更新
6. 繰り返す
結果: NTMが自動的にメモリの使い方を学習!
NTMが解けるタスク
DeepMindの論文では、以下のタスクで従来手法を上回る性能を示しました:
1. Copy(コピー)
入力: [1, 2, 3, 4, 5]
出力: [1, 2, 3, 4, 5]
学習: 長さ1〜20の系列
テスト: 長さ120の系列でも完璧に動作!
従来のLSTM: 学習した長さを超えると性能が急低下
NTM: 長い系列でもほぼ完璧
2. Repeat Copy(繰り返しコピー)
入力: [1, 2, 3], 回数: 4
出力: [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
NTMは「ループ」の概念を学習できます。
3. Associative Recall(連想記憶)
入力: [key1, val1, key2, val2, key3, val3, ..., query_key]
出力: query_keyに対応するvalue
例:
[cat, animal, dog, animal, car, vehicle, ..., dog]
→ animal
NTMは「辞書」のようなデータ構造を学習できます。
4. Priority Sort(優先度ソート)
入力: [(データ1, 優先度0.3), (データ2, 優先度0.8), (データ3, 優先度0.1)]
出力: [データ2, データ1, データ3] ← 優先度順
5. N-Gram予測
言語モデルタスクでも、従来のLSTMより良い性能を示しました。
NTMの強みと弱み
強み
1. 長さ一般化
- 短い系列で学習 → 長い系列でも動作
2. データ効率
- 従来手法より少ないデータで学習可能
3. 解釈可能性
- 学習後、メモリの使い方を可視化できる
- 「今どこを読んでいるか」が見える
4. アルゴリズム学習
- 明示的なプログラミング不要
- データから自動的にアルゴリズムを学習
弱み
1. 学習の難しさ
- パラメータが多く、学習に時間がかかる
- ハイパーパラメータ調整が難しい
- 学習が不安定になることがある
2. 計算コスト
- メモリサイズNに対してO(N)の計算が必要
- 大規模なメモリでは遅い
3. 実用化の壁
- 理論的には素晴らしいが、実際のアプリケーションでは使いにくい
- Transformerなど、より実用的な手法が登場
4. 離散性の欠如
- すべてが「ソフト」なので、厳密な離散操作は苦手
- 例:「位置3を正確に読む」ではなく「だいたい位置3付近」
NTMの歴史的意義と影響
2014年の衝撃
NTMの論文は、AIコミュニティに大きな衝撃を与えました:
「ニューラルネットワークにプログラム的な能力を与えられる!」
後続研究への影響
NTMは多くの研究を触発しました:
1. Differentiable Neural Computer (DNC, 2016)
- DeepMindによるNTMの改良版
- より複雑なメモリ管理
- グラフ推論などで優れた性能
2. Attention機構の発展
- NTMのアテンション機構がTransformerに影響
- 「ソフトな参照」の概念が広まった
3. Memory-Augmented Neural Networks (MANN)
- 様々な外部メモリ付きニューラルネットワーク
- Few-shot learning(少数のサンプルで学習)などに応用
なぜ広く普及しなかったか?
1. Transformerの登場(2017)
NTM: 外部メモリで過去の情報を保持
Transformer: Attentionで直接過去を参照
→ Transformerの方がシンプルで効果的
2. 実装の複雑さ
- NTMは実装が複雑
- デバッグが難しい
- 実用的なアプリケーションで使いにくい
3. 学習の不安定性
- 学習がうまくいかないケースが多い
- 再現性が低い
最新の展開:NTMの復活?
最近、NTMのアイデアが再び注目されています!
理由
1. 効率性の重要性
- Transformerは大規模化で成功したが、計算コストO(n²)が問題に
- NTMのようなO(1)アクセスが再評価されている
2. 長さ一般化の課題
- Transformerは学習した長さを超えると性能低下
- NTMのアイデアが解決策として見直されている
3. 理論的理解の深化
- 本記事で紹介した研究のように、理論的な裏付けが進んだ
- 「なぜ外部メモリが必要か」が明確になった
現代的なアプローチ
組み合わせ戦略:
Transformer (高性能な表現学習)
+
NTM型外部メモリ (効率的な長期記憶)
=
次世代AIシステム?
例:
- Memorizing Transformers: Transformerに外部メモリを追加
- ∞-former: 無限長のコンテキストを扱えるTransformer
- RMT (Recurrent Memory Transformer): メモリトークンを持つTransformer
実装イメージ(疑似コード)
NTMの実装は複雑ですが、概念を理解するための簡単な疑似コードを示します:
class NeuralTuringMachine:
def __init__(self, memory_size, memory_dim):
# メモリ: N個 × M次元
self.memory = zeros(memory_size, memory_dim)
# コントローラ(LSTM など)
self.controller = LSTM()
# 読み書きヘッド
self.read_head = ReadHead()
self.write_head = WriteHead()
def forward(self, input):
# 1. コントローラで処理
controller_output = self.controller(input, prev_read)
# 2. メモリから読み取り
read_weights = self.read_head.address(controller_output, self.memory)
read_vector = weighted_sum(self.memory, read_weights)
# 3. メモリへ書き込み
write_weights = self.write_head.address(controller_output, self.memory)
self.memory = self.write_head.write(
self.memory,
write_weights,
controller_output
)
# 4. 出力生成
output = generate_output(controller_output, read_vector)
return output
class ReadHead:
def address(self, query, memory):
# コンテンツベース・アドレッシング
similarities = cosine_similarity(query, memory)
content_weights = softmax(beta * similarities)
# ロケーションベース・アドレッシング
# (補間、シフト、鋭化)
weights = interpolate(content_weights, prev_weights, g)
weights = shift(weights, shift_distribution)
weights = sharpen(weights, gamma)
return weights
class WriteHead:
def write(self, memory, weights, content):
# Erase
erase_vector = generate_erase_vector(content)
memory = memory * (1 - outer_product(weights, erase_vector))
# Add
add_vector = generate_add_vector(content)
memory = memory + outer_product(weights, add_vector)
return memory
まとめ:NTMから学ぶこと
重要な教訓
1. 外部メモリの重要性
- 固定サイズの内部状態には限界がある
- 外部メモリで能力を大幅に拡張できる
2. 微分可能性の力
- すべてを微分可能にすれば、エンドツーエンド学習が可能
- 複雑なシステムも自動的に学習できる
3. 理論と実践のギャップ
- 理論的に素晴らしくても、実用化には別の課題がある
- シンプルさも重要な要素
4. アイデアの継承
- NTMは直接的には普及しなかったが、そのアイデアは生き続けている
- Attention機構、Memory-Augmented Networks、最新のTransformer研究
初学者へのメッセージ
NTMは「AIに何ができるか」の可能性を広げた研究です:
- 人間のような問題解決: 外部のメモ帳を使いながら考える
- アルゴリズムの学習: プログラミング不要で、データから手順を学ぶ
- 理論と実践の橋渡し: チューリングマシンという理論とニューラルネットワークという実践を結びつけた
たとえ現在広く使われていなくても、NTMのアイデアは未来のAI研究の基礎となっています。
参考資料
原論文
- Graves, A., Wayne, G., & Danihelka, I. (2014). "Neural Turing Machines"
関連研究
- Graves, A., et al. (2016). "Hybrid computing using a neural network with dynamic external memory" (DNC)
- Vaswani, A., et al. (2017). "Attention is All You Need" (Transformer)
実装
- GitHub上に多数のオープンソース実装あり
- PyTorch、TensorFlowでの実装例
NTMは、AIが単なるパターン認識を超えて、アルゴリズム的な思考を獲得できる可能性を示した歴史的に重要な研究です。現在のAI研究の土台の一つとなっていることを、ぜひ覚えておいてください!
Discussion