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

[前回の記事](https://qiita.com/kino15/items/e6fc7a103bab9d60dbb5)でPythonでIBM Cloudで提供されているWatson API Visual Recognition（以下VR）を利用する方法を紹介しました。
VRの[APIリファレンス](https://www.ibm.com/watson/developercloud/visual-recognition/api/v3/?python#create_a_classifier)を読んでいると、custom classifier（訳はカスタム分類器？）というものが作れると書いてあったので、それに挑戦しました。
（ざっくりと書いているので、突然専門用語を使用してる箇所があるかもしれません、、）

今回は私の好きなアニメ ラブライブ！のキャラクターである絢瀬絵里さんを判別するためのカスタム分類器を作成してみました。

#下準備
・Googleの画像検索で絢瀬絵里さんの画像を10枚ほど探し、一つのフォルダに画像を保存、そのフォルダをzipに固める（このファイル名をlovelive_eri.zip）
（最低でも10枚、本当はもっと枚数があったほうが良いです）
学習させた絢瀬絵里さんの画像（一例）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/191958/b56962d4-800f-1d02-40c1-68cff85b5cb4.png)


・Googleの画像検索で絢瀬絵里さん以外のラブライブキャラの画像を10枚ほど探し、一つのフォルダに画像を保存、そのフォルダをzipに固める（このファイル名をlovelive_others.zip）
![2018-01-15 16_36_52-無題 - ペイント.png](https://qiita-image-store.s3.amazonaws.com/0/191958/d6da8fc3-63bc-4980-ee3a-7baed4e561c4.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='')

with open(join(dirname(__file__), './TrainingData/lovelive_eri.zip'), 'rb') as eri, open(join(dirname(__file__), './TrainingData/lovelive_others.zip'), 'rb') as others:
    result = visual_recognition.create_classifier('erivsothers', eri_positive_examples=eri, negative_examples=others)
    print(json.dumps(result, indent=2))
```

実行結果はこちらです


```json
{
  "classes": [
    {
      "class": "eri"
    }
  ],
  "owner": "{ownerID}",
  "status": "training",
  "name": "erivsothers",
  "created": "2018-01-15T05:25:05.523Z",
  "classifier_id": "{clasiifier_id}"
}
```

*ownerID*と*clasiifier_id*は作成したカスタム分類器を使用する際に必要となる情報です。

カスタム分類器を作成しているのはこちらの部分です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/191958/c5c3bacd-ba4f-10b3-d2c7-173b47b35114.png)
カスタム分類器の名前（'erivsothers'）、Positive事例の画像ファイル（eri_positive_examples=eri）、Negative事例の画像ファイル（negative_examples=others）を指定します。

Positive事例の画像ファイルを指定している*eri_positive_examples*にはネーミングルールがあり、今回のケースでは「絢瀬絵里の画像たちは*eri*クラスです」とVRに学習をさせています。

Negative事例の画像ファイルにはネーミングルールはありません。*negative_examples*固定です。今回はeriクラス以外に分類したい画像を入れて学習させています。


**Positive事例の画像ファイル、Negative事例の画像ファイルはともに10枚以上画像を用意してください。**
10枚以下でアップロードをすると分類器作成に失敗します。

######Positive事例のネーミングルールは以下の通りです
`{class}_positive_examples`
`{class}`を任意のものにすることで、任意のクラスを作成することができます。
今回は1クラスしか作成していませんが、複数のクラスを作成することができます。

#作成したカスタム分類器一覧を確認する

作成したカスタム分類器の一覧を表示するためのコードです。

```py3:list_custom_classifiers.py
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 = '')

print(json.dumps(visual_recognition.list_classifiers(), indent=2))
```
このように作成したカスタム分類器一覧が見られます

```json

{
  "classifiers": [
    {
      "name": "erivsothers",
      "status": "ready",
      "classifier_id": "{classifier_id}"←後ほど使うので、控えておいてください！！
    },
    {
      "name": "erivsnico",
      "status": "failed",
      "classifier_id": "{classifier_id}"
    },
    {
      "name": "erivsnico",
      "status": "failed",
      "classifier_id": "{classifier_id}"
    },
    {
      "name": "erivsothers",
      "status": "failed",
      "classifier_id": "{classifier_id}"
    }
  ]
}
```
statusがreadyになっているのは既に使えるもの、faildになっているのは分類器作成に失敗したものです。
statusは私の見た限りではready、faild、trainingの3種類です。

faildの原因は画像を10枚以上用意しないで分類器を作成してしまったためです。
***classifier_id*は後ほど使うので、控えておいてください。**

また、以下のコードで指定したカスタム分類器の詳細を確認することができます。

```py3:list_custom_classifiers.py
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 = '')
#作成したclassifier_idを入力してください
print(json.dumps(visual_recognition.get_classifier("classifier_id"), indent=2))
```

```json
{
  "status": "ready",
  "classes": [
    {
      "class": "eri"
    }
  ],
  "name": "erivsothers",
  "owner": "{ownerID}", ←後ほど使うので、控えておいてください！！
  "created": "2018-01-15T05:26:51.382Z",
  "classifier_id": "{classifer_id}"
}
```

#作成したカスタム分類器を試す
最後に今回作成したカスタム分類器がどれほど使えるのか試してみます！
カスタム分類器のテストをするために、また画像を4枚集めました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/191958/eb20b4a8-e5ab-4cc4-cb56-154f050c5726.png)
この4枚の画像をTestDataフォルダ（新たに作成）に入れ、zipにします。


絢瀬絵里さん（左2枚の画像）をちゃんと判別できるのか・・？

以下のコードを実行します


```py3:createdClassifier.py
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/TestData.zip')
#classifier_idをここに入力
classifier_ids_array = ['classifier_id']


with open(image_path, 'rb') as images_file_path:
    car_results = visual_recognition.classify(images_file = images_file_path,parameters=json.dumps({"owner": "{ownerID}",'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))
```

```py3
classifier_ids_array = ['classifier_id']
```

には作成したカスタム分類器のIDを入れます。

今回は一つしかclassifier_idを指定していませんが、複数のclassifier_idを指定できるはずです。

＊このコードのポイント
以下の一文で作成したカスタム分類器を指定します
`images_file_path,parameters=json.dumps({"owner": "{ownerID}",'classifier_ids': classifier_ids_array}))`
！！カスタム分類器の詳細で確認したowerIDを入力してください！！

判定結果はこちらです！

```json

{
  "custom_classes": 1,
  "images": [
    {
      "classifiers": [],
      "image": "./lovelive/TestData.zip/TestData/eri_test.jpg"
    },
    {
      "classifiers": [
        {
          "name": "erivsothers",
          "classifier_id": "erivsothers_123300531",
          "classes": [
            {
              "score": 0.534255,
              "class": "eri"
            }
          ]
        }
      ],
      "image": "./lovelive/TestData.zip/TestData/eri_test2.jpg"
    },
    {
      "classifiers": [],
      "image": "./lovelive/TestData.zip/TestData/kotori_test.jpg"
    },
    {
      "classifiers": [],
      "image": "./lovelive/TestData.zip/TestData/nico_test.jpg"
    }
  ],
  "images_processed": 4
}
```

4枚中1枚しかちゃんと結果が出ていない、、
判別できたのは左から二番目、全身の写っている画像でした。

結果がこのようになっているものは判定した結果、当てはまるものがないため、`classifiers`の中が殻になっているのだと思われます。

```json
    {
      "classifiers": [],
      "image": "./lovelive/TestData.zip/TestData/kotori_test.jpg"
    }
```
他のキャラのクラスも作成すれば結果は少し変わると思います


#最後に（感想等）
今回はPythonでカスタム分類器を作成してみました。
VRを使えばそれほどコーディングをせずにカスタム分類器を作れるんだなぁを思いました。
記事を書いてからNegative事例の画像たちがあまり良くなかったのではと思い始めました
学習データ（アニメキャラの画像）を集めるのが大変でした

またネタがあったら投稿したいと思います