###### tags: `俳句AI`
# 俳句学習ロジック
## [Tensor2Tensor](https://hackmd.io/@T7k0V7TMQFelvJKKdo3pww/tensor2tensor)で学習
### エクスポートコマンド
このコマンドでSavedModelに変換します。
```bash=
t2t-exporter --data_dir=$HOME/t2t_data \
--problem=my_problem \
--model=transformer \
--hparams_set=transformer_base_single_gpu \
--output_dir=$HOME/t2t_train/my_problem/transformer-transformer_base_single_gpu \
--decode_hparams="beam_size=4,alpha=0.6" \
--t2t_usr_dir=$HOME/t2t_usr/my_problem
```
exportというファイルが出力され、中にSavedModelが入っています。

---
tensorflow-model-serverをインストール
```bash=
echo "deb [arch=amd64] http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal" | sudo tee /etc/apt/sources.list.d/tensorflow-serving.list && \
curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | sudo apt-key add -
apt-get update && apt-get install tensorflow-model-server
```
### tensorflow_model_serverを立ち上げる
```bash=
pip install tensorflow-serving-api
```
```bash=
tensorflow_model_server --port=9000 \
--model_name=my_model \
--model_base_path=$HOME/t2t_train/my_problem/transformer-transformer_base_single_gpu/export/ &
```
立ち上げられました。

---
## ML Engineで予測APIを提供する
## [オンライン予測の取得](https://cloud.google.com/ml-engine/docs/tensorflow/online-predict?hl=ja#formatting_your_input_for_online_prediction)

```json=
{
"error": "Prediction failed: Error during model execution: AbortionError(code=StatusCode.INVALID_ARGUMENT, details=\"Could not parse example input, value: '桜'\n\t [[{{node ParseSingleExample/ParseSingleExample}}]]\n\t [[DatasetToSingleElement]]\")"
}
```
サービングとML EngineによるAPIもやり方がわかれば同じらしい。
pythonからAPIリクエスト送りたい!
---
[tensor2tensorの翻訳モデルをサーバ化して実行](http://datanerd.hateblo.jp/entry/2019/08/08/114515)を参考にしました。
この方もTensor2Tensorを使っているようです。
[tensor2tensorで和英翻訳](http://datanerd.hateblo.jp/entry/2019/07/25/101436)
### 今回のデータセットの形式
TSV形式
[Tensor2Tensorを使って独自データでseq2seqしてみる](https://www.madopro.net/entry/t2t_seq2seq)
| answer | question |
| -------- | -------- |
| 季節 季語 単語 | 俳句
結果的に学習はでき、デプロイも出来ました。あとはリクエストを送るだけです。
### エクスポートされたモデルをGCSにコピーする
```bash=
ORIGIN="gs://your-project-id/"
EXPORTS_PATH=t2t_train/export/
LATEST_EXPORT=${EXPORTS_PATH}/$(ls ${EXPORTS_PATH} | tail -1)
gsutil cp -r ${LATEST_EXPORT}/* $ORIGIN
```
### モデルを作成する
```bash=
MODEL_NAME=my_model
VERSION=v1
gcloud ml-engine versions create $VERSION \
--model $MODEL_NAME \
--origin $ORIGIN
```
### モデルバージョンの作成は手動ですで行いました。
---
## AI Platform(旧ML Engine)でサービング
## [Serving](https://github.com/tensorflow/tensor2tensor/tree/master/tensor2tensor/serving)の記事を参考に実行。
### ローカル
```bash=
t2t-query-server --server=127.0.0.1:9000 \
--servable_name=my_model \
--problem=my_problem \
--data_dir=$HOME/t2t_data \
--t2t_usr_dir=$HOME/t2t_usr/my_problem
```

で文字を入力すると

が出力されるようになった。
### ML Engine
```bash=
MODEL_NAME=haiku_model
VERSION=v1
ORIGIN="gs://haiku-cloud-id"
DATA_DIR=$ORIGIN/t2t_data
USR_DIR=$ORIGIN/t2t_usr/my_problem
t2t-query-server \
--cloud_mlengine_model_name $MODEL_NAME \
--cloud_mlengine_model_version $VERSION \
--problem my_problem \
--data_dir=$DATA_DIR \
--t2t_usr_dir=$USR_DIR
```
同じ画面になり、
なにかしら文字を入力すると、
```bash=
I0831 03:01:57.417220 139835491129152 usr_dir.py:43] Importing user module
>> {"instances": [{"input": "桜"}]}
W0831 22:03:30.688194 139722244257600 __init__.py:44] file_cache is unavailable when using oauth2client >= 4.0.0 or google-auth
my_problem from path /home/yudai/t2t_usr
I0831 03:03:46.133155 139835491129152 discovery.py:271] URL being requested: GET https://www.googleapis.com/discovery/v1/apis/ml/v1/rest
I0831 03:03:47.545753 139835491129152 discovery.py:867] URL being requested: POST https://ml.googleapis.com/v1/projects/haiku-cloud-id/models/my_model/versions/v1:predict?alt=json
I0831 03:03:47.546408 139835491129152 transport.py:157] Attempting refresh to obtain initial access_token
I0831 03:03:47.550398 139835491129152 client.py:777] Refreshing access_token
Traceback (most recent call last):
File "/home/yudai/anaconda3/envs/py27/bin/t2t-query-server", line 17, in <module>
tf.app.run()
AttributeError: 'list' object has no attribute 'shape'
```
```bash=
W0831 22:03:30.688194 139722244257600 __init__.py:44] file_cache is unavailable when using oauth2client >= 4.0.0 or google-auth
```
が原因のようです。
[Google Cloud Functionsでgoogle-api-python-clientを利用してfile_cache is unavailableエラーになったときの対応方法](https://qiita.com/kai_kou/items/4b754c61ac225daa0f7d)で調べた結果から、
### リクエストコード
を書き直してみると、通信はされますが、
```bash=
python predict_sample.py
```
```python=
# -*- coding: utf-8 -*-
import json
import subprocess
from httplib2 import Http
from oauth2client.client import GoogleCredentials
from googleapiclient import discovery
project = "haiku-cloud-id"
model = "my_model"
print("Calling ML model on Cloud ML Engine...")
credentials = GoogleCredentials.get_application_default()
service = discovery.build('ml', 'v1', http=credentials.authorize(Http()), cache_discovery=False)
name = 'projects/{}/models/{}'.format(project, model)
data = {
"instances": [
{"input": "春"}
]
}
response = service.projects().predict(
name=name,
body=data,
).execute()
print(json.dumps(response, sort_keys=True, indent=2))
```
```bash=
Calling ML model on Cloud ML Engine...
{
"error": "Prediction failed: Error during model execution: AbortionError(code=StatusCode.INVALID_ARGUMENT, details=\"Could not parse example input, value: '\u6625'\n\t [[{{node ParseSingleExample/ParseSingleExample}}]]\n\t [[DatasetToSingleElement]]\")"
}
```
が出力されます。
instances.json
```json=
{"instances": [{"input": "春"}]}
```
```bash=
gcloud ai-platform predict --model $MODEL_NAME \
--version $VERSION_NAME \
--json-instances $INPUT_DATA_FILE
```
```bash=
{
"error": "Prediction failed: Expected tensor name: input, got tensor name: ['instances']."
}
```
```python=
from __future__ import absolute_import, division, print_function
import os
from six.moves import input
from tensor2tensor.serving import serving_utils
from tensor2tensor.utils import hparam, registry, usr_dir
def make_request_fn(servable_name="my_model", server="localhost:9000"):
request_fn = serving_utils.make_grpc_request_fn(
servable_name=servable_name, server=server, timeout_secs=30)
return request_fn
def translate(text,
udir="/home/yudai/t2t_usr/my_problem",
ddir="/home/yudai/t2t_data",
servable_name="my_model",
server="localhost:9000"):
usr_dir.import_usr_dir(udir)
problem = registry.problem("my_problem")
hparams = hparam.HParams(
data_dir=os.path.expanduser(ddir))
problem.get_hparams(hparams)
request_fn = make_request_fn(servable_name, server)
inputs = text
outputs = serving_utils.predict([inputs], problem, request_fn)
outputs, = outputs
output, score = outputs
return {"input": text, "output": output, "score": score}
def run():
while True:
inputs = input(">>")
result = translate(inputs)
output = result["output"]
score = result["score"]
if len(score.shape) > 0:
print_str = """
Input:
{inputs}
Output (Scores [{score}]):
{output}
"""
score_text = ",".join(["{:.3f}".format(s) for s in score])
print(
print_str.format(inputs=inputs,
output=output,
score=score_text))
else:
print_str = """
Input:
{inputs}
Output (Score {score:.3f}):
{output}
"""
print(print_str.format(inputs=inputs, output=output, score=score))
if __name__ == "__main__":
run()
```