こんにちは!最近そういえばディープラーニングしてないなーって思ったのでリハビリがてら Tensorflow で遊んでみました。「何かデータセットで判別をしてみた」みたいな話ではなく、理論的な内容になります。
モデルは基本的な DNN を使います。 DNN って何?という人は下記の記事を参照ください。
このモデルは線形判別の手法を使っているのに、線形判別できないようなデータも精度良く分けれるという特徴を持っています。なぜそんなことが可能なのかをモデルの挙動をグラフで可視化して眺めてみます。
DNN によるデータ点の幾何学的移動
ニューラルネットワークでレイヤーを移動する際、線形結合と活性化関数の二種類の計算が行われます。線形結合の部分では重みとバイアスによるアフィン変換でデータ点が移動し、活性化関数(今回はtanh)では非線形変換による各点作用でデータ点が移動します。
結論を言ってしまうと、上記のような線形判別できないパターンでも、適切な中間層数・次元を設定することで学習が上手くいき、そのパラメータでデータ点を移動させてみると綺麗に線形判別できるようなパターンになることがわかっています。即ち、ディープラーニングは空間をうねうね曲げまくっていい感じに線形判別できるようにデータを動かすものともいえます(動きがみえると結構面白いです)。
実験
ということで実際に動かしてみましょう。まずは、このデータの分類をやってみます。データ点は1000個ずつ計2000個あります。学習時の最適化手法は Adam でエポック数は20、バッチサイズは16としています。
モデルは中間層なしで設計してみました。結果ものせます。
Model: "DNN_model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_layer (Dense) (None, 2) 6
output_layer (Dense) (None, 1) 3
=================================================================
Total params: 9
Trainable params: 9
Non-trainable params: 0
_________________________________________________________________
正答率は大体90% 程です。このときのデータ点の移動は次のようになります。まだ線形判別はできなさそうで、正答率が100%にならない要因です。
次は中間層を1層だけ増やしてみます(中間層の次元は入力と同じ2にします)。
Model: "DNN_model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_layer (Dense) (None, 2) 6
hidden_layer1 (Dense) (None, 2) 6
output_layer (Dense) (None, 1) 3
=================================================================
Total params: 15
Trainable params: 15
Non-trainable params: 0
_________________________________________________________________
この場合も正答率は大体90% 程です。このときのデータ点の移動は次のようになります。中間層があるのでデータ点の移動は2回行われます。これでもまだ線形判別はできなさそうです(オレンジと青色が混ざっている部分があります)。
では、次は中間層の数を5つに増やしてみます。
Model: "DNN_model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_layer (Dense) (None, 2) 6
hidden_layer1 (Dense) (None, 2) 6
hidden_layer2 (Dense) (None, 2) 6
hidden_layer3 (Dense) (None, 2) 6
hidden_layer4 (Dense) (None, 2) 6
hidden_layer5 (Dense) (None, 2) 6
output_layer (Dense) (None, 1) 3
=================================================================
Total params: 39
Trainable params: 39
Non-trainable params: 0
_________________________________________________________________
この場合では正答率は100%になりました。このときのデータ点の移動は次のようになります。中間層の2層目から線形判別できそうで、3, 4, 5層では人が線を決めても判別できそうになってます。これこそがディープラーニングの凄さといえるでしょう。
では、もう一つの線形判別不可能なデータでも実験してみたいと思います。
実は、この形のデータは次元を拡張しないといくら中間層を増やしても上手くいきません。同じ次元での変換ではオレンジ色の円が青色の円の外に出ることはないからです。
試しに中間層10個・次元2でやってみます。
Model: "DNN_model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_layer (Dense) (None, 2) 6
hidden_layer1 (Dense) (None, 2) 6
hidden_layer2 (Dense) (None, 2) 6
hidden_layer3 (Dense) (None, 2) 6
hidden_layer4 (Dense) (None, 2) 6
hidden_layer5 (Dense) (None, 2) 6
hidden_layer6 (Dense) (None, 2) 6
hidden_layer7 (Dense) (None, 2) 6
hidden_layer8 (Dense) (None, 2) 6
hidden_layer9 (Dense) (None, 2) 6
hidden_layer10 (Dense) (None, 2) 6
output_layer (Dense) (None, 1) 3
=================================================================
Total params: 69
Trainable params: 69
Non-trainable params: 0
_________________________________________________________________
正答率は100%には届きませんが、95%程度になりました。このときのデータ点の移動は次のようになります。結構もがいてる様がみえて面白いですが、このモデルではどんなに頑張っても100%にはなりません。
ということで中間層数はそのままで次元を3に増やしてみます。
Model: "DNN_model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_layer (Dense) (None, 3) 9
hidden_layer1 (Dense) (None, 3) 12
hidden_layer2 (Dense) (None, 3) 12
hidden_layer3 (Dense) (None, 3) 12
hidden_layer4 (Dense) (None, 3) 12
hidden_layer5 (Dense) (None, 3) 12
hidden_layer6 (Dense) (None, 3) 12
hidden_layer7 (Dense) (None, 3) 12
hidden_layer8 (Dense) (None, 3) 12
hidden_layer9 (Dense) (None, 3) 12
hidden_layer10 (Dense) (None, 3) 12
output_layer (Dense) (None, 1) 4
=================================================================
Total params: 133
Trainable params: 133
Non-trainable params: 0
_________________________________________________________________
この場合は正答率が100%になります。このときのデータ点の移動は次のようになります(本当はxyz空間ですが、xy平面に射影しています)。中間層の5層目でオレンジの円が青色の円から飛び出しているのがわかります。これは、いままでxとyでしか空間を曲げていなかったのをz方向にまで拡張して曲げることでオレンジと青色を隔離することに成功しています(サポートベクターマシンのカーネルトリックみたいなものです)。なので、いままでの次元2の変換ではトーラスを保ったまま変化していたのが、今回の射影上ではぐちゃぐちゃになっています(3次元空間ではトーラスのままです)。
ということで、ディープラーニングで遊んだだけの記事でした。この辺りの微分幾何学の話も面白いですね。最後まで読んでいただきありがとうございました。