AutoML Vision APIを使ってみた

AutoML VisionのAPIを使って見たのでメモを残しておきます。

今回は、pythonを使います。JAVA、node.jsも使えるみたいです。
[Client Libraries](https://cloud.google.com/vision/automl/docs/client-libraries?hl=ja)

この辺りを参考にしながらやっていきます。

- [ Quick Start ](https://googlecloudplatform.github.io/google-cloud-python/latest/automl/index.html)
- [ Client for Cloud AutoML API (コードのドキュメント)](https://googlecloudplatform.github.io/google-cloud-python/latest/automl/gapic/v1beta1/api.html)
- [Github](https://github.com/GoogleCloudPlatform/google-cloud-python/tree/master/automl)


## サンプルコード
基本的に、AutoML VisionのPREDICTタブにあるpythonのコードのまま叩けます。

```python
from google.cloud import automl_v1beta1
# 認証
KEY_FILE = "******.json"
prediction_client = automl_v1beta1.PredictionServiceClient()
prediction_client = prediction_client.from_service_account_json(KEY_FILE)

# 予測
name = 'projects/{}/locations/us-central1/models/{}'.format(project_id, model_id)
payload = {'image': {'image_bytes': content }}
request = prediction_client.predict(name, payload)

# 予測結果の取得
print(request)
```

##  認証
`automl_v1beta1.PredictionServiceClient()`で認証を行います。
以下のように環境変数を設定しておくとそこから自動で読み込んでくれるらしい。

```
export GOOGLE_APPLICATION_CREDENTIALS=key-file
```

今回は環境変数を汚したくなかったのでファイルから読み込むようにしました。

```python

prediction_client.from_service_account_json(KEY_FILE)
````



## 予測
nameにはproject_idとモデルidを、payloadには指定されたフォーマットのjsonを使って、予測したい画像を与えます。

```python
name = 'projects/{}/locations/us-central1/models/{}'.format(project_id, model_id)
payload = {'image': {'image_bytes': content }}
```

残りの引数は以下の通り。

```python
def predict(self,
                name,
                payload,
                params=None,
                retry=google.api_core.gapic_v1.method.DEFAULT,
                timeout=google.api_core.gapic_v1.method.DEFAULT,
                metadata=None):
```
- params
    (dict[str -> str])の形で score_thresholdなどのパラメータを渡す。
- retry
[retryクラス](https://googlecloudplatform.github.io/google-cloud-python/latest/core/retry.html#google.api_core.retry.Retry)があるのでそれにそって渡す。デフォルトではretryしない。
- timeout
    predictに割と時間がかかることがあるので、タイムアウトはセットしておいても良いかも。    [Github source](https://github.com/GoogleCloudPlatform/google-cloud-python/blob/master/api_core/google/api_core/gapic_v1/method.py)によるとデフォルト値は60s



## 予測結果の取得
jsonかと思わせてjsonじゃないフォーマットだったので、ハマりました。


```python
request = prediction_client.predict(name, payload)
print(request)
```

AutoML VisionのPREDICTタブにあるpythonのコードを実行すると、以下の結果が返ってきます。

```
payload {
  classification {
    score: 0.215105131269
  }
  display_name: "kotobuki_tsumugi"
}
```

scoreは予測結果、display_nameはラベル。
これがjsonかと思わせて、jsonじゃないのが罠です。

そこで、[ドキュメント](https://googlecloudplatform.github.io/google-cloud-python/latest/automl/gapic/v1beta1/api.html)をみると、以下のように書いてあります。

```
Returns: A PredictResponse instance.
```

で、[PredictResponce instance](https://googlecloudplatform.github.io/google-cloud-python/latest/automl/gapic/v1beta1/types.html#google.cloud.automl_v1beta1.types.PredictResponse)というのは以下。

```
class google.cloud.automl_v1beta1.types.PredictResponse
 - payload
 - metadata
```


なにやらpayloadとmetadataをもっているクラスだそうです。

そこで、以下のようにするとうまく中身が取り出せます。

```
print (request.payload)
```

出力

```
[classification {
  score: 0.215105131269
}
display_name: "kotobuki_tsumugi"
]
```

さらに、scoreとdisplay_nameは以下のようにすると取り出せます。

```
score = request.payload[0].classification.score
display_name = request.payload[0].display_name

print(score, display_name)
```

出力

```
0.215105131269
kotobuki_tsumugi
```

無事中身が取り出せました。

## 予測結果の取得2
データセットを増やすと、Precisionは高い値となったがRecallは低くなりました。
<img src="https://i.imgur.com/WYIkXqE.png
" alt="" width="400">

すると、判定しようとした画像によっては、予測結果が空で返ってくることがありました。おそらく、Recall(再現度)が低いと、空が返ってくる模様。payloadにerror文とかは入れてくれてないんですね...。

PrecisionとRecallはAutoML VisionのEVALUATEタブにあるScore thresholdのバーから変更できます。データセットの画像がTrue positives/False negativesかどうかをみることができるのでそれを見ながら調整できます。

APIを叩くときには、predictの引数のparamsから設定できます。デフォルトは0.5。

# まとめ
今回は、pythonを使ってAutoML VisionのAPIを叩いてみました。
簡単に使うことができて、リファレンスもちゃんとあるので難しくないかと思います。まだベータ版なので出力結果のフォーマットやエラー周りは、これからわかりやすく変わってくるのではないでしょうか。