>>> mlflow.start_run()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/amedama/.virtualenvs/py37/lib/python3.7/site-packages/mlflow/tracking/fluent.py", line 112, in start_run
_active_run_stack[0].info.run_id))
Exception: Run with UUID a14a8f9bf213473aa4a7a437ac811077 is already active. To start a new run, first end the current run with mlflow.end_run(). To start a nested run, call start_run with nested=True
ただし、オプションに nested=True を指定すると、エラーにならず新たに Run を作ることができる。
>>> mlflow.start_run(nested=True)
<ActiveRun: >
ただ、上記で作られた Run は MLflow のモジュールの中でグローバル変数として用意されたスタック構造で管理されているに過ぎない。
スタック構造は隠しオブジェクトだけど、あえて中身を見せるとこんな感じ。
まず、MLflow Tracking では Experiment と Run というモノを作っていく。
これらは、特定の目的を持った実験と、それに 1:N で紐付いた各試行を表している。
つまり、試行錯誤の度に Run が増えることになる。
そして、それぞれの Run には次のような情報が、またもや 1:N で紐づく。
$ head mlruns/0/3de33a8f39294c4f8bd404a5d5bccf39/params/foo
bar
$ head mlruns/0/3de33a8f39294c4f8bd404a5d5bccf39/metrics/logloss
15912673157371.00
$ cat mlruns/0/3de33a8f39294c4f8bd404a5d5bccf39/artifacts/test-artifact
Hello, World!
複数人のチームで使うときは、いくつかの選択肢があるけど基本的には MLflow Server を用意して、そこに皆でアクセスする。
MLflow Server というのは Tracking URI として使える REST API と、先ほど確認した WebUI が一緒になったもの。
注意点として、MLflow Server はあくまで Tracking URI と WebUI のエンドポイントを提供するもの。
なので、Artifact URI の実体については別に用意しなければいけない。
たとえばクラウドストレージが使えるならそれを使っても良し、自分たちで FTP サーバを立ち上げたり HDFS のクラスタを組むことも考えられるだろう。
ここでは MLflow Server について軽く解説しておく。
まず、MLflow Server は mlflow server コマンドで起動できる。
起動するときに、Tracking URI (--backend-store-uri) と Artifact URI (--default-artifact-root) を指定する。
$ kind create cluster
Creating cluster "kind" ...
✓ Ensuring node image (kindest/node:v1.21.1) 🖼
✓ Preparing nodes 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
Set kubectl context to "kind-kind"
You can now use your cluster with:
kubectl cluster-info --context kind-kind
Not sure what to do next? 😅 Check out https://kind.sigs.k8s.io/docs/user/quick-start/
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane,master 103s v1.21.1
docker container list コマンドを使って稼働しているコンテナを見ると Kubernetes のコントロールプレーンのコンテナが見える。
$ docker container list
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eec5aa7fa35d kindest/node:v1.21.1"/usr/local/bin/entr…"2 minutes ago Up 2 minutes 127.0.0.1:49921->6443/tcp kind-control-plane
$ kind create cluster \
--name kind-multi \
--config kind-multi-node-cluster.yaml
Creating cluster "kind-multi" ...
✓ Ensuring node image (kindest/node:v1.21.1) 🖼
✓ Preparing nodes 📦 📦 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
✓ Joining worker nodes 🚜
Set kubectl context to "kind-kind-multi"
You can now use your cluster with:
kubectl cluster-info --context kind-kind-multi
Have a nice day! 👋
すると、次のように 3 つのノードから成るクラスタができる。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-multi-control-plane Ready control-plane,master 53s v1.21.1
kind-multi-worker Ready <none> 24s v1.21.1
kind-multi-worker2 Ready <none> 24s v1.21.1
確認すると、Docker コンテナも 3 つ稼働している。
$ docker container list
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bcb2f337b802 kindest/node:v1.21.1"/usr/local/bin/entr…" About a minute ago Up About a minute kind-multi-worker
eb32f4375353 kindest/node:v1.21.1"/usr/local/bin/entr…" About a minute ago Up About a minute kind-multi-worker2
22da177bed79 kindest/node:v1.21.1"/usr/local/bin/entr…" About a minute ago Up About a minute 127.0.0.1:50566->6443/tcp kind-multi-control-plane
自前のイメージで Deployment を立ち上げてみる
マルチノードのクラスタを使って遊んでいこう。
試しに、複数の Pod を持った Deployment を作ってみる。
$ kubectl apply -f deployment.yaml
deployment.apps/helloworld-deployment created
すると、次のようにそれぞれのオブジェクトができた。
Pod を見ると、ちゃんとそれぞれのワーカーで動作している様子が確認できる。
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
helloworld-deployment 2/222 12s
$ kubectl get replicaset
NAME DESIRED CURRENT READY AGE
helloworld-deployment-d857c4cb6 222 25s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
helloworld-deployment-d857c4cb6-8tvzk 1/1 Running 0 44s
helloworld-deployment-d857c4cb6-zcfl7 1/1 Running 0 44s
Pod に HTTP でアクセスする
続いては上記の Pod に HTTP でアクセスしてみる。
kubectl expose deployment コマンドで Service オブジェクトを作る。
ちなみに、デフォルトでは --type=LoadBalancer な Service は作れないようだ。
$ kubectl delete service helloworld-deployment
$ kubectl expose deployment helloworld-deployment --type=LoadBalancer
service/helloworld-deployment exposed
$ kubectl get services -l app=helloworld
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloworld-deployment LoadBalancer 10.96.93.210<pending>8080:30640/TCP 20s
上記のように、状態が <pending> となっており、IP アドレスが割り振られない。
確認が済んだら Service を削除しておこう。
$ kubectl delete service helloworld-deployment
オートヒーリングを確認する
続いてはオートヒーリングの様子を観察するために Pod を壊してみよう。
まずは今の Pod の状態をかくにんしておく。
$ kubectl get pods -l app=helloworld
NAME READY STATUS RESTARTS AGE
helloworld-deployment-d857c4cb6-8tvzk 1/1 Running 0 8m9s
helloworld-deployment-d857c4cb6-zcfl7 1/1 Running 0 8m9s
ここで、Pod を片方削除してみよう。
$ kubectl delete pods helloworld-deployment-d857c4cb6-8tvzk
pod "helloworld-deployment-d857c4cb6-8tvzk" deleted
別のターミナルから Pod の状態を確認すると、指定した Pod が削除されて新たに別の Pod が作られる様子が見える。
$ kubectl get pods -l app=helloworld
NAME READY STATUS RESTARTS AGE
helloworld-deployment-d857c4cb6-8tvzk 0/1 Terminating 0 9m29s
helloworld-deployment-d857c4cb6-ndprj 1/1 Running 0 34s
helloworld-deployment-d857c4cb6-zcfl7 1/1 Running 0 9m29s
最終的には以下のように Pod が 2 つの状態で安定する。
$ kubectl get pods -l app=helloworld
NAME READY STATUS RESTARTS AGE
helloworld-deployment-d857c4cb6-ndprj 1/1 Running 0 45s
helloworld-deployment-d857c4cb6-zcfl7 1/1 Running 0 9m40s
また、ログを確認すると Pod が作り直されていることがわかる。
$ kubectl describe replicaset helloworld-deployment | tail
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 11m replicaset-controller Created pod: helloworld-deployment-d857c4cb6-8tvzk
Normal SuccessfulCreate 11m replicaset-controller Created pod: helloworld-deployment-d857c4cb6-zcfl7
Normal SuccessfulCreate 2m49s replicaset-controller Created pod: helloworld-deployment-d857c4cb6-ndprj
$ python benchmark.py
unable to import 'smart_open.gcs', disabling that module
MainThread - gensim.models.base_any2vec - WARNING - consider setting layer size to a multiple of 4for greater performance
/Users/amedama/.virtualenvs/py37/lib/python3.7/site-packages/gensim/models/base_any2vec.py:743: UserWarning: C extension not loaded, training will be slow. Install a C compiler and reinstall gensim for fast training.
"C extension not loaded, training will be slow. "
MainThread - gensim.models.word2vec - INFO - collecting all words and their counts
MainThread - gensim.models.word2vec - INFO - PROGRESS: at sentence #0, processed 0 words, keeping 0 word types
...
MainThread - gensim.models.base_any2vec - INFO - training model with 3 workers on 71290 vocabulary and 50 features, using sg=1 hs=1 sample=0.001 negative=5 window=5
MainThread - gensim.models.base_any2vec - INFO - EPOCH 1- PROGRESS: at 0.06% examples, 151 words/s, in_qsize 5, out_qsize 0
MainThread - gensim.models.base_any2vec - INFO - EPOCH 1- PROGRESS: at 0.18% examples, 447 words/s, in_qsize 6, out_qsize 0
MainThread - gensim.models.base_any2vec - INFO - EPOCH 1- PROGRESS: at 0.24% examples, 309 words/s, in_qsize 5, out_qsize 0
MainThread - gensim.models.base_any2vec - INFO - EPOCH 1- PROGRESS: at 0.29% examples, 379 words/s, in_qsize 5, out_qsize 0
$ head $(python -c "from gensim.test.utils import datapath; print(datapath('wordsim353.tsv'))"2>/dev/null)# The WordSimilarity-353 Test Collection (http://www.cs.technion.ac.il/~gabr/resources/data/wordsim353/)# Word 1 Word 2 Human (mean)
love sex 6.77
tiger cat 7.35
tiger tiger 10.00
book paper 7.46
computer keyboard 7.62
computer internet 7.58
plane car 5.77
train car 6.31
>>> from itertools import chain
>>> correct = len(list(chain.from_iterable(s['correct'] for s in analogy_scores[1])))
>>> incorrect = len(list(chain.from_iterable(s['incorrect'] for s in analogy_scores[1])))
>>> correct / (correct + incorrect)
0.7492042304138001