###### tags: `俳句AI`
# 俳句AI開発
```bash=
VERSION=v1
MODEL_NAME=my_model
ORIGIN="gs://haiku-cloud-id/train/my_problem/export/1567023569"
gcloud ai-platform models create $MODEL_NAME \
--regions asia-northeast1
gcloud ml-engine versions create $VERSION \
--model $MODEL_NAME \
--origin $ORIGIN \
--runtime-version 1.14
```
ML Engine上でモデル、バージョンともにデプロイ完了。
https://storage.cloud.google.com/ramen-image/gundam/gface64x64.zip?folder=true&hl=ja&organizationId=true
```python=
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
import base64
import os
from httplib2 import Http
from googleapiclient import discovery, errors
from oauth2client.client import GoogleCredentials
from tensor2tensor.bin import t2t_trainer
from tensor2tensor.utils import cloud_mlengine as cloud
from tensor2tensor.utils import decoding, t2t_model, trainer_lib, usr_dir
credentials = GoogleCredentials.get_application_default()
PROJECT_ID = 'haiku-cloud-id'
project_id = 'projects/{}'.format(PROJECT_ID)
model_name = 'my_model'
version = 'v1'
modelID = '{}/model/{}'.format(project_id, model_name)
examples = "桜"
api = discovery.build(model_name, version, http=credentials.authorize(Http()), cache_discovery=False)
input_data = {
"instances": [{
"input": {
"b64": base64.b64encode(ex.SerializeToString())
}
} for ex in examples]
}
prediction = api.projects().predict(body=input_data, name=modelID).execute()
response = prediction.execute()
print(response)
```
ML Engineにデプロイされるが下記がエラー発生した。
記述、文法、タイポを確かめる。
認証情報を設定したが、変化しない。
discovery.buildを確かめる。複数の書き方があるため、バージョンを調査する。
```bash=
Traceback (most recent call last):
File "export_custom.py", line 22, in <module>
api = discovery.build(model_name, version, http=credentials.authorize(Http()), cache_discovery=False)
File "/home/yudai/anaconda3/envs/py27/lib/python2.7/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/home/yudai/anaconda3/envs/py27/lib/python2.7/site-packages/googleapiclient/discovery.py", line 234, in build
"name: %s version: %s" % (serviceName, version))
googleapiclient.errors.UnknownApiNameOrVersion: name: my_model version: v1
```
https://stackoverflow.com/questions/56950799/getting-a-google-api-client-error-using-the-uberi-speech-to-text-code によると、パッケージをバージョンアップさせ解決したらしい。
```bash=
Python 2.7.16
google-api-python-client==1.7.11
google-auth==1.6.3
google-auth-httplib2==0.0.3
httplib2==0.13.1
tensor2tensor==1.13.4
tensorflow==1.14.0
```
```bash=
api = discovery.build(model_name, version, http=credentials.authorize(Http()), cache_discovery=False)
を
api = discovery.build("ml", "v1", http=credentials.authorize(Http()), cache_discovery=False)
```
に変更すると成功した。
次は、
```bash=
Traceback (most recent call last):
File "export_custom.py", line 31, in <module>
} for ex in examples]
AttributeError: 'str' object has no attribute 'SerializeToString'
```
```bash=
input_data = {
"instances": [
{"input": "sakura"}
]
}
```
```bash=
googleapiclient.errors.HttpError: <HttpError 401 when requesting https://ml.googleapis.com/v1/projects/projects/haiku-cloud-id/models/haiku_model/versions/haiku_model_v1:predict?alt=json returned "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.">
```
401:有効な認証情報の不足によるリクエスト失敗。
OAuth2.0の設定が必要らしい。
[Access Tokenを取得してGoogle Cloud MLでオンライン予測](https://qiita.com/FukuharaYohei/items/5face08fa7d07bbe11fe)
## OAuth 2.0のクライアントIDの認証情報を取得
jsonをダウンロード
```json=
{"installed":{"client_id":"940978461745-m5548t7kho98s9a4mombsuhphniiim1o.apps.googleusercontent.com","project_id":"haiku-cloud-id","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"uc0qGLfACXV6GbJKfrZ1uVBm","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}
```
### Authorization Code取得のためのURL
```
https://accounts.google.com/o/oauth2/auth?client_id=940978461745-m5548t7kho98s9a4mombsuhphniiim1o.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/cloud-platform&response_type=code&approval_prompt=force&access_type=offline
```
### Authorization Code
```
4/rwGfYGpAgxQBHZTx5YMajt3Ah85c_Twi19Hb5sUg5lUTBAP3ls-U6aw
```
### Access Token取得
```bash=
curl -d client_id=940978461745-m5548t7kho98s9a4mombsuhphniiim1o.apps.googleusercontent.com -d client_secret=uc0qGLfACXV6GbJKfrZ1uVBm -d redirect_uri=urn:ietf:wg:oauth:2.0:oob -d grant_type=authorization_code -d code=4/rwGfYGpAgxQBHZTx5YMajt3Ah85c_Twi19Hb5sUg5lUTBAP3ls-U6aw https://accounts.google.com/o/oauth2/token
```
```bash=
{
"access_token": "ya29.Il-bBw2Xf1Oy0f10G1pCvjUnhz81Ll9cDKukhlcjk0c2-tAU5g-9kmiM3ubor1dAoI_knFzA3RN3kkYTGwOwk8aIpkLQmAZj36KzU-kb8jHJkDE67foAK8tyHKnN7MHWqw",
"expires_in": 3600,
"refresh_token": "1//0eJRAAg_brzJxCgYIARAAGA4SNwF-L9IrL-LR75-HLsDqJvvBG-vWfdYzHISJuepgcYuQO41BuajkF6ObwML3DIM4Plh4osPre7k",
"scope": "https://www.googleapis.com/auth/cloud-platform",
"token_type": "Bearer"
}
```
実行してみる。
```bash=
W1009 23:01:16.042706 139624238204736 http.py:118] Invalid JSON content from response: {
"error": {
"code": 403,
"message": "Permission denied on resource project projects.",
"status": "PERMISSION_DENIED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.Help",
"links": [
{
"description": "Google developer console API key",
"url": "https://console.developers.google.com/project/projects/apiui/credential"
}
]
}
]
}
}
Traceback (most recent call last):
File "export_custom.py", line 30, in <module>
prediction = api.projects().predict(body=input_data, name=model_id).execute()
File "/home/yudai/anaconda3/envs/py27/lib/python2.7/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/home/yudai/anaconda3/envs/py27/lib/python2.7/site-packages/googleapiclient/http.py", line 856, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://ml.googleapis.com/v1/projects/projects/haiku-cloud-id/models/haiku_model/versions/haiku_model_v1:predict?alt=json returned "Permission denied on resource project projects.". Details: "[{u'@type': u'type.googleapis.com/google.rpc.Help', u'links': [{u'url': u'https://console.developers.google.com/project/projects/apiui/credential', u'description': u'Google developer console API key'}]}]">
```
権限不足のため、リクエストできない。
JSONのURLに飛ぶと、project-idが設定されていなかった。
## Flask上でローカル推論を行う
### gRPCサーバーを立ち上げる
```bash=
tensorflow_model_server --port=9000 \
--model_name=my_model \
--model_base_path=$HOME/t2t_train/my_problem/transformer-transformer_base_single_gpu/export/ &
```
次に、query.pyを実行すると推論できる。
### Flaskに組み込む
docker-compose.ymlを書く
[transformerで自然な会話ができるボットを作った](https://sekailab.com/wp/2019/03/27/transformer-general-responce-bot/)
query.pyをモジュール化し、app.pyにimportする。
## 実行手順
### Flaskで俳句AIを実行できるようにする
Dockerでtensorflow-servingが動くようにする。
モデルに単語が入力できるようにする。
HTMLとpythonを繋げる
俳句モデルの精度を上げる
- ひらがな化、17音のみ抽出
- データセットを分割する
- OptuneでHPチューニング
```bash=
T2T: skipped importing 71 data_generators modules.
...
ImportError: This version of TensorFlow Probability requires TensorFlow version >= 1.15;
Detected an installation of version 1.12.0. Please upgrade TensorFlow to proceed.
```
tensorflowのバージョンが合わないことにより、t2tが入れられない。
Dockerfileを確認してみる。
tensorflow==1.15.0
を追加してみる。
デプロイがPushedで止まる。
buildに13分かかっていたらしい。
## 締切り迫る
開発期間はあと3日、22、23、24、しか無い。
金曜日が提出日。
一日で集中できる時間は8時間、23日はバイトのため6時間集中したとすると、
20時間でリリースまで行う必要がある。
リリースを行う工程:
T2TをFlaskで推論させる。
カスタムドメインをエンドポイントと対応させるのか?
エンドポイントとは?とURLの関係。
余裕があれば、俳句モデルの学習データ改善とOptuneによるチューニングする。<-1日はかかるはず。
3時間本気でやってもできなかったら、強制的に他のタスクを取り組み、他の簡単になりそうな方法を試す。
## T2TをFlaskで推論させる:2日かかる
現在のデプロイ環境では時間がかかりすぎるため、Flaskだけのディレクトリを作成し、開発を先に進めたい。
22日:
GKEのコンソールからサービスをデプロイしている。
DockerfileのCMDでt2tのコマンドを実行できるのか?
>
普通のDockerで行ってみたいが、docker-compose.ymlは、
k8sではどのように扱いが異なるのか?
> k8sでも使えるが、変換する必要がある。また、書き方を覚える必要がある。
haiku-cloud-cluster-v2が正しい名前空間と思っていたら、再起動させたほうが良いかもしれない。
ymlファイルの名前が間違えているのかと考えたが、違うらしい。
Dockerfile
```Dockerfile=
# Python image to use.
FROM python:3.6
# Set the working directory to /app
WORKDIR /app
# copy the requirements file used for dependencies
COPY requirements.txt .
# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt
# Install ptvsd for debugging
RUN pip install ptvsd
RUN pip install tensorflow
RUN pip install tensor2tensor
VOLUME /model/t2t_data
VOLUME /model/t2t_usr
CMD [t2t-query-server --server=model:8500 --servable_name=my_model --problem=my_problem --data_dir=t2t_data --t2t_usr_dir=t2t-usr]
# Copy the rest of the working directory contents into the container at /app
COPY . .
# Run app.py when the container launches
ENTRYPOINT ["python", "-m", "ptvsd", "--port", "3000", "--host", "0.0.0.0", "app.py"]
```
docker-compose.yaml
```yaml=
version: "3"
services:
model-server:
image: tensorflow/serving:1.15.0
volumes:
- ./export:/models/my_model
environment:
- MODEL_NAME=my_model
logging:
driver: "json-file"
options:
max-size: "1k"
max-file: "3"
src:
build:
context: ./src/
dockerfile: ./Dockerfile
volumes:
- ./export:/model/t2t_data
- ./my_problem:/model/t2t_usr
links:
- model-server:export
ports:
- "5000:5000"
command: bash -c "t2t-query-server --server=model:8500 --servable_name=my_model --problem=my_problem --data_dir=/model/t2t_data --t2t_usr_dir=/model/t2t_usr"
logging:
driver: "json-file"
options:
max-size: "1k"
max-file: "3"
```
docker-compose.ymlが動いているのかを確かめたい。
tf 1.12.0だとバージョンが違う事があったためtensorflow/serving:1.12.0に変更してみる。特に変わりなし。
```
ERROR in app: Exception on /result [POST]
...
ModuleNotFoundError: No module named 't2t_usr'
```
```python=
def translate(text,
udir="/t2t_usr",
ddir="/t2t_data",
servable_name="my_model",
server="model:8500"):
usr_dir.import_usr_dir(udir)
problem = registry.problem("my_problem")
```
のディレクトリがおかしいらしい。
```
udir="/my_problem"
ddir="/export"
```
に変更してみる。
my_problem.pyで`pandas`が足りないらしいので、`pandas==0.42.2`をrequirements.txtに加える。
```
ValueError: File /export/vocab.my_problem.8192.subwords not found
```
と出たので、`t2t_data`を`export`に改名し、デプロイしてみる。
`t2t-query-server`ではなく、`tensorflow-model-server`で実行してみる。
### 1からやり直してみる。
GCEにCent OSのインスタンスを立ち上げ、Dockerを入れ、Flaskを動かしていく。
画像は、GCSからいけるのか?
https://qiita.com/umeee/items/cdf30e037a0ee66e8d10
https://medium.com/analytics-vidhya/deploy-your-first-deep-learning-model-on-kubernetes-with-python-keras-flask-and-docker-575dc07d9e76
```Dockerfile=
FROM python:3.6
WORKDIR /app
COPY requirements.txt /app
RUN pip install -r ./requirements.txt
COPY app.py /app
CMD ["python", "app.py"]~
```
```bash=
# [.]は重要
sudo docker build -t keras-app:latest .
sudo docker run -d -p 5000:5000 haiku-ai
sudo docker login
sudo docker images
sudo docker tag <your image id> <your docker hub id>/<app name>
```
```bash=
#cloud shell
gcloud config set compute/zone asia-northeast1-a
gcloud container clusters create io
kubectl run haiku-ai --image=tonoyamayudai/haiku-ai --port 5000
```
先がわからない
## Cloud Codeが動かない
k8sはクラスタで、個別に外部IPアドレスにドメインを紐付けるとは違うのか?
GKE上でポチポチすることでデプロイできるらしい。
クラスタがクラッシュして無限ループしているらしい。
特に、Istioが悪さをしているらしいので、再度削除して同じ名前で立ち上げて取り除いてみる。
全く新しい環境ならいけるのかと思ったが、
```
Failed to wait for deployment rollout
```
になる。Dockerは元気に動いている。
名前空間を変えてみる。Remove form ContextをVS Code上で右クリックで行った。動かない。
Set as a Active clusterを右クリック。kubeconfigにゾーンが自動入力される。
高速にデプロイしている!
Desktop/haiku-cloudのimage名に
## ドメインとアプリを紐付けたい:1日かかる
できた。
GCPのCloud DNSで独自ドメインを登録。
外部IPアドレス(external)を静的タイプに変更。
## 俳句モデルの改善
他のタスクが煮詰まったときにやるタスクで後回しにしたい。
### キーワードをランダムに選ぶ際に、単語をランダムに選ぶスクリプトを書く必要がある。精度は上がるのか?<-やっていた。
> 以前のバージョンは、抽出単語からランダムチョイスすることを忘れていた。
mecab_node_new.pyで単語抽出、
```
'|', 'ぶれる', '美', '僧', 'つれる', '雪', '解', '野', '|'
```
をnew_txt_replace.pyで
```
朝霧, 中, 九, 段, ともす, 哉
```
にする。
random_choices.pyで取り出すと、
```
['哉']
['雨,']
['町,']
```
をnew_txt_replace.pyでキレイにする。
```
哉
雨
町
```
あとは、fileをpasteコマンドで列方向に繋げていく。
### 17音の俳句だけを取り出したい。pykakasiで出来ないか?
```
```
```
tensorboard --logdir $TRAIN_DIR --host localhost --port 2222
```
### Optuneでチューニングしたい。精度は変わるのか?
### TDD、や統合テストをしたい
### Tensorflowで実装し、Attention画像を出力させたい
### Ruby on Rails、MySQL、CI/CDでポートフォリオを作りたい
tonoyama.me