最近山ほどPythonのパッケージを作っている。
というのも、パッケージの配布方法を身に着けてからは過去のパッケージとは呼べないコードの山がただのゴミに思えてきて、そのゴミをリサイクルするためにまともなパッケージ化を進めている。 基本的に同じ作業なので、だた仕事が急に大量発生しただけである。
そのゴミの一つとして、ygo-agent
を思い出して、現在掘り起こして作業中である。
強化学習によって遊戯王オフィシャルカードゲームのエージェントを作ろうというプロジェクトであったが、有限時間でニューラルネットワーク学習できる環境及びコードが用意できなくて、2021年5月からずっと放置していた。
では、なぜ今更掘り起こしたかというと改善案が浮かんだからである。 それを忘れないうちにここにメモでもしておこうかなと。
決定木
モチベーションが落ちた理由はTensorFlowでNNを実装しても実行環境が用意できないためであった。 ちなみに現在も実行環境は用意できていない。
そもそも「2階のテンソルで表現することの難しい遊戯王をビット列に変換するなどして無理やりテンソルの形にしていたのが無茶だったのでは?」と思い始めて、別のアルゴリズムでの強化学習を考えることにした。
一番最初に記憶から浮かんできたのが「決定木」である。 「決定木アルゴリズム」は簡単に説明すると、ツリー上の条件分岐を経て出力を決定するアルゴリズムで、その条件分岐の条件を最適化してしていく事でヒューリスティック解を得るという手法である。
よくよく考えてみると、我々もカードゲームをするときは決定木で判断していないか?
「現在の手札にあれとこれがあって、相手の手札に○○が確定していて、残りライフが××で~」みたいに一つ一つ条件を確認しながら、最終的にプレイするカードを決めているはずだ。
決定木は古典的なアルゴリズムだが、カードゲームをする人間の思考回路と似ていると所から遊戯王との親和性は高いと思われる。
決定木の最適化
問題はどのように決定木を作成し、最適化するかという点である。 ニューラルネットワークは使えない。
次に記憶から浮かんできたのは「遺伝的アルゴリズム」である。 「遺伝的アルゴリズム」は複数のインスタンスを作成し、「交配」と「淘汰」を何世代も繰り返すことで解を得るアルゴリズムである。
実はこのアルゴリズムは最適解へ収束するという保証はない。 我々生物の仕組みを模倣しているので、ある程度良い方向に改善されることが期待できるが、基本的に突然変異に頼った博打アルゴリズムである。 また、複数のインスタンスを作成してそれぞれの”性能”を評価するため計算コストも高い。
こんな欠陥だらけの古典的アルゴリズムであるが、それでも私が期待するのはそれがいわゆる”調整”のプロセスに似ているからである。 ”調整”とは即ち、何回かの試行を通して裏目や新たな選択肢を見つける作業である。
いや待て。書いていて思ったが、”調整”のトライアンドエラープロセスはニューラルネットワークのほうが似てないか? いやでもニューラルネットワークも遅いしハイパーパラメータの調整も上手くいかないし・・・
まあ、なんか良い感じのアルゴリズム考えておきます。
Pythonのパッケージ化
諸君の中にはPython初心者を抜け出して、まとまったパッケージを書けるようになったが配布の方法がワカラナイという者がいるかもしれない。
そこで私のやっているパッケージ配布の3分クッキングを紹介しよう。
ディレクトリの整理
プロジェクト名 ├─.git ├─tests ├─パッケージ名 ├─LICENSE ├─README.md ├─setup.cfg └─setup.py
最小構成だとこんな感じ。
import パッケージ名
で読み込むのでプロジェクト名は何でもいいです。
tests
テストコードを収納するディレクトリ。
テストコードは配布物に混ぜる必要がないから分けておく。
LICENSE, README.md
配布するつもりならどちらもしっかり用意しておきたい。
setup.cfg
pip
などのパッケージインストーラー(厳密にいえばsetup.py
)が参照する設定ファイル。
コピペして名前とか変えればOK。
[metadata] name = ygocore-python version = attr: ygocore.__VERSION__ author = hinihatetsu author_email = hinihatetsu@example.com url = https://github.com/hinihatesu/ygocore-python description = YGO core package for Python long_description = file: README.md license = MIT license_file = LICENSE [options] python_requires = >= 3.8 # Python 3.8 以上 include_package_data = True packages = find: # プロジェクトディレクトリから__init__.pyのあるディレクトリを自動でパッケージ化 test_suite = tests install_requires = # pip install 時に一緒にインストールされるパッケージ library1 library2 [options.packages.find] exclude = tests # testsは配布しないので除外
他にもオプションがあるので慣れたら調べてみると良い。
setup.py
from setuptools import setup setup()
これだけ。
あとはGithub
に挙げておけば,
$ pip install git+https://github.com/yourname/yourprogect
でインストールできる。
PyPI
はまた今度。
おまけ
そういえば夏休み中にR
習得して、今年の目標Jupyter
を達成したのだが、結局「データ分析?えーPythonで!」てなりそうな気がする。
R
は統計処理に向いた言語っていうけど、まともにデータ分析しようと思ったらtibble
とかggplot
のライブラリに頼らないといけないし、若干改善されてました!(2021/12/04)でVSCode
+Jupyter
での使い勝手が悪いし(改行するごとに#を入力しなければならない)Python
かJulia
でいいかな~と。
アプリケーションレベルになるとJulia
は学術色が強いから選択肢から外れがち。結局残るのがPython
て感じ。
Julia
の多重ディスパッチはあるレベル以上のアプリケーションからは足かせになるイメージ。
日常の業務だとnode.js
のデフォルト非同期処理はあまりに面倒だし、Go
も産業用プログラミング言語って感じ。
吐き出てきたエラーとか見てると、「ああ~これもGo
で動いてんのか~」と普及率に結構驚く。
でもモダンなフロントエンド作るときはVue.js
使うし、クロスプラットフォームのバイナリを生成したい時はGo
使うから適材適所ってことね。
個人用のライトなアプリケーション作りたい私にはPython
がマッチしていたってだけ(動きはヘヴィーだけど)。