###### 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