継続学習による破壊的忘却の抑制

## 概要
### 継続学習
* 1つのネットワークで複数の異なるタスクを順番に学習し、以前に学習したタスクを解く能力を維持したまま、新しいタスクを追加的に学習すること
* ニューラルネットワークは新しいタスクの学習によって以前の学習内容を失いやすく、克服が課題となる

### 継続学習への関心
#### サイエンスの問題としての関心：
* 動物が絶えず学習し続けられるのと同様に、1つのネットワークで異なるタスクを継続的に学習できるようにするにはどうすればよいか？
#### 工学的で現実的な要請に基づく関心：
* あるタスクを一定の性能でこなすニューラルネットワークがあるとき、性能向上や適用範囲の拡大を目的とした追加的な学習(追加学習)を行う
* それまでに達成していた性能が低下しないように追加学習を行うにはどうすべきかが課題となる
* ※追加学習はオンライン学習と同じ意味で使われることもあるらしい…。

### 各関心における共通事項
* 新たに学習を行う際は、それ以前の学習で用いら訓練データを再度利用することはできない制約を課す！
* 現実でも以下の状況が考えられ、上記制約は一般的と思われる：
    * 以前用いた訓練データを保持する記憶域がない
    * 同じ学習を繰り返すことがコストの面で不可能


## 破壊的忘却
### 破壊的忘却とは？
* モデルが次々と新しいタスクを学習するときに、過去に学習したタスクを忘れてしまう現象のこと
参考：https://www.skillupai.com/blog/tech/catastrophic-forgetting/ 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594896/f9face09-58b8-7be9-6638-a19a68769f63.png)

* 現実的にも例えば、1つのモデルで「チワワとマフィンの分類問題」を学習した後に「月とハムの分類問題」を学習することを考えることがあるが、後段の学習をした際に前段の精度が下がることは好ましくない…。

* 継続学習は「破壊的忘却」を抑制することが主題となっている


## 対象とする問題の型
* 対象とする問題の型は以下の3つ
    * タスクが追加される場合
    * タスクは同じままで新しいクラスが追加される場合 (クラス増分)
    * タスクは同じままでドメインが追加される場合 (ドメイン増分)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594896/4550cc90-2214-5512-95e5-604f74568e58.png)

## 方法
継続学習は以下の3タイプに大別される：

### 正則化ベースの手法
* 損失関数に正則化項を付与する
* 例：Elastic Weight Consolidation (EWC) 

### リプレイを行う手法
* 過去のタスクの学習に用いたデータセットを再現(リプレイ)することで、過去のタスクを忘れないように新しいタスクを学習する
* 新しいタスクを学習する際に、古いタスクのサンプルを生成したり、蒸留したりで再学習する
* 例：Learning without Forgetting (LwF)
* 例：Deep Generative Replay

### アーキテクチャベースの手法
* ネットワークの構造を工夫することで過去のタスクを忘れないように新しいタスクを学習する
* 例：PackNet 

参考：https://www.skillupai.com/blog/tech/continual-learning/ 


## 正則化ベースの手法
### Elastic Weight Consolidation (EWC) 

2つのタスク $\mathcal{T}_𝐴$, $\mathcal{T}_𝐵$ に対する訓練データセットを $\mathcal{D}_𝐴$, $\mathcal{D}_𝐵$ とする。

損失関数 $𝐸$ を以下とする：
```math
𝐸(𝑤;\mathcal{D}_𝐴, \mathcal{D}_𝐵 )=𝐸_𝐴 (𝑤;\mathcal{D}_𝐴 )+𝐸_𝐵 (𝑤; \mathcal{D}_𝐵) 
```

しかし、 $\mathcal{T}_𝐴$の学習後、 $\mathcal{T}_𝐵$の学習時に$\mathcal{D}_𝐴$ を使用できない。。。

$𝐸_𝐴 (𝑤;\mathcal{D}_𝐴 )$を$\mathcal{D}_𝐴$を使わずに計算するため近似関数を作る。

タスク$\mathcal{T}_𝐴$の最適解を$𝑤_𝐴^∗≡𝑎𝑟𝑔𝑚𝑖𝑛_𝑤  𝐸_𝐴 (𝑤;\mathcal{D}_𝐴)$とし、$𝑤_𝐴^∗$の近傍で$𝐸_𝐴 (𝑤;\mathcal{D}_𝐴 )$を近似することを考える。

$𝑤_𝐴^∗$は最適解なので$𝑤=𝑤_𝐴^∗$で$\frac{𝜕𝐸_𝐴}{𝜕𝑤}=0$なので、$𝐸_𝐴$ を$𝑤=𝑤_𝐴^∗$ の周りでテイラー展開し、2次の項で打ち切る：
```math
E_A(w, \mathcal{D_A}) \approx \frac{1}{2}(w - w_A^*)^TH(w - w_A^*)
```
ここで、$H$はヘッセ行列：$H_{ij} = \left. \frac{\partial^2E_A}{\partial w_i\partial w_j} \right|_{w_A=w_A^*}$

𝐻は巨大な行列なので、対角成分だけを使って近似する：
```math
E_A(w, \mathcal{D_A}) \approx \frac{1}{2}\sum_i H_ii(w_i - w_i^*)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594896/16affab8-4746-a435-9266-1407182ad94e.png)


## リプレイを行う手法
### Learning without Forgetting (LwF)

古いタスク$\mathcal{T}_𝐴$を学習したネットワーク$𝑓_𝐴$を保存する。

新しいタスク$\mathcal{T}_𝐵$の訓練データ$\mathcal{D}_𝐵$に対する$𝑓_𝐴$の出力を用いて$\mathcal{T}_𝐴$の疑似的な訓練データ$\mathcal{D}_𝐴^′$を作成し学習する。

$\mathcal{D}_𝐴^′$の目標出力には、蒸留の考え方に従い温度スケーリングを適用したものを使用する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594896/f6280edc-1c41-21d0-4139-40d4cb9bcdd8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594896/1fd8e619-f733-0e61-e688-6cc17e43b694.png)



### Deep Generative Replay

GeneratorとSolverの組(これをScholarと呼ぶ)を学習する。

Generatorはデータを生成し、Solverはその生成データに対するタスクを解く。

あるタスク$\mathcal{T_t}$の学習においては、タスク$\mathcal{T_t}$のデータと、それまでに学習したタスク$\mathcal{T_{𝑡−1}}$のScholarから生成されるデータを使ってタスク$\mathcal{T_t}$のScholarを学習する。

これを繰り返すことで今までに学習したタスクを忘れることなく、新しいタスクを学習していくことが可能になる(らしい)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594896/4a22aa24-2cf3-5a97-b77d-89c271f54076.png)

## アーキテクチャベースの手法
### PackNet

PackNetではフィルターを使って、各タスクで使用できるニューロンの数に制限をかける。

図はネットワーク全体の40%をタスク1に割り当て、残りの60%のうちの2/3をタスク2に割り当て、1/3をタスク3に割り当てる様子を表す。

各段階でre-training後にparameterはfixされる、pruningされた箇所(図の白ノード)はweight=0として扱う。

このように、1つのネットワークを複数のネットワークに分割するようにして、複数のタスクに対応できるように学習する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594896/cd3d4e59-5608-db76-f06b-8dc721ddcdee.png)


## 古いタスクのデータを少しなら使える場合…
これまでは新しいタスクに移行した後は、古いタスクのデータは一切使えない状況を考えた。

とはいえ、問題が記憶域の容量なのであれば、現実的に少しであればデータを一部保存しておき後で利用することも可能である。

実際、旧タスクのデータを保持し、新しいタスク学習時に保持したデータを再学習に用いると良い性能が得られる (直感的にはそう、論文もあるらしい)。

ランダムに訓練サンプルを選抜し、新タスクのサンプルと一定割合で混合したミニバッチを作る単純な方法がEWCやLwFを上回る。

ただし、旧タスクを小数の同じサンプルで学習し続けると過剰適合につながる。
* Gradient Episodic Memory(GEM)は新タスクの学習時に旧タスクの損失を小さくするのではなく、増加しないように制約するだけにする
* 記憶サンプルを選ぶ際に良い効果を与えるサンプルを選ぶ工夫もある (iCaRLはクラス追加の型を対象とする)

## <参考>破壊的忘却の原因
破局的忘却は何が原因か？
参考：https://ai-scholar.tech/articles/deep-learning/catastrophic-forgetting-analysis 

以下のPaperにより破壊的忘却のメカニズムについて研究されているとのこと：
* 「Anatomy of Catastrophic Forgetting: Hidden Representations and Task Semantics」 (2020.7.14)
https://arxiv.org/abs/2007.07400 

* まとめは以下のよう：
    * 破局的忘却は上位層(出力に近い層)が大きく寄与する
    * タスク間類似度が(論文内で定義された指標に基づいて)中程度の場合に、最も破局的忘却が強くなる