2023年になった。東京駅に人を見送りに来てひまになったので有楽町のビックカメラ7Fにあるカフェで gokart をお試ししてみた。
gokart とは
gokart はエムスリーが開発している機械学習パイプラインツール。 Spotify により開発されている luigi のラッパーになっている。
機械学習モデルを開発していると前処理、事前学習、ファインチューニング、可視化などなど工程が多く、管理が大変になる。パイプラインツールを使って楽になるのか試してみた。内容的にはただ以下の公式ドキュメントに沿って動かしただけ。
quickstart で動作を理解する
の部分にしたがって動作を理解する。
pip install gokart
以下を quickstart.py
として保存して実行する。
import gokart
class Example(gokart.TaskOnKart):
def run(self):
self.dump('Hello, world!')
task = Example()
output = gokart.build(task)
print(output)
$ python quickstart.py
Hello, world!
$ tree
.
├── quickstart.py
└── resources
├── __main__
│ └── Example_8441c59b5ce0113396d53509f19371fb.pkl
└── log
├── module_versions
│ └── Example_8441c59b5ce0113396d53509f19371fb.txt
├── processing_time
│ └── Example_8441c59b5ce0113396d53509f19371fb.pkl
├── random_seed
│ └── Example_8441c59b5ce0113396d53509f19371fb.pkl
├── task_log
│ └── Example_8441c59b5ce0113396d53509f19371fb.pkl
└── task_params
└── Example_8441c59b5ce0113396d53509f19371fb.pkl
resources
に実行結果やログが保存されている。
import pickle
with open('resources/__main__/Example_8441c59b5ce0113396d53509f19371fb.pkl', 'rb') as f:
print(pickle.load(f)) # Hello, world!
with open('resources/log/processing_time/Example_8441c59b5ce0113396d53509f19371fb.pkl', 'rb') as f:
print(pickle.load(f)) # 0.0002276897430419922
with open('resources/log/random_seed/Example_8441c59b5ce0113396d53509f19371fb.pkl', 'rb') as f:
print(pickle.load(f)) # {'seed': 1770683860, 'seed_methods': ['random.seed', 'numpy.random.seed']}
with open('resources/log/task_params/Example_8441c59b5ce0113396d53509f19371fb.pkl', 'rb') as f:
print(pickle.load(f)) # {}
$ cat resources/log/module_versions/Example_8441c59b5ce0113396d53509f19371fb.txt
# 空
タスクの実行
もやってみる。
タスクを実行するには run
と build
があり、どちらかだけを使うべきらしい。 run
が普通のスクリプト用で、 build
が Jupyter や IPython 用らしい。
run
を使ってみるには以下を sample.py
として保存する。
import gokart
import luigi
class SampleTask(gokart.TaskOnKart):
param = luigi.Parameter()
print(param)
def run(self):
self.dump(self.param)
gokart.run()
以下のコマンドで実行する。
python sample.py SampleTask --local-scheduler --param=hello
コマンド実行を Python 内でするには
gokart.run(['SampleTask', '--local-scheduler', '--param=hello'])
でできる。
自分でタスクを定義するにはクラスを作れば良いはず。self.dump()
で作った pickle を下流のタスクに受け継いでいくのだと思う。より理解を深めるために言語処理100本ノックとかを題材にやってみたい。
チュートリアル
M3 の推奨するのは coockiecutter でテンプレートから生成するという使い方らしい。こちらもやってみる。
$ pip install cookiecutter
$ cookiecutter https://github.com/m3dev/cookiecutter-gokart
project_name [project_name]: nlp100
package_name [package_name]: gokart_nlp100
python_version [3.7.0]: 3.10
author [your name]: pn11
package_description [What's this project?]: nlp100 using gokart
license [MIT License]:
$ tree
.
├── __init__.py
├── model
│ ├── __init__.py
│ └── sample.py
└── utils
└── template.py
2 directories, 4 files
$ python main.py gokart_nlp100.Sample --local-scheduler
/Users/pn11/git/luigi-nlp100/.venv/lib/python3.10/site-packages/luigi/configuration/core.py:89: UserWarning: Config for ini parser added, but used cfg parser. Set up right parser via env var: export LUIGI_CONFIG_PARSER=ini
warnings.warn(msg.format(added=parser, used=default_parser))
[2023/01/02 15:38:14][luigi][INFO](setup_logging.py:75) logging configured via *.conf file
[2023/01/02 15:38:14][luigi-interface][INFO](worker.py:625) Informed scheduler that task gokart_nlp100.Sample__99914b932b has status PENDING
[2023/01/02 15:38:14][luigi-interface][INFO](interface.py:172) Done scheduling tasks
[2023/01/02 15:38:14][luigi-interface][INFO](worker.py:1214) Running Worker with 1 processes
[2023/01/02 15:38:14][luigi-interface][INFO](worker.py:162) [pid 14827] Worker Worker(salt=6452722305, workers=1, host=MacBook-Air.local, username=pn11, pid=14827) running gokart_nlp100.Sample()
[2023/01/02 15:38:14][luigi-interface][INFO](worker.py:220) [pid 14827] Worker Worker(salt=6452722305, workers=1, host=MacBook-Air.local, username=pn11, pid=14827) done gokart_nlp100.Sample()
[2023/01/02 15:38:14][luigi-interface][INFO](worker.py:625) Informed scheduler that task gokart_nlp100.Sample__99914b932b has status DONE
[2023/01/02 15:38:14][luigi-interface][INFO](worker.py:518) Worker Worker(salt=6452722305, workers=1, host=MacBook-Air.local, username=pn11, pid=14827) was stopped. Shutting down Keep-Alive thread
[2023/01/02 15:38:14][luigi-interface][INFO](interface.py:175)
===== Luigi Execution Summary =====
Scheduled 1 tasks of which:
* 1 ran successfully:
- 1 gokart_nlp100.Sample(...)
This progress looks :) because there were no failed tasks or missing dependencies
===== Luigi Execution Summary =====
なんかできた。これをやることによっておそらくタスクを再利用しやすくなるなどのメリットがあるのだと思うが、とりあえずはテンプレート使わずにオレオレファイル構造で良いかな。
この部分読んでたら typo みつけたのでプルリク出しといた。新年初プルリク。