TensorFlowでALICesを判別(顔判定モデル作成)

# 目的
機械学習について学んでみたいと思った。
よく聞くTensorFlowの入門編として、顔判定モデルを作成した。
ALICesの二人は似ていると噂されており、機械学習でも判別できるのか試してみた。

# 参考ページ
- https://qiita.com/Ringa_hyj/items/3b4b6ea1db30e30134eb
- https://www.pc-koubou.jp/magazine/15856

# 環境準備
- AnacondaのCreateから、Python3.6.13を選択して仮想環境作成
- 各ライブラリインストール
```
pip install --ignore-installed --upgrade tensorflow
pip install python-opencv
pip install tensorflow-hub
pip install google_images_download
```

# データ準備
## 画像収集
- 画像をgoogle_images_downloadを使用して集める。
```
googleimagesdownload --keywords "黒崎真音"
googleimagesdownload --keywords "神田沙也加"
```
- google_images_downloadは、pip installによって入れたバージョンではエラーが出てしまうので、
下記コマンドで別バージョンをインストール
```
git clone https://github.com/Joeclinton1/google-images-download.git gid-joeclinton
pip install -e gid-joeclinton
```
- ダウンロードされたファイルは「downloads/黒崎真音」のように検索ワードでフォルダが作成され、その中に入っている
この後の切り出しで日本語はエラーになるため、「downloads/maon」等に変更する

## 顔切り出し
- 先ほど収集した画像から顔を切り出す
- 参考　https://chusotsu-program.com/opencv-face-trim/

- 顔検出モデルをダウンロードし、下記facedetect.pyと同じフォルダに配置
https://github.com/opencv/opencv/tree/master/data/haarcascades
haarcascade_frontalface_alt2.xml

```python:facedetect.py
import cv2
import glob
 
cascade_file = 'haarcascade_frontalface_alt2.xml'
#cascade_file = 'haarcascade_frontalface_default.xml'
cascade_face = cv2.CascadeClassifier(cascade_file)

files = glob.glob("./downloads/maon/*")
cnt=0
for file in files:
    
    image = cv2.imread(file)
    #モデルを読み込む
 
    # 顔を探して配列で返す
    face_list = cascade_face.detectMultiScale(image, minSize=(20, 20))
    for i, (x, y, w, h) in enumerate(face_list):
        trim = image[y:y+h,x:x+w]
        cv2.imwrite('cut' + str(cnt+1) + '.jpg', trim)
        cnt += 1
```

- 切り出したファイルを下記のようなフォルダ階層に移動する
「photos」には学習用のファイル、「test」には判定用のファイルを格納する
photos
  └─ maon
　　　　  └─ cut01.jpg
　　　　  └─ cut02.jpg
　　　　  └─ cut03.jpg
　　　　　　　　⋮
└─ sayaka
　　　　  └─ cut01.jpg
　　　　  └─ cut02.jpg
　　　　  └─ cut03.jpg
test
  └─ maon1.jpg
  └─ sayaka1.jpg



# 再学習
- retrain.pyを使用して再学習を行う
https://github.com/tensorflow/hub/blob/master/examples/image_retraining/retrain.py
```
python retrain.py --image_dir photos
```

- tensorflow 2.6.2だと、

> ModuleNotFoundError: No module named 'tensorflow.contrib'

のエラーが出た。
tensorflow.contribを利用できるのは1.15らしいので再インストール
```
pip install tensorflow==1.15
```

- 下記のような警告が出るが、実行はできる
> W0420 20:53:19.828737 10704 module_wrapper.py:139] From retrain.py:721: The name tf.summary.histogram is deprecated. Please use tf.compat.v1.summary.histogram instead.


- 学習開始されると下記のような結果がずらっと表示されていく
```
I0420 20:53:35.489253 10704 retrain.py:1116] 2022-04-20 20:53:35.489253: Step 0: Train accuracy = 68.0%
I0420 20:53:35.489253 10704 retrain.py:1118] 2022-04-20 20:53:35.489253: Step 0: Cross entropy = 0.677935
I0420 20:53:36.054380 10704 retrain.py:1137] 2022-04-20 20:53:36.054380: Step 0: Validation accuracy = 64.0% (N=100)
I0420 20:53:37.083724 10704 retrain.py:1116] 2022-04-20 20:53:37.083724: Step 10: Train accuracy = 79.0%
I0420 20:53:37.084602 10704 retrain.py:1118] 2022-04-20 20:53:37.084602: Step 10: Cross entropy = 0.550215
I0420 20:53:37.191247 10704 retrain.py:1137] 2022-04-20 20:53:37.191247: Step 10: Validation accuracy = 60.0% (N=100)
I0420 20:53:38.198427 10704 retrain.py:1116] 2022-04-20 20:53:38.198427: Step 20: Train accuracy = 87.0%
I0420 20:53:38.199245 10704 retrain.py:1118] 2022-04-20 20:53:38.199245: Step 20: Cross entropy = 0.509002
I0420 20:53:38.303275 10704 retrain.py:1137] 2022-04-20 20:53:38.303275: Step 20: Validation accuracy = 79.0% (N=100)
I0420 20:53:39.310761 10704 retrain.py:1116] 2022-04-20 20:53:39.310761: Step 30: Train accuracy = 90.0%
I0420 20:53:39.311750 10704 retrain.py:1118] 2022-04-20 20:53:39.311750: Step 30: Cross entropy = 0.458924
I0420 20:53:39.415735 10704 retrain.py:1137] 2022-04-20 20:53:39.415736: Step 30: Validation accuracy = 77.0% (N=100)
I0420 20:53:40.419135 10704 retrain.py:1116] 2022-04-20 20:53:40.419135: Step 40: Train accuracy = 98.0%
I0420 20:53:40.420129 10704 retrain.py:1118] 2022-04-20 20:53:40.420129: Step 40: Cross entropy = 0.406557
I0420 20:53:40.525718 10704 retrain.py:1137] 2022-04-20 20:53:40.525719: Step 40: Validation accuracy = 74.0% (N=100)
I0420 20:53:41.537707 10704 retrain.py:1116] 2022-04-20 20:53:41.536726: Step 50: Train accuracy = 83.0%
I0420 20:53:41.537707 10704 retrain.py:1118] 2022-04-20 20:53:41.537707: Step 50: Cross entropy = 0.375709
I0420 20:53:41.640053 10704 retrain.py:1137] 2022-04-20 20:53:41.640053: Step 50: Validation accuracy = 75.0% (N=100)
I0420 20:53:42.653381 10704 retrain.py:1116] 2022-04-20 20:53:42.652416: Step 60: Train accuracy = 93.0%
I0420 20:53:42.653381 10704 retrain.py:1118] 2022-04-20 20:53:42.653381: Step 60: Cross entropy = 0.349069
```


- 結果グラフ確認
tensorboardの下記コマンドで学習経緯のグラフが表示できる
よくわかっていないが、tensorboardを利用して学習の精度を確認できるのだと思う
この辺り勉強が必要
```
tensorboard --logdir /tmp/retrain_logs
```

# 判定
- label_image.pyを使用して判定を行う
- https://github.com/tensorflow/tensorflow/raw/master/tensorflow/examples/label_image/label_image.py
- 先ほど顔切り出し時に分けておいた「test」フォルダの画像を指定して判定を行う
## 判定結果(maon)
```
python label_image.py --graph /tmp/output_graph.pb --labels /tmp/output_labels.txt --input_layer Placeholder --output_layer final_result --image "test\maon1.jpg"
```
```
maon 0.79692864
sayaka 0.20307136
```
- 79%の確率で黒崎真音と判定
- まあまあ正確？

## 判定結果(sayaka)
```
python label_image.py --graph /tmp/output_graph.pb --labels /tmp/output_labels.txt --input_layer Placeholder --output_layer final_result --image "test\sayaka1.jpg"
```
```
sayaka 0.9979144
maon 0.002085614
```
- 99%の確率で神田沙也加と判定
- ほぼ100%！

# まとめ
- 判定は79%と99%の確率で正答できた。
- この差は、おそらく学習枚数の差？
    - maon:39枚
    - sayaka:59枚
- 学習画像枚数を水増しなどして実行してみたい