話題のED法、誤差拡散法による学習法
こちらをpytorchを使用してレイヤとして実装しました。
おまけでとりあえずMNISTを丸ごと学習するスクリプトと、いくつかのモデルを用意しています。
devcontainerとtensorboardによる訓練のロギングまで実装しておいたので、実験してみてください。
実装した内容について
ED法を示した図を基に実装しました。
※転載の転載です@Cartelet 金子勇さんのED法の解説と弱点、行列積を使用した効率的な実装
出典:https://web.archive.org/web/20000306212433/http://village.infoweb.ne.jp:80/~fwhz9346/ed.htm
ED法の特徴を図から次のように捉え実装しました。
- 入力~出力までの経路が一意
- 自身と1つ前の入力、出力からやってきた上げる・下げるの信号でその重みを調整する
- 誤差は全層で共有する
- pytorchのbackwardの仕組みを使いながらも、最終層のgrad_outをバイパスすることで実現
- 層を全くごとに結合され、in/2個だけ次の出力が生まれる
- 図を見る限りそうとしか考えられない
- 最初に十分な数の入力複製を作成しておく
- 通常のモデルであれば特徴量は段階ごとに増えるのとは対照的で面白いと思う
- 出力数を内積などで直接増やすことはできない
- 入力と出力の関係が崩れ、誤差の共有ができなくなるため
- 全層をそもそも十分に複製し、結合してしまうことで複数出力を実現している
- 考え方的にはconv1dのgroupsに近い
もとのC実装は見たのですが、あんまり図のとおりに実装している気がしないので、いっそ図のほうに寄せて考えて実装しました。
なので、ちょっと変わっているかもしれません。
確認できていること
- 一番手前の層までgradが共有される
- 出力を10個に増やし、softmaxがかけられている
- なんとなく訓練されるっぽい
- 多分torchにできてるからcudaで動く(はず)
確認できていないこと
- ここまで実装したけどちゃんと訓練してログを見れてない
- くそ重いので、注意してください(CPUで実行)
- epoch100くらいまではなんかそれっぽくACCが上がるみたいです
実装できていること
- いくつかのbackwardをいじった関数の実装
- レイヤとしての実装
- 活性化関数を任意に差し替える方法
現状追加のアイデア
- 層をまたぐたびに減る分は、また入力を複製して作ってしまえば理論上無限に中間層を増やせるかもしれない
ぜひ実験してください
- 実験結果や感想、改善案はIssueやコメント、プルリクでいただけると嬉しいです