DiCENet: Dimension-wise Convolutions for Efficient Networks ~最新(2019年7月時点)のCNNモデル~ (2019/8月追記)

# 初めに
※まだ書き途中です
最新のCNNであるDiCENet(Dimension-wise Convolutions for Efficient Networks)を読みました。メモ書きっぽく残しておくので参考文献などは後から付け足していきます。また、このモデルは査読が終わっていないものです。
元論文: [DiCENet: Dimension-wise Convolutions for Efficient Networks](https://arxiv.org/abs/1906.03516)
##環境
* OS: Linux18.04
* 言語: Python
* フレームワーク: Pytorch 1.1.0

# 背景
DiCENetは2つのモジュール、「DimConv (Dimention-wise Convolution)」と「Efuse (Efficient Channel Fusion)」から成っています。結果としてDiCENetは、クラス分類、セマンティック・セグメンテーション、物体検出などの分野で、FLOPsは他の最新のモデルよりも低いモデルみたいです。
![x10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416091/9d632303-ab9a-5636-88e2-bcfb6c65a5c4.png)
他のモデルと比較すると、FLOPsが同じ場合、DiCENetが最も良い精度となっており、精度が同じ場合、FLOPsが最も小さいのはDiCENetとなっています。

しかし、性能は[MobileNetv2](https://arxiv.org/abs/1801.04381)や[ShuffleNetv2](https://arxiv.org/abs/1807.11164)などと比べたら勝つものの、[ResNeXt](https://arxiv.org/abs/1805.00932v1)など、FLOPsが莫大で精度の良いモデルと比較すると低いみたいです。
![com_flops_imagenet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416091/c1de0542-e33b-41bb-7c5d-039fb021913f.png)
横軸のFLOPsが対数なのに注意してください。[ResNeXt](https://arxiv.org/abs/1805.00932v1)が莫大な計算量なのがわかります。

ResNeXtは計算量ガン無視で精度を求めるモデルですが、近年では限られたリソースでも実行できるように冗長な演算、パラメータを減らす傾向にあります。上のグラフの[MobileNetv1](https://arxiv.org/abs/1704.04861)、[ShuffleNetv1](https://arxiv.org/abs/1707.01083)、[MobileNetv2](https://arxiv.org/abs/1801.04381)、[ShuffleNetv2](https://arxiv.org/abs/1807.11164)やDiCENetもその類のモデルかと思われます。

Standard Conv → Depth-wise Conv + Point-wise Conv → DimConv + EFuseの順で説明していきます。
<b>※間違えて解釈している可能性もあります。お気づきになられましたら、ぜひご指摘ください。</b>

#従来の畳み込み

- Standard Conv  
- Depth-wise Conv+Point-wise Conv
- Depth-wise Conv+Point-wise Convの問題点    

## Standard Conv(普通の畳み込み)の処理
* 入力チャネル3、出力チャネル16の例
![本来の畳み込み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416091/cec0bde2-48f1-8f46-3fd4-9ab892d1679a.png)
Standard Convでは入力と同じチャネル数のフィルターを出力チャネルの数だけ準備します。この例だと3枚で1組のフィルターを16組準備して、入力画像を1組(3枚)のフィルターで畳み込んで、1枚の特徴マップを出力します。
DiCENetの論文に記されている図っぽく書くと以下のようになります。
  
* 入力チャネル$ D_{in} $、出力チャネル$ D_{out} $の例
![standard2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416091/9e582cf5-0bd6-8edb-90f9-1157b158dc74.png)




##Depth-wise Conv + Point-wise Conv
続いてDepth-wise ConvとPoint-wise Convの説明に入ります。
### Depth-wise Convolution(チャネル別畳み込み)
![チャネル別畳み込み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416091/ac49a286-b969-28dc-d027-ff983eff756f.png)
[Xception](https://arxiv.org/abs/1610.02357)[^1]というモデルでより計算量の少ないDepth-wise Convolutionという畳み込み手法が提案されました。この畳み込み処理ではフィルターを入力チャネル数と同じ枚数だけ準備し、1枚の入力に1枚のフィルターを畳み込んで、1枚の出力チャネルを出力します。従来の畳み込みと比べて計算量が減っているのがわかると思います。従来の畳み込み処理では1枚の出力特徴マップに入力の全チャネルの情報が集約されていますが、Depth-wise Convolutionでは1枚の出力特徴マップには1つのチャネルの情報しか入っていません。これがDepth-wise(深さごと)という名前の由来です(深さとチャネルは同じ意味)。しかし、これだけだとチャネル間が独立しているため、チャネル間の依存関係を考慮できません。そこでこのDepth-wise ConvolutionにPoint-wise Convolutionを組み合わせることでチャネル間の依存関係を考慮します。

### Point-wise Convolution(1×1畳み込み)
![11畳み込み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416091/92c4a47a-73c3-1e3e-686b-f883b95c145d.png)
この畳み込みは従来の畳み込みと同じ方法で畳み込むのですが、フィルターのサイズが1×1なのに注意してください。フィルターのサイズが1×1なので、出力特徴マップ1枚のサイズは入力と変わりませんが、この畳み込み処理のおかげでチャネル間での依存関係を考慮できるようになります。

### Depth-wise ConvとPoint-wise Conv
![Depth-wise ConvolutionとPoint-wise Convolution.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416091/51ab6277-233c-2ca0-a5d5-2d95b5acdec1.png)
従来の畳み込みとDepth-wise Convolution & Point-wise Convolutionを組み合わせたものだと後者のほうが計算量が少なく、精度が同等又はそれ以上となるみたいです。Xception、MobileNetのほかにもMobileNet V2, ShuffleNet, ShuffleNet V2などでも使用されています。
DiCENetの論文に記されている図っぽく書くと以下のようになります。

* 入力チャネル$ D_{in} $、出力チャネル$ D_{out} $の例
![depth point 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416091/5a50f777-2672-b781-950e-981d98ff7aba.png)





## Depth-wise + Point-wiseの問題点
上で述べたように、Depth-wise ConvolutionとPoint-wise Convolutionの組み合わせは従来の畳み込みの代替として普及し、いろいろなモデルに適用されるようになりました。しかし、それによって新たな問題が発生しました。Point-wise Convolutionの計算が、モデル全体の計算の8，9割以上を占めることになり、Point-wise Convolutionが計算上のボトルネックとなったのです。
#DiCENetの畳み込み
これらの問題点を解決すべく、ShuffleNetなどが提案されました。DiCENetもその一つです。
![DiCE unit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416091/9a369fc7-7ec1-98d4-a717-985ef1aaaa8d.png)


DiCENetのDimConvはDepth-wise Convolutionの代替として、EFuseはPoint-wise Convolutionの代替として提案されました。
## DimConv(Dimention-wise Convolution) 次元別の畳み込み
![DimConv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416091/09843e97-3bbf-0cb5-71fc-910e86608fc2.png)
上で述べたDepth-wise Convolutionはチャネル別の畳み込みでしたが、DimConvはそれぞれの次元(width:幅、height:高さ、channel:チャネル)別に畳み込みをします。まずは入力を3つに分岐させて、それぞれの次元別畳み込みを行います。そして、それぞれの出力3つの加重平均を取って一つのテンソルにまとめ、DimConvの出力とします。これのおかげでDepth-wise Convolutionよりも空間的な特徴を抽出できるみたいです。


## EFuse (Efficient Channel Fusion) 
![EFuse.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416091/335f26b6-d2ad-3b13-0de0-f8ff800786f9.png)

EFuseの入力はDimConvからの出力であり、EFuseはPoint-wise Convolutionのようにチャネル間の依存関係を考慮するための演算ですが、Point-wise Convolutionよりも計算量が大幅に少なくなるみたいです。まず入力を2つに分岐させてます。一方はGlobal Average Poolingの後に全結合層につなげて、シグモイドを適用します。もう一方では、チャネル別畳み込み(Depth-wise Convolution)をします。そして、それぞれの出力結果の要素ごとの乗算結果をEFuseの出力とします。

## DiCENetのネットワーク構成
ネットワークの構成はShuffleNev2を参考にしています。詳しくはShuffleNetv2の論文を読んでください。
![DiCENetネットワーク構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416091/1e27574f-1ea4-9be1-e005-251161f863c3.png)
出力と入力のチャネル数が同じ場合、ShuffleNetv2では
<b>Point-wise -> Depthwise -> Point-wise</b>
という構成になっているところをDiCENetは
<b>Point-wise ->  DiCE unit </b>
となっています。  
出力のチャネル数が入力のチャネル数より増える場合(with Stirde)、ShuffleNetv2では
<b>Point-wise -> Depthwise(stride=2) -> Point-wise</b>
という構成になっているところをDiCENetは
<b> Global Average Pooling -> DiCE unit -> Point-wise </b>
となっています。


<!--
# 参考文献
これから書きます。。。すみません 
-->