2026年1月4日日曜日

AIと戯れる

AI方面の知識がなくても、ぱっと思いついたアイディアをなんとなくAIに手伝ってもらいながら試す事ができるようになりました。
趣味のプログラミングが楽しいです。

これは、どういう事か内容を教えてください。と、AIに解説してもらったり

この内容を実装してみたいです。と、AIにお願いしてみたり

この結果は、こういう理由でこうなっているのではないか?こういう風に実装を変えて試してもらえないでしょうか?と、AIにお願いしたり

個人でアイディアをぶつけて、実験する敷居がものすごく下がりました。
なんなら、AIの方から提案してくれたり、お?それいいね!やってみましょう!と二人三脚で、いろいろ試せる
いい時代になりましたね!

以下、こんなアホな事をやらせてました。

EDLA (Error Diffusion Learning Algorithm) 実装履歴

概要

誤差拡散法(ED法)を用いたニューラルネットワーク学習の実験記録。 バックプロパゲーション(BP)を使わない学習手法の可能性を探った。


時系列実験ログ

Phase 1: ED法の基本理解と初期実装

着想

  • Qiitaの記事からED法について学習開始
  • 10層の深いネットワークで勾配消失問題が発生することを確認

実装ファイル

  • ed_entropy.py: Python版EDLA(エントロピーベースのu0調整)
  • ed_mnist.py: MNIST用Python実装
  • ed_network.cpp: C++版(高速化目的)

課題

  • 深いネットワークで学習が進まない
  • sigmoidの飽和による情報伝達の問題

Phase 2: 論文準拠の正確な実装

着想

  • arXiv論文(2504.14814v3)を発見
  • 公式GitHub実装と比較して、重要な違いを発見

重要な発見: sign(w) の欠落

// 修正前(誤り)
delta = (target - output) * g_prime;

// 修正後(正しい)
delta = (target - output) * g_prime;
delta *= sign(w);  // ← この行が重要!

実装

  • edla_paper.cpp: 論文準拠の正確な実装

結果

テスト 修正前 修正後
XOR - 41エポック
Parity - 7エポック

収束安定性が向上。


Phase 3: 活性化関数の比較実験

着想

  • 情報伝達問題の原因は活性化関数の飽和
  • 様々な活性化関数でg'(a)の健全性を検証

実装オプション(edla_paper.cpp)

--sigmoid  : 標準sigmoid
--tanh     : tanh(a/5)をスケーリングして[0,1]へ
--wavelet  : Mexican Hat Wavelet
--softmax  : Softmax出力層
--linear   : 線形活性化(実験用)

MNIST結果

活性化関数 Epoch 1 最終精度 勾配 g'(a)
sigmoid 87.76% 94.99% 0.0217
tanh (スケーリングなし) 56.87% ~50% 0.0058
tanh(a/5) 95.01% 97.66% 0.0504
wavelet 42.34% - -
softmax 88.20% 88.34% 0.0315
linear NaN NaN 発散

結論

  • tanh(a/5) が最良(勾配がsigmoidの2.3倍)
  • softmaxはED法のP/N構造と相性が悪い(88%で停滞)
  • linearは出力が発散してNaN

Phase 4: Logic Gate Networks論文の調査

着想

  • arXiv:2411.04732(NeurIPS 2024)を調査
  • 論理ゲートによる超高速推論の可能性を検討

論文の要点

  1. 16種類の論理ゲートを学習可能に
  2. Residual Initialization: Identity(素通り)を90%で初期化
  3. 訓練時は浮動小数点(微分可能)、推論時はバイナリ
  4. CIFAR-10で86%達成

CIFAR-10比較実験(cifar10_compare.cpp)

モデル Epoch 5精度 時間
EDLA 17.32% 1071s
Logic Gate (簡易版) 10.00% 151s

考察

  • LGNは畳み込み構造が必須(今回は全結合のみ)
  • 重要な発見: LGNも訓練時は微分が必要 → 勾配消失問題あり

Phase 5: Residual概念のED法への適用

着想

  • LGNのResidual Initializationは「Identity経路で勾配を維持」
  • ED法でも同様の効果が得られるのでは?

実装1: Gated EDLA(edla_residual.cpp, edla_residual2.cpp)

// 各ニューロンでα確率でIdentity、(1-α)で通常計算
output = α × prev_layer_mean + (1-α) × tanh_scaled(activation)

結果(3層ネットワーク)

手法 MNIST精度
オリジナル EDLA (tanh/5) 95.01%
Gated EDLA 86.54%

→ 浅いネットワークでは効果なし(むしろ悪化)


Phase 6: Identity経路の導入(ユーザー提案)

着想(ユーザー)

「100x100の入力を400x400に拡張し、25%をIdentityに割り当てる」

層のニューロンを「計算ニューロン」と「Identityニューロン」に分離する方式。

実装(edla_identity.cpp)

隠れ層構成:
[計算ニューロン 75%][Identityニューロン 25%]

               入力平均をそのまま出力

結果(3層、XORテスト)

Identity比率 XOR収束エポック
0% 2533
12.5% 1270 ← 最速
25% 1540
50% 1549

結論

  • 12.5%のIdentityが最速収束
  • しかしGated方式と大きな差はない

Phase 7: 深いネットワーク(10層)でのIdentity効果検証

着想(ユーザー)

「10層ぐらいないと、Identityを使うメリットが無い気がします」

深いネットワークでこそIdentity経路が有効なはず。

実装(edla_deep.cpp)

  • 可変深さのネットワーク
  • Identity配置オプション追加

結果(MNIST、10層)

方式 最高精度
Identity無し 11.70%(学習崩壊)
Identity有り(全層) 43.00%

約31%の改善! 深いネットワークでIdentity経路が劇的に有効。

浅い vs 深い比較

深さ Identity無し Identity有り 効果
3層 85.90% 85.30% -0.6%(効果なし)
12層 11.70% 43.00% +31.3%

Phase 8: Identity配置の最適化

着想(ユーザー)

「9層と10層を繋ぐ箇所では勾配消失しても問題なさそう」 「出力に近い層はIdentity不要では?」

実験: Identity配置の比較

Identity範囲 最高精度 解釈
無し 11.70% 学習崩壊
全層(1-10) 43.00% 基準
前半のみ(1-5) 18.50% 部分的効果
後半のみ(6-10) 11.70% 効果なし

追加実験: 最終層を除外

Identity範囲 最高精度
層1-8 30.90%
層1-9 73.65% ← 最良!
層1-10(全層) 43.00%

重要な発見

  1. 出力側の層(6-10)にIdentityは効果なし
  2. 入力側の層(1-5)にこそIdentityが必要
  3. 最終層を除外した方が性能が向上(73.65% > 43.00%)
  4. 最終層はIdentityがあると「素通り情報」が出力を汚染

基本アルゴリズム

ED法の特徴

  • P/Nニューロン対: 正(Positive)と負(Negative)のニューロンをペアで持つ
  • 符号制約付き重み: weights_pp ≥ 0, weights_pn ≤ 0, weights_np ≤ 0, weights_nn ≥ 0
  • sign(w)更新: 勾配ではなく重みの符号方向に更新
  • 活性化関数: tanh(a/5) をスケーリングして [0,1] に正規化

更新式

d = target - output  (誤差)

if d > 0:
    Δw_pp = lr * d * g'(a) * x * sign(w_pp)
    Δw_np = lr * d * g'(a) * x * sign(w_np)
else:
    Δw_nn = lr * |d| * g'(a) * x * sign(w_nn)
    Δw_pn = lr * |d| * g'(a) * x * sign(w_pn)

実験1: Identity経路の導入

背景

  • Logic Gate Networks (arXiv:2411.04732) の「Residual Initialization」概念を参考
  • 深いネットワークで情報が途切れる問題への対策

Identity経路の実装

各層の構成:
  75% = Compute neurons (通常のED計算)
  25% = Identity neurons (入力平均をそのまま通す)

結果

設定 精度 備考
Identity無し(10層) 11.70% 学習崩壊
Identity全層 43.00% 改善あり
Identity層1-9 79.90% 最良
Identity層1-5のみ 18.50% 効果不足
Identity層6-10のみ 11.70% 効果なし

結論

  • Identity経路は深いネットワークに必須
  • 最終層(層10)にはIdentity不要(出力に直接情報が必要)
  • 前半〜中盤の層でIdentityが効果的

実験2: ネットワーク幅の検討

比較設定

  • 定幅: 128 → 128 → 128 → ... → 128
  • 縮小幅: 128 → 96 → 72 → 54 → 41 → 30 → 30 → 30 → 30 → 30

結果

構成 精度
定幅(128固定) 約70%
縮小幅 79.90%

結論

  • 幅を徐々に縮小する方が良い
  • 後半の層は情報が集約されるため、少ないニューロンで十分

実験3: 学習率と安定性

問題

  • lr=1.0: Epoch 3で崩壊(73.65%→30%)
  • lr=0.5: Epoch 6で崩壊

解決策: 学習率減衰

lr = max(0.05, 0.3 * 0.95^(epoch-1))

結果

設定 最高精度 安定性
lr=1.0 固定 73.65% ❌ Epoch 3で崩壊
lr=0.5→decay 74.35% ❌ Epoch 6で崩壊
lr=0.3→decay(0.95) 79.90% ✅ 安定

学習曲線(lr=0.3, decay=0.95)

Epoch  1: 48.90%
Epoch  5: 72.30%
Epoch 10: 78.20%
Epoch 15: 79.90% ← ピーク
Epoch 17: 79.35%
Epoch 18: 78.85% ← プラトー開始

実験4: ED + BP ハイブリッド

アイデア

  • 前半8層: ED法で学習(粗い特徴抽出)
  • 後半2層: BP法で学習(精密な分類)

実装

  • edla_hybrid.cpp を作成
  • ED層とBP層を直列接続

結果

  • うまく機能しなかった

原因分析

  1. 重みの構造が異なる

    • ED法: 4つの符号制約付き重み行列(pp, pn, np, nn)
    • BP法: 1つの制約なし重み行列
  2. 出力の意味が異なる

    • ED層: 正負を分離した表現
    • BP層: 通常の実数値特徴を期待
  3. 更新方向が競合

    • ED法: sign(w)方向に押す
    • BP法: 勾配方向に引く
    • 互いに干渉する可能性

結論

ED法とBP法のパラメータは「意味が違いすぎる」ため、 同一ネットワーク内での直接結合は困難(「油と水」)


他手法との比較

MNIST精度ランキング

手法 精度 備考
SOTA (CNN + Ensemble) 99.87% 最先端
CNN (LeNet-5) 99.0% 古典的
Forward-Forward ~98.5% BP不使用
MLP (BP) 98.4% 3層1000ニューロン
SVM 98.6% 非NN
ED法(本実験) 79.90% -
ランダム 10% ベースライン

位置づけ

  • ED法は精度では他手法に遠く及ばない(約20%の差)
  • しかし、計算の単純さ・メモリ効率では優位性あり

学習率微調整の見込み

予測

改善項目 見込み精度
学習率微調整のみ 80.5% ~ 82.0% (+0.6~2.1%)
+データ増加(60k) 82% ~ 85%
+ネットワーク拡大 84% ~ 87%
全部合わせて 85% ~ 88%

試すべきパラメータ

  • 初期学習率: 0.25, 0.35
  • 減衰率: 0.93, 0.97
  • 最小学習率: 0.08, 0.10
  • ウォームアップ: 3エポック

実装ファイル一覧

ファイル 用途 Phase
ed_entropy.py Python版EDLA(エントロピー調整) 1
ed_mnist.py MNIST用Python実装 1
ed_network.cpp C++版基本実装 1
edla_paper.cpp 論文準拠実装(複数活性化関数対応) 2, 3
edla_residual.cpp Gated EDLA実験 5
edla_residual2.cpp Gated EDLA改良版 5
edla_identity.cpp Identity経路導入版 6
edla_deep.cpp 深層ネットワーク + Identity配置実験 7, 8
cifar10_compare.cpp CIFAR-10比較実験(EDLA vs LGN) 4
edla_hybrid.cpp ED+BPハイブリッド(失敗) -

今後の方向性

ED法を続ける場合

  1. データ量増加: 10,000 → 60,000枚
  2. ネットワーク幅拡大: 1.5倍(192→144→108→...)
  3. 学習率スケジュール: Cosine Annealing, Cyclic LR

別アプローチ

  1. 蒸留方式: ED出力を教師としてBPネットを別に学習
  2. アンサンブル: ED分類器とBP分類器を投票で統合
  3. 別タスク: 異常検知、強化学習など精度が絶対でない領域

主な知見

時系列で得られた知見

  1. sign(w)の重要性(Phase 2)

    • 公式実装に delta *= sign(w) がある
    • これなしでは収束が不安定
  2. 活性化関数の選択(Phase 3)

    • tanh(a/5) が最良(勾配2.3倍)
    • softmaxはP/N構造と相性悪い
  3. 深いネットワークとIdentity(Phase 6-8)

    • 3層ではIdentity不要
    • 10層以上ではIdentity必須
    • 最終層はIdentity除外が最適
  4. Identity配置の原則

    • 入力側の層(1-5): 必須
    • 中間層(6-9): あった方が良い
    • 最終層(10): 不要(むしろ有害)
  5. 学習率減衰が安定性の鍵

    • lr=0.3, decay=0.95 が最適
    • 高すぎると崩壊、低すぎると学習しない
  6. ED法とBP法の直接結合は困難

    • パラメータの意味が根本的に異なる
    • ハイブリッドは別の工夫が必要
  7. ED法の限界と利点

    • 精度ではBP系手法に劣る(~20%差)
    • 計算効率・メモリ効率では優位

実験環境

  • OS: macOS
  • コンパイラ: g++ (C++17)
  • 最適化: -O3
  • データセット: MNIST (10,000訓練 / 2,000テスト)
  • 乱数シード: 42

最終更新: 2026年1月4日