Google Cloud AutoML Vision で、10人の女優を識別する

# はじめに
- [Google Cloud AutoML](https://cloud.google.com/automl/) の凄さを体感したく思っていました。
- 先日、[TensorFlowで安倍乙と石原さとみの顔認識をやってみた](https://qiita.com/maeda_mikio/items/172701701dbe82faafcc) で利用した画像を利用して、比較してみます。


# 画像
- 画像は、グレースケール化とリサイズ `28x28` したものを利用します。
- 以下が画像の概要です。

|名前 |フォルダ名 |画像数 |
|---|---|---|
|安倍乙|0_abe_oto |415 |
|石原さとみ |1_ishihara_satomi |492 |
|大原優乃 |2_ohara_yuno |372 |
|小芝風花 |3_koshiba_fuka |400 |
|川口春奈 |4_kawaguchi_haruna |369 |
|森七菜 |5_mori_nana |389 |
|浜辺美波 |6_hamabe_minami |481 |
|清原果耶 |7_kiyohara_kaya |428 |
|福原遥 |8_fukuhara_haruka |420 |
|黒島結菜 |9_kuroshima_yuina |448 |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/baa75499-2a56-4c31-9031-454a85c2d8f6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/977f7b27-7793-79ab-ab50-a7abd9067509.png)


# AutoML

## 画像のzip化
- AutoML へ画像をアップロードするために `zip` 化を行います。
- `.jpeg` を複数ファイルアップロードすることも出来ますが、この場合は、UIでラベル付等をする必要があります。
- 以下の様なフォルダ構成を準備します。
- `images` 等の中にラベル名とするフォルダ名 `0_abe_oto` を作成します。ラベル名は、`安倍乙`等の日本語は使えません。
- `0_abe_oto` には、トレーニング、検証、テストに利用する画像ファイルを保存します。

```
$ tree
.
├── images
│   ├── 0_abe_oto
│   │   ├── 0002-0001.jpeg
│   │   ├── 0004-0001.jpeg
省略
│   ├── 1_ishihara_satomi
│   │   ├── 0001-0001.jpeg
│   │   ├── 0004-0001.jpeg
```

- 上記を `zip` 化します。

```
$ zip images.zip -r images
  adding: images/ (stored 0%)
  adding: images/2_ohara_yuno/ (stored 0%)
  adding: images/2_ohara_yuno/0393-0001.jpeg (deflated 1%)
省略
```

## プロジェクトの作成
- GCPコンパネでプロジェクトを作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/81155c78-28e7-073f-c73e-4c411f9e9455.png)

## AutoML Vision の有効化

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/bdb9f2d0-3aa5-6369-2cf8-521fc608cd39.png)

## 新しいデータセット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/844d2529-0f8b-501d-2f2d-7289ae1fa8c3.png)

- データセット名を適当につけます。
- 今回は、10人の女優の画像があるので、`マルチラベル分類`を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/20dcc9b1-7bc0-8632-331e-6c32c60082af.png)

- パソコンから画像をアップロードします。今回は、`images.zip` ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/3649e0b0-53b0-5684-b879-be9aa0794f52.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/99ea132b-7737-c4b0-23f4-60a1f1f9918d.png)

- 保存する Cloud Storage を選択します。
- 新規プロジェクトから AutoML APIを有効にした場合は、バケットが作成されているはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/72edc627-81f7-ef64-2f0a-9bb6ad1a2096.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/a9444c0e-b3b5-7e35-46af-e704d4e080e1.png)

- 画像のインポートは、ある程度の時間がかかります。`images.zip` 内のファイル数は約4,000、ファイルサイズは約4Mバイトです。
- 終了すると、メール通知があります。だいたい、20分かかりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/9783f547-132f-9463-e128-6368a3ca2c68.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/ad7e1877-c4ab-2955-7cd8-395f53015d76.png)


## イメージの確認
- ラベル、画像等が確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/6e0cb477-cf58-7545-8d12-8f220037d6b5.png)

## トレーニング
- アップロードした画像は、トレーニング、検証、テストに分けられていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/7140f7ec-e6f9-89a0-6129-ee473584aa97.png)

- [マニュアル](https://cloud.google.com/vision/automl/docs/beginners-guide)には、以下の記載があります。
- 各ラベルの画像は、最低100枚、理想的には1,000枚とのこと。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/6d43d772-3012-ad1b-0739-49e4a14bc50e.png)

- モデルは、`Cloud hosted` にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/093f279d-7242-502e-8ac5-55ce12c6b639.png)

- ノード時間は、悩ましいところです。今回の推奨では、`32ノード時間`になっていました。
- これは、画像数が約4,000枚だからでしょう。
- [料金](https://cloud.google.com/vision/automl/pricing)は、以下の様になります。
    - 32ノード時間 * 3.15ドル = 100.8ドル = 約11,000円

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/30ee1eff-9e31-38d2-624d-6b560861dbec.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/34ab0296-34c8-6042-f8af-fee4dcc45b85.png)

- 今回は、以下の説明があったので `8ノード時間` にしました。
- また、REST API も試してみたいので、デプロイしました。
- だいたい、1時間後に完了のメールが届きました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/cbe4f0f8-aaaa-1a57-701a-8dffa628448c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/0d8f931a-5964-8f52-8492-50035ea6e5d7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/2706890b-7a11-9d88-be00-bca20c18ff0d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/b4a82442-505b-0036-ef13-ef4b65edb12e.png)


## トレーニング結果
- 平均適合率は `0.673` でした。
- 適合率、再現率等は、[AutoML Vision 初心者向けガイド 評価](https://cloud.google.com/vision/automl/docs/beginners-guide#evaluate) を確認して頂ければと思います。
- 混同行列は、見やすくて良いですね！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/ba82447a-9ecc-c27a-e381-32f851aabf13.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/0a24dd97-d984-8075-36a2-b3f302c8a88e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/9d64c93b-edc1-4e6e-a46e-b4504eadffde.png)


## テストと使用
- 画像をアップロードして確認することが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/fc5cb8a0-57ed-f2f5-7cde-a6d58e0d489b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/c6c6332b-9c15-e9a2-40f8-4312810accf8.png)

## REST API
- REST API を使ってみます。

- 画像をBASE64にします。

```
$ base64 -i input.jpg -o output.txt

$ cat output.txt
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoKCgoKBggLDAsKDAkKCgr/wAALCAAcABwBAREA/8QAFwABAQEBAAAAAAAAAAAAAAAACQcICv/EACsQAAEDBAEEAQMEAwAAAAAAAAECAwQFBgcRCAASEyExCUFRCiIycRRhof/aAAgBAQAAPwDG+IL1g1Wj0CVftWjQUX1fkGXWnJLqUJTGXUEABSlaCW0tMqBHxpQ66G6hnPFdKx+q9nLxhCiRofkXUmXkqZDYT7IUnY0B9x0Uf1wsxcdOSfHSHcuJrslVOrUOvtSoM5duTI7D7KwW3fDIdaSh0DuSSEk/G/evRAXdLZqdbcqjDYaTKSl3sHsAkbP/AHfV54rYpyryvzfbeJcZzGUPxPHK80yA1LZitNBLaStl0Ft3167FAje/R66MsX8UqPbXGeJY15mM7JiojvzlMw22m/2kfLTaQhI9JJSAE/PoD11jT6h308sbYo4l5VzDkrMN4XNKatudKoqrmu2XOS1KUsLZUEuLDaQj022hCEpSk69+ugZET/IQkkgdg7dHXrpI/wBO2xabOWKlXVOtpqwUG3w6sb8Q/glI/G+4n8k/10ofMLkVWqVbsulY5ydka2ELZ8VUVTLOg9jw7gVPR5E91o77U9oUnvaA2dEnrC31xee1OyBxCoeJ6FCq9Lk3MiM0KbW0tomuspUD5HEtLWgBQSFelH+Q+N66IMR3nE94JBJPdr87PVL4sZNvzEmWEXrju5ZFLnwkKcQtggocAAJQtBBStB+4I/rR99PZYPK69L84Z0DMl22JZ9QrS6WHwudQA+htYbJ2gOqUUex9j0FmaM+ZF5ac6o92ZinR5DhvBiAzChseKNHjokpT2Ib2db1tRJJJ/wBaAlh0002UgfvClnf2JWonXX//2Q==
```

- request.json を作成します。上記のBASE64の結果を `imageBytes`に設定します。

```
{
  "payload": {
    "image": {
      "imageBytes": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoKCgoKBggLDAsKDAkKCgr/wAALCAAcABwBAREA/8QAFwABAQEBAAAAAAAAAAAAAAAACQcICv/EACsQAAEDBAEEAQMEAwAAAAAAAAECAwQFBgcRCAASEyExCUFRCiIycRRhof/aAAgBAQAAPwDG+IL1g1Wj0CVftWjQUX1fkGXWnJLqUJTGXUEABSlaCW0tMqBHxpQ66G6hnPFdKx+q9nLxhCiRofkXUmXkqZDYT7IUnY0B9x0Uf1wsxcdOSfHSHcuJrslVOrUOvtSoM5duTI7D7KwW3fDIdaSh0DuSSEk/G/evRAXdLZqdbcqjDYaTKSl3sHsAkbP/AHfV54rYpyryvzfbeJcZzGUPxPHK80yA1LZitNBLaStl0Ft3167FAje/R66MsX8UqPbXGeJY15mM7JiojvzlMw22m/2kfLTaQhI9JJSAE/PoD11jT6h308sbYo4l5VzDkrMN4XNKatudKoqrmu2XOS1KUsLZUEuLDaQj022hCEpSk69+ugZET/IQkkgdg7dHXrpI/wBO2xabOWKlXVOtpqwUG3w6sb8Q/glI/G+4n8k/10ofMLkVWqVbsulY5ydka2ELZ8VUVTLOg9jw7gVPR5E91o77U9oUnvaA2dEnrC31xee1OyBxCoeJ6FCq9Lk3MiM0KbW0tomuspUD5HEtLWgBQSFelH+Q+N66IMR3nE94JBJPdr87PVL4sZNvzEmWEXrju5ZFLnwkKcQtggocAAJQtBBStB+4I/rR99PZYPK69L84Z0DMl22JZ9QrS6WHwudQA+htYbJ2gOqUUex9j0FmaM+ZF5ac6o92ZinR5DhvBiAzChseKNHjokpT2Ib2db1tRJJJ/wBaAlh0002UgfvClnf2JWonXX//2Q=="
    }
  }
}
```

- サービスアカウントを AutoML 編集者で作成して、keyをダウンロードします。

```
$ export GOOGLE_APPLICATION_CREDENTIALS=/Users/maeda_mikio/Downloads/automl-20200111-67d782c3de3c.json
```

- curlを実行します。予測結果が取得出来ました。

```
$ curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" https://automl.googleapis.com/v1beta1/projects/655668842161/locations/us-central1/models/ICN6623260133629624320:predict -d @request.json
{
  "payload": [
    {
      "annotationSpecId": "3339315769602211840",
      "classification": {
        "score": 0.8167497
      },
      "displayName": "0_abe_oto"
    }
  ]
}
```

## Python
- Pythonでも実行します。

```
$ pip install google-cloud-automl
```

```predict.py
import sys

from google.cloud import automl_v1beta1
from google.cloud.automl_v1beta1.proto import service_pb2


# 'content' is base-64-encoded image data.
def get_prediction(content, project_id, model_id):
  prediction_client = automl_v1beta1.PredictionServiceClient()

  name = 'projects/{}/locations/us-central1/models/{}'.format(project_id, model_id)
  payload = {'image': {'image_bytes': content }}
  params = {}
  request = prediction_client.predict(name, payload, params)
  return request  # waits till request is returned

if __name__ == '__main__':
  file_path = sys.argv[1]
  project_id = sys.argv[2]
  model_id = sys.argv[3]

  with open(file_path, 'rb') as ff:
    content = ff.read()

  print(get_prediction(content, project_id, model_id))
```

```
$ python3 predict.py input.jpg 655668842161 ICN6623260133629624320
payload {
  annotation_spec_id: "3339315769602211840"
  classification {
    score: 0.8167496919631958
  }
  display_name: "0_abe_oto"
}
```


# おわりに
- AutoML Vision で画像の分類をやりました。
- 評価結果は、非常にわかりやすいですね。また、REST API、Pythonからの利用も簡単です。
- ただ、料金はきになる部分ですね。個人での利用は、悩ましいな。