金子勇氏が考案したED法でMNISTを試してみた。ED法(誤差拡散法)について理論的なことは全く分かっていないが、動かすことで分かることもある。幸いにして私にはClaude Codeという優秀な助手(兼家庭教師)がいる。難しいことは全て彼にお願いしながら進めることにした。
サンプルプログラムの改造を依頼
金子氏が公開したサンプルプログラムの中にC言語によるED法のサンプルプログラムがある。サンプルプログラムは金子氏HPのアーカイブからダウンロードできる。
Kaneko's Software Page
2026-03-01 追記
上記ページからリンクされたページは一部画像データが消失している。完全に保存されたED法のページはこちら。
PyTorchベースでMNIST学習を試すスクリプトmnist.pyは私の手元にあった。山岡忠夫氏の「強い将棋ソフトの創り方」4.4章 PyTorchの基本にあるスクリプトでこちらのGitHubに公開されている。2層の畳み込みニューラルネットとバックプロパゲーション(誤差逆伝播法)で学習する仕様になっている。
以下のようにClaude Codeに頼んでみた。
mnist.pyではPyTorchでバックプロパゲーション(誤差逆伝播法)を使用しています。
金子勇氏が開発した誤差拡散法(ED法)をPyTorchに実装し、MNISTを実行できる環境をPythonで作成してください。
ED法のC言語によるサンプルプログラムはフォルダedの下にあります。
畳み込み層はとりあえず2層でいいです。
Claude Codeはコードを作成してくれたが、動かしてみると全く学習してくれなかった。何度もClaude Codeとやり取りしたが改善することはできなかった。
作戦変更
サンプルプログラムはそれぞれ動いた実績のあるプログラムでも、ED法を移植するという作業は難しいことが分かった。そこでED法として動いた実績のあるコードを入手して動かすことにした。
幸いにしてすでにPythonでED法を実装してMNISTをちぃがぅさんが試している。
金子勇さんのED法を実装してMNISTを学習させてみた #Python - Qiita
コードはTensorFlowベースで書かれている。私のPython3.10環境でTensorFlowが動くが不安であったがClaude Codeに聞いたところ問題ないとのことなのでPython3.10環境で進めた。
コードはほぼそのままで動いたが1箇所だけ修正が必要だった。main_tf()のmodel定義で(28 * 28)が括弧付き整数784として評価されエラーとなった。shape引数にはタプルが必要なため末尾にカンマを追加した。この修正もClaude Codeに教えてもらった。
- tf.keras.layers.Input(shape=(28 * 28)),
+ tf.keras.layers.Input(shape=(28 * 28,)),
サンプルコードでは数字0と1を学習させていたが、数字4と5に変更。TensorFlowモデルは3層5エポックに変更。ED法モデルは10層で変更なし。TensorFlowモデルの学習精度は97%、ED法モデルの学習精度は83.7%であった。
テストデータ先頭10データの評価結果を表示させた。このデータではED法は全問正解でTensorFlowは9問正解となった。

私はMNISTの学習をさせるには畳み込みニューラルネットが必要と思い込んでいたのだが、ちいがぅさんのコードsample.pyにそれらしき記述が見当たらないためClaude Codeに質問した。
tensorflowに詳しくないのでsample.pyで畳み込みニューラルネットがどのように実装されているか説明してください。フィルタの次元、ゼロパディング、ストライド、バイアスはどこでどのように設定されていますか。畳み込み層の層は何層ですか、プーリング層はどこで指定していますか。
Claude Codeの回答
`sample.py` には畳み込みニューラルネット(CNN)は実装されていません。
`sample.py` の `main_tf()` で使われているのは 全結合層(Dense層)のみ で構成されたネットワーク(MLP: 多層パーセプトロン)です。
そんな方法もあることを初めて知った。勉強になるな〜。
Claude Codeはコーディングしてくれる助手であるだけでなく、私にとっての家庭教師でもある。難関大学の学生か院生を家庭教師で雇うとすれば今どき時給3千円はするだろう。週1回2時間で一ヶ月に5回来てもらうと手当は3万円になる。それを月3千円で契約して好きな時間に対応してもらえるのであれば安いものだ。
MNISTの全データ(数字0から9まで)の学習
サンプルプログラムでは数字0と1の学習(2クラス分類)となっている。これを数字0から9の学習(多クラス分類)に対応させたいと思った。Claude Codeに修正してもらったところ、TessorFlowでは問題なく学習できたが、ED法では学習できなくなった。
Claude Codeに質問した。
2クラス分類のsample.pyでは正しく学習できていますが多クラス分類のsample_all.pyでは学習できていません。tensorflowの学習は正しくできています。両方のソースの処理の違いを説明してください。
Claude Codeの回答
sample.py(2クラス、`MultiLayerModel`)
def train(self, inputs, target):
x = self.forward(inputs)
diff = target - x
if diff > 0:
direct = "upper"
else:
direct = "lower"
diff = -diff
for neurons in self.hidden_neurons_list:
for n in neurons:
n.update_weight(diff, direct)
self.out_neuron.update_weight(diff, direct)
- 出力ニューロンは 1個
- `diff` と `direct` は 1回だけ決まる
- 隠れ層への更新は 1回のみ、方向も 1方向のみ
sample_all.py(多クラス、`MultiLayerModelMultiClass`)
def train(self, inputs, target_class: int):
out = self.forward(inputs)
targets = [1.0 if i == target_class else 0.0 for i in range(self.num_classes)]
for neuron, t, o in zip(self.out_neurons, targets, out):
diff = t - o
direct = "upper" if diff > 0 else "lower"
for neurons in self.hidden_neurons_list:
for n in neurons:
n.update_weight(diff, direct)
neuron.update_weight(diff, direct)
- 出力ニューロンは 10個
- 隠れ層のニューロンが 10クラス分ループで10回更新される
- 各クラスで `direct` が異なる場合がある
問題の本質:隠れ層への矛盾した更新
1サンプルを処理するとき、10個の出力ニューロンに対して次の状況が起きます:
| 出力ニューロン |
target |
output(学習前) |
diff |
direct |
| 正解クラス |
1.0 |
~0.1 |
+0.9(大) |
upper |
| 不正解クラス×9個 |
0.0 |
~0.1 |
−0.1(小) |
lower |
隠れ層は全出力ニューロンで共有されていますが、ループで10回更新される際に:
- 正解クラス → `"upper"` 方向に更新(出力を上げる)
- 不正解クラス×9 → `"lower"` 方向に更新(出力を下げる)
この矛盾した信号が隠れ層に繰り返し加わるため、更新が打ち消し合い、隠れ層の重みがほぼ動かない状態になります。
バックプロパゲーションとの根本的な違い
TensorFlowが正常に学習できているのは、バックプロパゲーションが「全出力からの誤差を合算してから隠れ層を1回だけ更新する」ためです。
| 手法 |
隠れ層の更新方法 |
| バックプロパゲーション |
全出力の誤差を加算した勾配で1回更新 |
| ED法(現在の多クラス実装) |
各出力ニューロンごとに順番に10回更新(方向が矛盾する) |
ED法を多クラスへ拡張するには、全出力クラスの `diff` と `direct` を整理してから隠れ層を 1回だけ 更新する仕組みに変更する必要があります。
どうやらED法には課題もあるようだ。ED法について説明されたページを見返したところ、ED法は0か1かという2クラス分類には強いが多クラス分類には対応しにくいという弱点があるようだ。
ただし対応できないということではない。解決方法を見つけている方もいた。
ED法で複数出力してみた(XOR 正答率:100%) #ED法 - Qiita
Claude Codeに解決方法を考えてもらい何度か試したがうまく学習できない。一筋縄ではいきそうにないのでこの辺であきらめることにした。
感想
ED法の2クラス分類でMNISTを動かした。まだED法は理解できていないが少しだけ理解が深まった気はする。
余談
ED法についてネットで調べていたらやねうらお氏の以下の記事を見つけた。その中にED法とBP(バックプロパゲーション)について興味深いことが書かれていたので一部引用させていただく。
Winnyの金子さんのED法について | やねうら王 公式サイトやねうら王 公式サイト
いずれにせよ、BP法は、チート性能だ。人間より遥かに少ないニューロンで人間より高い性能が出せる(ことがある)のは、このBP法のお陰だと言っても過言ではないと思う。人間の脳はBP法なんて使っていない。使わせてもらえていない。だから学習がこんなに非効率なのだ。人間が社会人になるまで平均的には20数年かかけるのも、学習が非効率すぎるからだと言えよう。
金子氏は「BPは人間の脳では絶対にできない方法だからシミュレーション屋としてはきらいだ」と言って人間の脳の仕組みにより忠実なED法を考え出したわけだが、BPを使うことで多クラス分類(複数出力)も対応できて効率的に学習できているんだからBPでいいじゃんという考え方も確かにあると思った。
「人間が社会人になるまで20数年かかる」という言葉も最近サム・アルトマンが発言していてその点でも興味深かった。
gigazine.net
私が一番驚いたのはページ中に金子氏の遺作「NekoFight」のリンクがあったことだ。どうせリンク切れしてるだろうと思いながらクリックしたらZIPファイルをダウンロードできた。解凍してどうせWindows11では動かないだろうと思って起動したら普通に動いた。奇跡である。NekoFightについては別記事で紹介したい。