機械学習の活性化関数の判定性能の比較実験をやってみました

# はじめに

この記事ではニューラルネットワークの
各種の活性化関数の判定性能の比較結果をまとめています。

対象者として、
* 活性化関数のざっくりとした比較を知りたい人
* どの活性化関数を採用するか検討してる人
* 機械学習を始めようとしてる人
などを想定してます。

# 活性化関数とは
あるニューロンの入力合計から、出力を決定するための関数です

![ニューロン.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/09d616dc-6886-3e4e-e926-6d1b9eae659f.jpeg)

```math
y = f(\sum_{k=1}^{n} ω_i*x_i + b) \\
```

f(x)が活性化関数です

## 本記事で比較する活性化関数

* tanh
* sigmoid
* hard_sigmoid
* softmax
* ReLU
* PReLU

入力層と中間層に上記活性化関数をセットして判定結果の比較を行います 

# 性能評価

## 実験環境

| ツール | 学習回数 | 勾配法 | 損失関数 |
| - | - | - | - |
| keras | 100回 | Adam | mean_squared_error |

## 実験対象
マイヤーの三角形の判定を採用しました
https://qiita.com/Oldcastle/items/49e1abdc0dd9c0d628c4

### 入力データ
三角形の3辺の長さを与えます

### 判定結果
* 三角形なのか、  
* 直角三角形なのか、  
* 二等辺三角形なのか、  
* 正三角形なのか  
を判定します

## 評価方法

11種類の確認条件の正解数で活性化関数の性能評価を行います  

### 評価条件
* 1 三角形を三角形と判定できるか？  
* 2 大きい直角三角形を判定できるか？  
* 3 小さい直角三角形を判定できるか？  
* 4 大きい二等辺三角形を判定できるか？  
* 5 小さい二等辺三角形を判定できるか？  
* 6 大きい正三角形を判定できるか？  
* 7 小さい正三角形を判定できるか？  
* 8 三角形が成立しない3辺の長さ（短い）の時に三角形と判定しないか？  
* 9 三角形が成立しない3辺の長さ（長い）の時に三角形と判定しないか？  
* 10 1辺が0の場合に三角形と判定しないか？  
* 11 1辺がマイナスの場合に三角形と判定しないか？  

### 評価条件の採点方法
* 期待値と結果が完全一致の場合  
    → 正解として、1点 とカウントします  
* 期待値と結果が、一致なし、もしくは、部分一致、の場合
    → 間違いとして、0点 とカウントします  

    例
    3辺の長さを3,4,5とした場合、
    直角三角形と判断したら、"正解"とし、 
    ただの三角形と判断したら、"間違い"とし、 
    三角形ではないと判断したら、"間違い"とします

活性化関数毎の評価結果の合計点で判定性能を評価します

#### 備考
活性化関数毎の得手不得手があるので、
この結果をもって活性化関数の優劣を判断することはできませんが、
判断の材料の1つにはなるかと考えています

## tanh

### 概要

* 主に出力層で採用されることが多い
* 出力範囲 -1.0 ～ +1.0

```math
y = \tanh x = \cfrac{e^x - e^{-x}}{e^x + e^{-x}}
```

### 結果

#### 所感
出力層に現在でも採用される人気関数だけあって、正解数が多い
けど、中間層に採用しちゃうと、出力範囲が-1～+1なのがダメなのか、いまいちな気がします

#### モデル
![tanh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/c77cf2f0-894e-0312-e4b9-e3f668ef6a53.png)

#### 判定結果の表

| 判定結果 | 入力 | 期待値 | 期待値(数値) | 結果 | 結果(数値) |
| -        | -    | -      | -            | -    | -          |
| 0 | <span style="color: red; ">間違い</span> | 6.0,4.0,5.0| ただの三角形  | 1,0,0,0,e=tri | 直角三角形,Righttriangle | 0.999986,0.989156,-0.037906,0.003898 |
| 1 | 正解 | 6.0,8.0,10.0| 直角三角形0  | 1,1,0,0,e=Right | 直角三角形,Righttriangle | 0.999968,0.977978,0.006283,-0.000291 |
| 2 | 正解 | 3.0,4.0,5.0| 直角三角形1  | 1,1,0,0,e=Right | 直角三角形,Righttriangle | 0.999965,0.974399,-0.008991,-0.000434 |
| 3 | 正解 | 8.0,8.0,10.0| 二等辺三角形0  | 1,0,1,0,e=Iso | 二等辺三角形,Isoscelestriangle | 0.999991,-0.003010,0.981360,-0.000403 |
| 4 | 正解 | 4.0,4.0,5.0| 二等辺三角形1  | 1,0,1,0,e=Iso | 二等辺三角形,Isoscelestriangle | 0.999993,0.005119,0.996532,0.001854 |
| 5 | 正解 | 8.0,8.0,8.0| 正三角形0  | 1,0,1,1,e=Equ | 正三角形,Equilateraltriangle | 0.999996,-0.033165,0.999980,0.996219 |
| 6 | 正解 | 2.0,2.0,2.0| 正三角形1  | 1,0,1,1,e=Equ | 正三角形,Equilateraltriangle | 0.999994,0.003263,0.999997,0.985353 |
| 7 | 正解 | 4.0,4.0,9.0| 三角形ではない0  | 0,0,0,0,e=No | 三角形ではない,no | -0.009939,0.018703,0.158450,-0.003449 |
| 8 | 正解 | 2.0,2.0,5.0| 三角形ではない1  | 0,0,0,0,e=No | 三角形ではない,no | -0.015225,0.027436,-0.041762,-0.002854 |
| 9 | 正解 | 4.0,0.0,9.0| 三角形ではない2  | 0,0,0,0,e=No | 三角形ではない,no | 0.000729,0.030665,-0.060030,-0.003380 |
| 10 | 正解 | -1.0,4.0,5.0| 三角形ではない3  | 0,0,0,0,e=No | 三角形ではない,no | 0.035658,-0.010008,0.160421,0.000067 |
正解数 = 10

![tanh.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/c3778520-686e-9fbf-89fe-37c8319f7090.jpeg)


## sigmoid

### 概要

* ReLUの登場前は採用事例が多かった  
* 出力範囲 0.0 ～ +1.0  

```math
y = \cfrac{1}{1 + e^{-x}}
```

### 結果

#### 所感
往年の人気関数だけあって、正解数は多い
けど、期待値と判定結果のギャップが多いのが気になりますね

#### モデル
![sigmoid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/8bdce0e0-0b51-6aaa-3471-b2c52d7f3c22.png)

#### 判定結果の表
| 判定結果 | 入力 | 期待値 | 期待値(数値) | 結果 | 結果(数値) |
| -        | -    | -      | -            | -    | -          |
| 0 | <span style="color: red; ">間違い</span> | 6.0,4.0,5.0| ただの三角形  | 1,0,0,0,e=tri | 直角三角形,Righttriangle | 0.999448,0.980894,0.132899,0.024337 |
| 1 | 正解 | 6.0,8.0,10.0| 直角三角形0  | 1,1,0,0,e=Right | 直角三角形,Righttriangle | 0.995973,0.933592,-0.008989,0.000568 |
| 2 | 正解 | 3.0,4.0,5.0| 直角三角形1  | 1,1,0,0,e=Right | 直角三角形,Righttriangle | 0.988942,0.957374,0.000931,0.004329 |
| 3 | 正解 | 8.0,8.0,10.0| 二等辺三角形0  | 1,0,1,0,e=Iso | 二等辺三角形,Isoscelestriangle | 0.999998,-0.039776,0.995581,-0.039327 |
| 4 | 正解 | 4.0,4.0,5.0| 二等辺三角形1  | 1,0,1,0,e=Iso | 二等辺三角形,Isoscelestriangle | 1.000000,-0.000101,0.992283,0.001879 |
| 5 | 正解 | 8.0,8.0,8.0| 正三角形0  | 1,0,1,1,e=Equ | 正三角形,Equilateraltriangle | 1.000000,-0.002798,0.999990,0.975780 |
| 6 | 正解 | 2.0,2.0,2.0| 正三角形1  | 1,0,1,1,e=Equ | 正三角形,Equilateraltriangle | 1.000000,0.033016,0.999420,0.940484 |
| 7 | 正解 | 4.0,4.0,9.0| 三角形ではない0  | 0,0,0,0,e=No | 三角形ではない,no | 0.260340,0.048332,0.439551,-0.029142 |
| 8 | 正解 | 2.0,2.0,5.0| 三角形ではない1  | 0,0,0,0,e=No | 三角形ではない,no | 0.126301,0.004408,0.416081,0.013138 |
| 9 | 正解 | 4.0,0.0,9.0| 三角形ではない2  | 0,0,0,0,e=No | 三角形ではない,no | -0.030247,0.072398,-0.067080,0.008566 |
| 10 | 正解 | -1.0,4.0,5.0| 三角形ではない3  | 0,0,0,0,e=No | 三角形ではない,no | -0.278447,-0.097397,-0.187003,-0.001929 |
正解数 = 10

![sigmoid.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/c0435d70-5aaa-b72c-fad2-1c76791fcb69.jpeg)

## hard_sigmoid

### 概要

```math
y = \left\{
  \begin{array}{cc}
    1 & (x \gt 2.5) \\
    0.2x + 0.5 & (-2.5 \le x \le 2.5) \\
    0 & (x \lt -2.5)
  \end{array}
\right.
```

### 結果

#### 所感
正解数は多いけど、期待値と判定結果のギャップが多い傾向にある気がします
高速化のsigmoidらしいけど、ここまで期待値と判定結果のギャップがあると採用するには微妙だな

#### モデル
![hard_sigmoid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/58d1d579-e13e-f930-2bb0-e955a8b264a1.png)

#### 判定結果の表
| 判定結果 | 入力 | 期待値 | 期待値(数値) | 結果 | 結果(数値) |
| -        | -    | -      | -            | -    | -          |
| 0 | 正解 | 6.0,4.0,5.0| ただの三角形  | 1,0,0,0,e=tri | ただの三角形,triangle | 0.994354,0.574325,0.787680,-0.161254 |
| 1 | <span style="color: red; ">間違い</span> | 6.0,8.0,10.0| 直角三角形0  | 1,1,0,0,e=Right | ただの三角形,triangle | 0.974759,0.898180,-0.047856,-0.015284 |
| 2 | <span style="color: red; ">間違い</span> | 3.0,4.0,5.0| 直角三角形1  | 1,1,0,0,e=Right | ただの三角形,triangle | 0.979049,0.797488,0.038165,0.003264 |
| 3 | 正解 | 8.0,8.0,10.0| 二等辺三角形0  | 1,0,1,0,e=Iso | 二等辺三角形,Isoscelestriangle | 0.999783,0.043587,0.999193,0.019981 |
| 4 | 正解 | 4.0,4.0,5.0| 二等辺三角形1  | 1,0,1,0,e=Iso | 二等辺三角形,Isoscelestriangle | 0.998371,0.131260,0.987543,0.025992 |
| 5 | <span style="color: red; ">間違い</span> | 8.0,8.0,8.0| 正三角形0  | 1,0,1,1,e=Equ | 二等辺三角形,Isoscelestriangle | 0.999992,-0.081960,0.999996,0.455133 |
| 6 | <span style="color: red; ">間違い</span> | 2.0,2.0,2.0| 正三角形1  | 1,0,1,1,e=Equ | 二等辺三角形,Isoscelestriangle | 0.997360,0.115261,0.989323,0.248780 |
| 7 | 正解 | 4.0,4.0,9.0| 三角形ではない0  | 0,0,0,0,e=No | 三角形ではない,no | 0.682961,-0.292177,0.712280,0.087241 |
| 8 | 正解 | 2.0,2.0,5.0| 三角形ではない1  | 0,0,0,0,e=No | 三角形ではない,no | 0.800713,-0.102048,0.608231,0.088516 |
| 9 | 正解 | 4.0,0.0,9.0| 三角形ではない2  | 0,0,0,0,e=No | 三角形ではない,no | -0.240946,0.417336,-0.424005,-0.135801 |
| 10 | 正解 | -1.0,4.0,5.0| 三角形ではない3  | 0,0,0,0,e=No | 三角形ではない,no | 0.344344,0.097496,0.349864,0.037688 |
正解数 = 7

![hard_sigmoid.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/f9017162-85ed-a11c-7dff-d8ab5247c9b6.jpeg)

## softmax

### 概要

* 分類問題の出力層で採用が多い
* 出力範囲 0.0 ～ +1.0

```math
y_i = \cfrac{e^{x_i}}{\displaystyle\sum_{k=1}^{n}{e^{x_k}}} \quad (i = 1, 2, \ldots, n)
```

### 結果

#### 所感
本実験は選択じゃないので、不利なのはわかってたけど、
正解数も期待値と判定結果のギャップも善戦したんじゃないかと思います

#### モデル
![softmax.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/17682248-01c5-81a7-7598-b2292c6d255b.png)

#### 判定結果の表
| 判定結果 | 入力 | 期待値 | 期待値(数値) | 結果 | 結果(数値) |
| -        | -    | -      | -            | -    | -          |
| 0 | 正解 | 6.0,4.0,5.0| ただの三角形  | 1,0,0,0,e=tri | ただの三角形,triangle | 1.000000,0.720018,0.858468,-0.016365 |
| 1 | 正解 | 6.0,8.0,10.0| 直角三角形0  | 1,1,0,0,e=Right | 直角三角形,Righttriangle | 1.000000,0.928948,0.007623,-0.026165 |
| 2 | <span style="color: red; ">間違い</span> | 3.0,4.0,5.0| 直角三角形1  | 1,1,0,0,e=Right | ただの三角形,triangle | 0.999999,0.893827,0.029419,0.005216 |
| 3 | 正解 | 8.0,8.0,10.0| 二等辺三角形0  | 1,0,1,0,e=Iso | 二等辺三角形,Isoscelestriangle | 0.999981,0.110358,0.989321,0.057350 |
| 4 | 正解 | 4.0,4.0,5.0| 二等辺三角形1  | 1,0,1,0,e=Iso | 二等辺三角形,Isoscelestriangle | 0.999657,0.022028,0.995175,-0.055756 |
| 5 | <span style="color: red; ">間違い</span> | 8.0,8.0,8.0| 正三角形0  | 1,0,1,1,e=Equ | 二等辺三角形,Isoscelestriangle | 0.999846,0.017986,1.000000,0.873808 |
| 6 | 正解 | 2.0,2.0,2.0| 正三角形1  | 1,0,1,1,e=Equ | 正三角形,Equilateraltriangle | 0.999870,-0.012967,1.000000,0.999764 |
| 7 | 正解 | 4.0,4.0,9.0| 三角形ではない0  | 0,0,0,0,e=No | 三角形ではない,no | 0.868875,-0.046845,0.949259,0.007745 |
| 8 | 正解 | 2.0,2.0,5.0| 三角形ではない1  | 0,0,0,0,e=No | 三角形ではない,no | 0.869092,-0.045468,0.948255,0.006970 |
| 9 | 正解 | 4.0,0.0,9.0| 三角形ではない2  | 0,0,0,0,e=No | 三角形ではない,no | -0.006356,0.003223,-0.000669,-0.000748 |
| 10 | 正解 | -1.0,4.0,5.0| 三角形ではない3  | 0,0,0,0,e=No | 三角形ではない,no | -0.006803,0.003141,-0.001434,-0.002151 |
正解数 = 9

![softmax.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/e9e35d60-5ef2-3364-e97b-9c1daf928ef2.jpeg)


## relu

### 概要

```math
y = \left\{
  \begin{array}{cc}
    x & (x \gt 0) \\
    0 & (x \le 0)
  \end{array}
\right.
```

### 結果

#### 所感
さすが人気の中間層に採用される関数だけあって、
正解数も期待値と判定結果のギャップも優れた結果をだしました
優先的に採用を検討したい関数ですね

#### モデル
![relu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/3723c1dc-ed65-1ed8-f9d8-1e7b5204ef51.png)

#### 判定結果の表
| 判定結果 | 入力 | 期待値 | 期待値(数値) | 結果 | 結果(数値) |
| -        | -    | -      | -            | -    | -          |
| 0 | <span style="color: red; ">間違い</span> | 6.0,4.0,5.0| ただの三角形  | 1,0,0,0,e=tri | 直角三角形,Righttriangle | 1.000000,0.902778,0.002665,-0.004156 |
| 1 | 正解 | 6.0,8.0,10.0| 直角三角形0  | 1,1,0,0,e=Right | 直角三角形,Righttriangle | 1.000000,0.965110,-0.003764,-0.005236 |
| 2 | 正解 | 3.0,4.0,5.0| 直角三角形1  | 1,1,0,0,e=Right | 直角三角形,Righttriangle | 1.000000,0.950468,-0.000710,-0.003806 |
| 3 | 正解 | 8.0,8.0,10.0| 二等辺三角形0  | 1,0,1,0,e=Iso | 二等辺三角形,Isoscelestriangle | 1.000000,-0.060001,0.974667,-0.022778 |
| 4 | 正解 | 4.0,4.0,5.0| 二等辺三角形1  | 1,0,1,0,e=Iso | 二等辺三角形,Isoscelestriangle | 1.000000,-0.029514,0.999140,-0.016192 |
| 5 | 正解 | 8.0,8.0,8.0| 正三角形0  | 1,0,1,1,e=Equ | 正三角形,Equilateraltriangle | 1.000000,-0.021102,1.000000,1.000000 |
| 6 | 正解 | 2.0,2.0,2.0| 正三角形1  | 1,0,1,1,e=Equ | 正三角形,Equilateraltriangle | 1.000000,-0.035200,1.000000,0.999963 |
| 7 | 正解 | 4.0,4.0,9.0| 三角形ではない0  | 0,0,0,0,e=No | 三角形ではない,no | -0.014690,-0.043248,0.003072,-0.013980 |
| 8 | 正解 | 2.0,2.0,5.0| 三角形ではない1  | 0,0,0,0,e=No | 三角形ではない,no | -0.015742,-0.068460,0.024393,-0.004752 |
| 9 | 正解 | 4.0,0.0,9.0| 三角形ではない2  | 0,0,0,0,e=No | 三角形ではない,no | -0.000451,-0.024576,0.006207,-0.015179 |
| 10 | 正解 | -1.0,4.0,5.0| 三角形ではない3  | 0,0,0,0,e=No | 三角形ではない,no | 0.000248,-0.020529,-0.006891,-0.003094 |
正解数 = 10

![relu.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/e67668a5-74bc-2b86-f273-d20c30ba574d.jpeg)


## PReLU

### 概要

```math
y = \left\{
  \begin{array}{cc}
    x & (x \gt 0) \\
    α*x & (x \le 0)
  \end{array}
\right.
```

αは学習によって動的に変わる

### 結果

#### 所感
ReLUを改良しただけあって、最高の成績をだしました
期待値と判定結果のギャップもほぼ０なので、文句のつけようもありません
今、採用するなら最有力かな

#### モデル
![PReLU.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/b2a8a15b-5e3b-94ae-cd6d-771bd1845caa.png)

#### 判定結果の表
|  | 入力 | 期待値 | 期待値(数値) | 結果 | 結果(数値) |
| -        | -    | -      | -            | -    | -          |
| 0 | 正解 | 6.0,4.0,5.0| ただの三角形  | 1,0,0,0,e=tri | ただの三角形,triangle | 0.994183,0.007635,0.056884,0.000834 |
| 1 | 正解 | 6.0,8.0,10.0| 直角三角形0  | 1,1,0,0,e=Right | 直角三角形,Righttriangle | 1.000851,1.002835,0.000000,0.000012 |
| 2 | 正解 | 3.0,4.0,5.0| 直角三角形1  | 1,1,0,0,e=Right | 直角三角形,Righttriangle | 0.997850,0.991651,0.000000,0.000019 |
| 3 | 正解 | 8.0,8.0,10.0| 二等辺三角形0  | 1,0,1,0,e=Iso | 二等辺三角形,Isoscelestriangle | 1.000700,0.003654,0.996864,0.000444 |
| 4 | 正解 | 4.0,4.0,5.0| 二等辺三角形1  | 1,0,1,0,e=Iso | 二等辺三角形,Isoscelestriangle | 1.001190,0.000726,0.993479,0.002013 |
| 5 | 正解 | 8.0,8.0,8.0| 正三角形0  | 1,0,1,1,e=Equ | 正三角形,Equilateraltriangle | 1.001208,0.000781,1.003762,1.008479 |
| 6 | 正解 | 2.0,2.0,2.0| 正三角形1  | 1,0,1,1,e=Equ | 正三角形,Equilateraltriangle | 0.988216,0.008406,1.000365,1.022394 |
| 7 | 正解 | 4.0,4.0,9.0| 三角形ではない0  | 0,0,0,0,e=No | 三角形ではない,no | 0.004798,0.001404,0.000000,0.004193 |
| 8 | 正解 | 2.0,2.0,5.0| 三角形ではない1  | 0,0,0,0,e=No | 三角形ではない,no | 0.009218,0.001693,0.000000,0.001662 |
| 9 | 正解 | 4.0,0.0,9.0| 三角形ではない2  | 0,0,0,0,e=No | 三角形ではない,no | 0.004954,0.002217,0.000000,0.010974 |
| 10 | 正解 | -1.0,4.0,5.0| 三角形ではない3  | 0,0,0,0,e=No | 三角形ではない,no | 0.006179,0.006016,0.000000,0.011212 |
正解数 = 11

![PReLU_g.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/e3e20590-6193-9fee-650c-c3d4745d39b3.png)



# まとめ

| 活性化関数 | 判定性能（11点満点） | 期待値とのギャップ |考察　|
| - | - | - | - |
| tanh | 10 | 1.021199 | 入力層の人気の活性化関数だけあって、判定性能は比較的良い結果をだしました。しかし、sigmoidと同様に最小値と最大値の付近の判定性能の鈍化があるように思いました。 |
| softmax | 9 | 2.150410 | 分類の判定ではないので、不利な条件での実験となりました。そのため、判定性能が高くでませんでした。データの条件次第では性能を発揮するように思いました  |
| sigmoid | 10 | 1.257565 | 出力の範囲が-1～+1なので、最小値と最大値の付近の判定性能が鈍化したように思いました。標準化した訓練データであればもっと判定性能があがるかもしれません  |
| hard_sigmoid | 7 | 2.170923 | sigmoidと判定性能は同じ結果となりました。　|
| ReLU | 10 | 0.914075 | 隠れ層の人気の活性化関数だけあって判定性能が高い結果となりました。この実験では入力データにマイナスを含むことが判定性能を少し悪化させたように思いました |
| PReLU | 11 | 0.069040 | この実験では最高の判定性能を出す結果となりました。ReLUのマイナス対応版だけあってマイナスがあっても判定性能の悪化がなさそうです。隠れ層はReLUかPReLUをデータの傾向で使い分けする感じでしょうか |

![まとめ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/193dee68-eec1-9978-2575-0685f740179a.png)



## 勾配法と損失関数について
* 本実験では固定していますが勾配法と損失関数の組み合わせでも判定性能が変わるので、いろいろ試して見る必要があるかと思います  

## 活性化関数の選び方
* 実行時間と判定性能の兼ね合いで活性化関数を決めるとよいかと思います  

## モデルの調整について
* 期待値とのギャップと正解数の比例関係をみると、まずは期待値とのギャップを小さくするような、
活性化関数を選んでから、層やdenseを調整したほうがよいかと思います  

# コード

~~~python
# -*- coding: utf-8 -*-
import numpy as np
import os.path
import time
import csv

from tensorflow.keras.models import Sequential, model_from_json
from tensorflow.keras.layers import Dense, Activation, PReLU
from tensorflow.keras.utils import plot_model
from tensorflow.keras import backend as K


X_train = []
y_train = []

def normalize(in_v):
  out = in_v
  out = out / 10.0
  return out

def secification(x,y,z):
  
  in_data = [x,y,z]
  in_data.sort()
  
#  print("in_data:")
#  print(in_data)
  in1 = normalize(in_data[0])
  in2 = normalize(in_data[1])
  in3 = normalize(in_data[2])
  
  d1 = in1 + in2
  d2 = in2 + in3
  d3 = in3 + in1

  return in1,in2,in3,d1,d2,d3

def print_judge(in_d):
  if in_d[0,0] > 0.9:
    if in_d[0,1] > 0.9:
      print('result_judge,Righttriangle')
      return
    if in_d[0,2] > 0.9:
      if in_d[0,3] >0.9:
        print('result_judge,Equilateraltriangle')
      else:
        print('result_judge,Isoscelestriangle')
      return
    print('result_judge,triangle')
  else:
    print('result_judge,no')

def judge_predict(model, in_str, x, y, z):
#  print('------------------------')
  print()
  print("input," + str(x) + ',' + str(y) + ',' + str(z) + ',' + in_str)
  v_test = [secification(x,y,z)]
  print("input_val,%f,%f,%f,%f,%f,%f" %( v_test[0][0],v_test[0][1],v_test[0][2],v_test[0][3],v_test[0][4],v_test[0][5] ) )
  classes = model.predict(v_test)
  print("result_val,%f,%f,%f,%f" %( classes[0][0],classes[0][1],classes[0][2],classes[0][3] ) )
#  print(classes)
  print_judge(classes)

with open('../data/keras_triangle.csv') as f:
  reader = csv.reader(f)
  for row in reader:
#    print(row)
    r0 = float(row[0])
    r1 = float(row[1])
    r2 = float(row[2])

    if float(row[5]) != 0.0 or float(row[6]) != 0.0:
      # 二等辺三角形 正三角形
      for i in range(100):
        X_train.append(secification(r0,r1,r2))
        y_train.append([float(row[3]),float(row[4]),float(row[5]),float(row[6]) ])
    elif float(row[4]) !=0.0:
      # 直角三角形
      for i in range(1000):
        X_train.append(secification(r0,r1,r2))
        y_train.append([float(row[3]),float(row[4]),float(row[5]),float(row[6]) ])
    else:
      X_train.append(secification(r0,r1,r2))
      y_train.append([float(row[3]),float(row[4]),float(row[5]),float(row[6]) ])

#  print(X_train)
#  print(y_train)

activate = ['PReLU','tanh', 'sigmoid', 'softmax', 'relu', 'hard_sigmoid']

for act in activate:
  print('activate,' + act)
  st_time = int(time.time() * 1000)
  model = Sequential()

  if act != 'PReLU':
    model.add(Dense(units=6, activation=act))
    model.add(Dense(units=36, activation= act ))
    model.add(Dense(units=4, activation='tanh'))
  else:
    model.add(Dense(units=6))
    model.add(PReLU())
    model.add(Dense(units=36))
    model.add(PReLU())
    model.add(Dense(units=4))
    model.add(PReLU())

  model.compile(optimizer='Adam', loss='mean_squared_error')

  model.fit(
    X_train,
    y_train,
    epochs=100,
    batch_size=32,
    verbose=0 # log off
    )

  loss_and_metrics = model.evaluate(X_train, y_train, batch_size=32)
  print('Test loss:', loss_and_metrics)

  classes = model.predict(X_train, batch_size=32)
  print(classes)

  np.set_printoptions(precision=3)

  judge_predict( model, "ok,1,0,0,0,e=tri", 6.0, 4.0, 5.0 )
  judge_predict( model, "ok,1,1,0,0,e=Right", 6.0, 8.0, 10.0 )
  judge_predict( model, "ok,1,1,0,0,e=Right", 3.0, 4.0, 5.0 )
  judge_predict( model, "ok,1,0,1,0,e=Iso", 8.0, 8.0, 10.0 )
  judge_predict( model, "ok,1,0,1,0,e=Iso", 4.0, 4.0, 5.0 )
  judge_predict( model, "ok,1,0,1,1,e=Equ", 8.0, 8.0, 8.0 )
  judge_predict( model, "ok,1,0,1,1,e=Equ", 2.0, 2.0, 2.0 )
  judge_predict( model, "ng,0,0,0,0,e=No", 4.0, 4.0, 9.0 )
  judge_predict( model, "ng,0,0,0,0,e=No", 2.0, 2.0, 5.0 )
  judge_predict( model, "ng,0,0,0,0,e=No", 4.0, 0.0, 9.0 )
  judge_predict( model, "ng,0,0,0,0,e=No", -1.0, 4.0, 5.0 )

  ed_time = int(time.time() * 1000)
  
  print("time,st = %d, ed = %d, t = %d ms" % (st_time, ed_time, ed_time-st_time) )
  
  model.summary()

  # モデルの概要図をファイル出力
  png_file = act + ".png"
  plot_model(model, to_file= png_file, show_shapes=True)
  
  K.clear_session() # init


~~~