scikit-learnで多項式回帰にスパースモデリングを試す

## はじめに
スパースモデリングは、解のスパース性を仮定して、少ないデータからでもデータの関係をモデル化できるようにする手法です。大量のデータがあることを前提にデータの関係をモデル化するディープラーニングとは対照的なものです。
理解を深めるため、scikit-learnで「ほとんどの係数がゼロの多項式関数」と解のスパース性を仮定した多項式回帰の問題を解いてみます。

### この記事でやること
- スパースモデリングの概要説明
- 多項式回帰を、`sklearn.linear_model`の[Regressors with variable selection](https://scikit-learn.org/stable/modules/classes.html#regressors-with-variable-selection)を使って解く
    - Google Colaboratoryで[この記事に用いたソースコードの全文](https://colab.research.google.com/drive/17SPaS-KUz2yRrTWTZQqZ-qRo6Evv0s9m?usp=sharing)を実行できます
    - （ただし、題材となる多項式関数はランダムに決定されるため、この記事と完全に同一とはなりません）

### この記事でやらないこと
- 詳細な数学的解説
- 最新アルゴリズム（各種座標降下法など）の紹介
- アルゴリズムの選択方針、パラメーターの調整方針
- スパースコーディング


## スパースモデリングにおけるスパース性の仮定
![スパース性の仮定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317463/faaf2060-3b87-c7ba-57db-846af7b3befa.png)
上の図の左側は、

- 観測されたデータを「結果」とする
- n個の「要因」が「結果」をもたらした、とモデル化した

ことを表したものです。

上の図の右側は、

- 要因はn個も考えられるけれども、そのうち実際に結果に関わるものは極少数で、大部分は関係がない

と仮定したことを表したものです。これが「スパース性を仮定する」と良い、スパース性を前提としたモデル化を「スパースモデリング」と言います。

## 多項式回帰を例題にする
具体的に考えるために、先程の図を多項式回帰の問題と考えることにします。
![sparse-reg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317463/d7ec3ab4-bbe0-87d8-33e6-0d9f685d4a93.png)
通常、多項式回帰は最小二乗法を使って解くことを考えます。しかし、モデルの説明変数$w_i$の数に対してデータの数が少ないときは過学習が起こります。

例として、真の関数を$$y = -2.59x^{4} + 0.776x^{29}$$とし、そのうちノイズの入った11点しかデータが取れなかった場合を考えます。
![subject.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317463/a99208c0-e0e7-446c-16a8-485b481c3360.png)
ここで、$$y = \sum_{i=0}^{39} w_i x^i$$とモデル化し、scikit-learnの`LinearRegression`を使って、最小二乗法による多項式回帰を実行してみます。

```python
from sklearn.linear_model import LinearRegression
model = LinearRegression()
```
![linear-crop-qz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317463/153ca27c-48d5-7786-cdbb-eb68828e8752.png)
確かに過学習が起きているらしいことが確認できました。
今回は、説明変数40個のモデルに対してデータが11個しか与えられていませんでした。この状況は、一般的なディープラーニングのアプローチで期待されている「モデルの説明変数に対して十分な量のデータがある状況」とは真逆のものです。

## scikit-learnでスパースモデリングを試す
ここで、「全40変数の内ほとんどの変数はゼロだが、どこが非ゼロかはわからない」というスパース性の仮定を置きます。この仮定を使うには「非ゼロの変数が少ないほど良い」としたアルゴリズムを使えば良いことになります。

以下に、scikit-learnで実装されているアルゴリズムを使った例を示します。
（各アルゴリズム名の見出しは、scikit-learnのドキュメントへのリンクになっています）

### [Lasso](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Lasso.html)
Lassoは、最小二乗法の目的である「残差の二乗和の最小化」に、L1正則化項を加え、これを最小化できる係数を決定するものです。

```python
from sklearn.linear_model import Lasso
model = Lasso(alpha=0.001)
```
![lasso-qz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317463/721e193f-b3a8-672d-d99e-ef0f938d5f72.png)

### [Elastic Net](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.ElasticNet.html)
Elastic Netは、（Lasso回帰で使われる）L1正則化項に加え、（Ridge回帰で使われる）L2正則化項も加えたものです。

```python
from sklearn.linear_model import ElasticNet
model = ElasticNet(alpha=0.001)
```
![elasticnet-crop-qz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317463/cf77305e-327f-9b60-704b-9319a1d40e77.png)

### [Orthogonal Matching Pursuit model (OMP)](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.OrthogonalMatchingPursuit.html)
OMPは、先程までの「最小二乗法+正則化項」とは異なり、「最良の係数を1つずつ見付け、順に付け加えていく」というイメージで係数を決定します。

```python
from sklearn.linear_model import OrthogonalMatchingPursuit
model = OrthogonalMatchingPursuit(n_nonzero_coefs=2)
```
![omp-qz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317463/2bd6390d-2a5b-26c3-d1b3-625182b9581d.png)

### [LARS](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Lars.html)
LARSは、「[特徴量の値と暫定での誤差との相関が最も大きい特徴量を1つずつ加えていく](https://leck-tech.com/machine-learning/lars)」というものです。

```python
from sklearn.linear_model import Lars
model = Lars(n_nonzero_coefs=2)
```
![lars-qz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317463/02862bf5-243a-5b32-3622-a72576cf3152.png)

### [Lasso-Lars](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LassoLars.html)
Larsを使ったLasso回帰です。詳細は分かりませんでした。

```python
from sklearn.linear_model import LassoLars
model = LassoLars(alpha=0.001)
```
![lassolars-qz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317463/b3227e77-7ec8-496b-4171-f7d13e44b5a5.png)


### 各係数の値
どのアルゴリズムも過学習を抑えられていることが分かりました。
では、最小二乗法で係数を求めたときの実際の各係数を見てみます。
![linear-coef-qz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317463/c92565f1-673d-2377-0079-cb736f8e4b9c.png)
全係数に値が入っています。

続いて、Lasso-Larsで係数を求めたときの実際の各係数です。
![lassolars-coef-qz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317463/f301f4f1-723e-8911-ff1f-cd96d95a81e7.png)
少ない係数で多項式が表現できています。


## まとめ
スパースモデリングの概要を説明し、簡単な多項式回帰の問題でスパースモデリングを試してみました。

「スパースモデリングは少ないデータからでも良質な学習ができる」とだけ聞くと、ディープラーニングより優れた方法という印象を受けるかもしれませんが、スパースモデリングが有効に作用するのはスパース性の仮定が前提にある場合だけです。ディープラーニングとスパースモデリングは、それぞれが前提としている状況が異なるので優劣の関係にはありません。
問題設定がスパース性とマッチしていれば、スパースモデリングはディープラーニングより好ましい結果を与えてくれるでしょう。
![summary-qz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1233542/e5155c7f-dfbd-d4ec-eea1-518bcecdc375.png)


## Reference
- [スパースモデリング、スパースコーディングとその数理(第11回WBA若手の会)](https://www.slideshare.net/narumikanno0918/11wba-55283892)
    - 全体の構成を考えるのに役に立ちました。
- [Python ではじめるスパースモデリング – HACARUS INC.](https://hacarus.com/ja/information/tech/2018-01-getting-started-with-sparsemodeling-in-python/)
    - Pythonコードの参考になりました。
- [LARS(Least Angle Regression)アルゴリズムまとめ(Python, sklearn) | 創造日記](https://leck-tech.com/machine-learning/lars)
    - LARSアルゴリズムを理解するのに参考になりました。