深層学習モデルのパラメータの数を数える

# 1. はじめに
ふとディープラーニングのパラメータってどうやって数えるんだっけと思って、理解を確認するためにも計算してみました。

# 2. モデルの構成

Kerasを使ってモデルを構成してみます。
今回作成するモデルは256x256のRBGの画像を入力として、９つのカテゴリーに分類するモデルとなります。

![スクリーンショット 2020-03-15 15.13.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110541/9fdb43e7-9237-21f1-6efd-e9bdff70d9a8.png)

## 実装

必要なモジュールをインポートします。

```python
from keras.models import Sequential
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation
from keras.layers.core import Flatten, Dropout
from keras.layers.core import Dense
```

分類するクラス数を定数として定義し、

```python
num_class = 9
```

モデルを構成します。

```python
# モデルの作成
model = Sequential()

model.add(Conv2D(32, kernel_size=3, padding="same", activation='relu', input_shape=(256, 256, 3)))
model.add(Conv2D(32, kernel_size=3, padding="valid", activation='relu'))
model.add(MaxPooling2D(pool_size=(3, 3)))
model.add(Dropout(0.5))

model.add(Conv2D(32, kernel_size=3, padding="same", activation='relu'))
model.add(Conv2D(32, kernel_size=3, padding="valid", activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(32, kernel_size=3, padding="same", activation='relu'))
model.add(Conv2D(32, kernel_size=3, padding="valid", activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())    #Flatten()により特徴マップをベクトルに変換
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_class, activation='softmax'))    #Softmax関数にて、9 クラスの確度として出力
```
モデル情報を出力します。

```python
model.summary()        # モデル情報の表示
```
以下の出力が得られます。この中で一番右側にパラメータ数が出力されています。今回のモデルでは、6,029,097のパラメータが学習によって調整されることになります。

```
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 256, 256, 32)      896       
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 254, 254, 32)      9248      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 84, 84, 32)        0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 84, 84, 32)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 84, 84, 32)        9248      
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 82, 82, 32)        9248      
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 41, 41, 32)        0         
_________________________________________________________________
dropout_2 (Dropout)          (None, 41, 41, 32)        0         
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 41, 41, 32)        9248      
_________________________________________________________________
conv2d_6 (Conv2D)            (None, 39, 39, 32)        9248      
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 19, 19, 32)        0         
_________________________________________________________________
dropout_3 (Dropout)          (None, 19, 19, 32)        0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 11552)             0         
_________________________________________________________________
dense_1 (Dense)              (None, 512)               5915136   
_________________________________________________________________
dropout_4 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 128)               65664     
_________________________________________________________________
dropout_5 (Dropout)          (None, 128)               0         
_________________________________________________________________
dense_3 (Dense)              (None, 9)                 1161      
=================================================================
Total params: 6,029,097
Trainable params: 6,029,097
Non-trainable params: 0
_________________________________________________________________
```

# 3. パラメータ数の計算
## 3-1. CNN層
まず第１層のCNN層をみてみます。フィルタ数:32枚、フィルタサイズ:3x3、入力チャンネル:3(RGB)、出力チャンネル:3を指定しています。

```python
model.add(Conv2D(32, kernel_size=3, padding="same", activation='relu', input_shape=(256, 256, 3)))
```

```
=================================================================
conv2d_1 (Conv2D)            (None, 256, 256, 32)      896       
_________________________________________________________________
```
パラメータ数は以下の式で求められます。
パラメータ数 = フィルタ縦サイズ ｘ フィルタ横サイズ　x 入力チャンネル数　x 出力チャンネル数 ＋ バイアス x 出力チャンネル数
param =3 x 3 x 3 x 32 + 1 x 32 = 896

同じように第２層も計算してみます。

```python
model.add(Conv2D(32, kernel_size=3, padding="valid", activation='relu', input_shape=(256, 256, 3)))
```

```
=================================================================
conv2d_2 (Conv2D)            (None, 254, 254, 32)      9248      
_________________________________________________________________
```
今度は第２層への入力が32チャンネルとなっているので、

パラメータ数 = フィルタ縦サイズ ｘ フィルタ横サイズ　x 入力チャンネル数　x 出力チャンネル数 ＋ バイアス x 出力チャンネル数
param =3 x 3 x 32 x 32 + 1 x 32 = 9248

第３,４,5,6のConv2D層も同様に計算することができます。


## 3-2. Flatten層
特徴マップをベクトル化しています。１次元に落としています。ここでは学習によって調整するパラメータではありませんが、

```
_________________________________________________________________
dropout_3 (Dropout)          (None, 19, 19, 32)        0         
_________________________________________________________________
```
よりベクトルの次元は19 x 19 x 32 = 11552となります。


## 3-3. Dense層(隠れ層)
特徴量をベクトル化するFlatten層の次のDense層では
パラメータ数 = 入力サイズ x 出力サイズ + バイアス　となるため
param = 11552 x 512 + 512 = 5915136

その次の隠れ層も同様に
dense_2 (Dense)   param = 512 x 128 + 512 = 65664
dense_3 (Dense)   param = 128 x 9 + 9 = 1161

# 4. まとめ
改めて構築したモデルを確認します。
一番右のParamの値を足すと、6,029,097となります。学習ではこのパラメータが調整されています。
そして学習によって調整されたパラメータがモデルの一部となり、推論においては、モデルを軽量化などしない限り、これらのパラメータが使われて計算されています。

```
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 256, 256, 32)      896       
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 254, 254, 32)      9248      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 84, 84, 32)        0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 84, 84, 32)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 84, 84, 32)        9248      
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 82, 82, 32)        9248      
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 41, 41, 32)        0         
_________________________________________________________________
dropout_2 (Dropout)          (None, 41, 41, 32)        0         
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 41, 41, 32)        9248      
_________________________________________________________________
conv2d_6 (Conv2D)            (None, 39, 39, 32)        9248      
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 19, 19, 32)        0         
_________________________________________________________________
dropout_3 (Dropout)          (None, 19, 19, 32)        0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 11552)             0         
_________________________________________________________________
dense_1 (Dense)              (None, 512)               5915136   
_________________________________________________________________
dropout_4 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 128)               65664     
_________________________________________________________________
dropout_5 (Dropout)          (None, 128)               0         
_________________________________________________________________
dense_3 (Dense)              (None, 9)                 1161      
=================================================================
Total params: 6,029,097
Trainable params: 6,029,097
Non-trainable params: 0
_________________________________________________________________
```