Watson API Visual Recognitionでラブライブキャラを判別するcustom classifierを作ってみる②

先日、IBM Cloudで提供されているWatson API Visual Recognitionを使ってラブライブのキャラを判別するカスタム分類器を作成しましたが、
・学習に使用した画像の枚数が少なく、確信度が低かった
・私の推しキャラ 絢瀬絵里（あやせえり）さんしか判別するすることができなかった（クラスを一つしか作っていなかった）
ため、より精度高く、**複数のキャラを判別することができる（クラスを複数作る）**を目標にカスタム分類器を作ります。

前回の記事
[Watson API Visual Recognitionでラブライブキャラを判別するcustom classifierを作ってみる](https://qiita.com/kino15/items/e146edd8d15e3ecca5c9)

#今回やること
絢瀬絵里さんの画像は絢瀬絵里、矢澤にこさんの画像は矢澤にこと判別することが出来るカスタム分類器を作成します。
（eriクラス、nikoクラス2つのクラスを作ります）

ラブライブを知らない方のために
![image.png](https://qiita-image-store.s3.amazonaws.com/0/191958/9e8a18b5-f493-b8a9-4dd0-b8df56d7060e.png)
左：絢瀬絵里、右：矢澤にこ

#下準備
１．二人のキャラクターの画像を50枚ずつ用意します。（Positive（正）事例、1キャラクターが写っている画像のみ）
Google画像検索でひたすら集めます
２．集めた画像をそれぞれ1つのフォルダに入れ、zipにします。（eri.zipとnico.zipを用意する）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/191958/ca65b396-c41f-81f3-8499-db32dc58dec7.png)
作成したカスタム分類器のテストをするためにテスト用のデータも用意しておきます（TestData.zip）
３．１で集めた以外のキャラクターの画像を10枚以上用意します。（ネガティブ（負）事例）
１，２と同様にzipにしておきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/191958/cb375193-993b-d546-d719-7dac84a27c11.png)

#カスタム分類器の作成
以下のコードでカスタム分類器を作成します

```py3:createClassifier.py
import json
from os.path import join, dirname
from os import environ
from watson_developer_cloud import VisualRecognitionV3

#apiキーはご自身のものを使用してください
visual_recognition = VisualRecognitionV3('2016-05-20', api_key='{api-key}')

with open(join(dirname(__file__), './lovelive_2/eri.zip'), 'rb') as eri, \
     open(join(dirname(__file__), './lovelive_2/nico.zip'), 'rb') as nico, \
     open(join(dirname(__file__), './lovelive_2/lovelive_others.zip'), 'rb') as others:
    result = visual_recognition.create_classifier('eri_nico', eri_positive_examples=eri, nico_positive_examples=nico, negative_examples=others)
    print(json.dumps(result, indent=2))
```

＊ポイント

```py3

eri_positive_examples=eri, nico_positive_examples=nico
```
eriクラス、nicoクラスを作成しています
*{class}_positive_examples=xxx*でクラス名、画像フォルダを指定します。

実行結果
eriクラス、nicoクラスができたのが確認できます

```json
{
  "classifier_id": "eri_nico_xxxxxxxx",
  "owner": "{ownerID}",
  "name": "eri_nico",
  "status": "training",
  "created": "2018-01-16T05:52:18.808Z",
  "classes": [
    {
      "class": "nico"
    },
    {
      "class": "eri"
    }
  ]
}
```

#作成したカスタム分類器のテストをする

こちらの５枚の画像で作成したカスタム分類器の性能を確かめてみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/191958/46b3dbd5-fa7d-bdf7-ae24-9c7d2cde9a61.png)
左二枚（eri_test.jpg、eri_test2.jpg）はeriクラス、右二枚（nico_test.jpg、niko_test2.jpg）はnicoクラスに分類されて欲しいです。
真ん中（kotori_test.jpg）は試しに入れておいた画像です。どちらのクラスに分類されてるのでしょうか？

```py3
import json
from os.path import join, dirname
from os import environ
from watson_developer_cloud import VisualRecognitionV3

visual_recognition = VisualRecognitionV3(
    #The release date of the version of the API you want to use.
    '2016-05-20',
    api_key = '')

image_path = join(dirname(__file__), './lovelive_2/TestData.zip')
classifier_ids_array = ['eri_nico_102677947']


with open(image_path, 'rb') as images_file_path:
    car_results = visual_recognition.classify(images_file = images_file_path,parameters=json.dumps({"owner": "9988f86c-0341-41f1-85b7-62a90def6c1c",'classifier_ids': classifier_ids_array}))
    f=open('result_customclassifier.json', 'w')
    f.write(json.dumps(car_results, indent=2))
    f.close()
    print(json.dumps(car_results, indent=2))
```

結果はこのようになりました！

```json
{
  "images_processed": 5,
  "custom_classes": 2,
  "images": [
    {
      "image": "./lovelive_2/TestData.zip/TestData/eri_test.jpg",
      "classifiers": []
    },
    {
      "image": "./lovelive_2/TestData.zip/TestData/eri_test2.jpg",
      "classifiers": [
        {
          "classes": [
            {
              "score": 0.593679,
              "class": "eri"
            }
          ],
          "classifier_id": "eri_nico_102677947",
          "name": "eri_nico"
        }
      ]
    },
    {
      "image": "./lovelive_2/TestData.zip/TestData/kotori_test.jpg",
      "classifiers": [
        {
          "classes": [
            {
              "score": 0.550993,
              "class": "eri"
            }
          ],
          "classifier_id": "eri_nico_102677947",
          "name": "eri_nico"
        }
      ]
    },
    {
      "image": "./lovelive_2/TestData.zip/TestData/nico_test.jpg",
      "classifiers": []
    },
    {
      "image": "./lovelive_2/TestData.zip/TestData/niko_test2.jpg",
      "classifiers": [
        {
          "classes": [
            {
              "score": 0.688922,
              "class": "nico"
            }
          ],
          "classifier_id": "eri_nico_102677947",
          "name": "eri_nico"
        }
      ]
    }
  ]
}
```

- 上半身だけの画像（eri_test.jpg(128 x 128)、nico_test.jpg(300 x 300)）は画像サイズが小さいせいなのか、どちらのクラスにも判別されませんでした。
- eri_test2.jpg(512 x 720)は0.593679の確信度でeriクラスに分類されていました。（10枚の画像で学習させたときの確信度が0.534255だったので、若干精度が上がりました）
- 今回どのクラスにも属さないkotori_test.jpg(512 x 720)はeriクラスに分類されていました。髪型が似ているせいですかね？（このキャプチャでは分かりづらいですが）
- 一番高い確信度だったのが、niko_test2.jpg(800 x 450)でした。ツインテールとそのリボンが特徴的だったのかもしれません

※画像名の横の(XXX x YYY)は画像の大きさです。

#最後に（箇条書き）
- 2つのクラスを持つカスタム分類器を作成してみました。
- 画像を50枚用意しても確信度はまだまだ低いんですね
- Negative_exampleの画像はどのようなものが好ましいのかよく分かっていません。
- 実業務でVRのような画像認識を使ったシステムを作るときには学習データが1クラスにつき2000枚位は必要なのかな－と勝手に思いました。

#参考リンク
[APIリファレンス](https://www.ibm.com/watson/developercloud/visual-recognition/api/v3/?python#create_a_classifier)