ygo-agent

最近山ほどPythonのパッケージを作っている。

というのも、パッケージの配布方法を身に着けてからは過去のパッケージとは呼べないコードの山がただのゴミに思えてきて、そのゴミをリサイクルするためにまともなパッケージ化を進めている。 基本的に同じ作業なので、だた仕事が急に大量発生しただけである。

そのゴミの一つとして、ygo-agentを思い出して、現在掘り起こして作業中である。

強化学習によって遊戯王オフィシャルカードゲームのエージェントを作ろうというプロジェクトであったが、有限時間でニューラルネットワーク学習できる環境及びコードが用意できなくて、2021年5月からずっと放置していた。

では、なぜ今更掘り起こしたかというと改善案が浮かんだからである。 それを忘れないうちにここにメモでもしておこうかなと。

決定木

モチベーションが落ちた理由はTensorFlowでNNを実装しても実行環境が用意できないためであった。 ちなみに現在も実行環境は用意できていない。

そもそも「2階のテンソルで表現することの難しい遊戯王をビット列に変換するなどして無理やりテンソルの形にしていたのが無茶だったのでは?」と思い始めて、別のアルゴリズムでの強化学習を考えることにした。

一番最初に記憶から浮かんできたのが「決定木」である。 「決定木アルゴリズム」は簡単に説明すると、ツリー上の条件分岐を経て出力を決定するアルゴリズムで、その条件分岐の条件を最適化してしていく事でヒューリスティック解を得るという手法である。

f:id:nnt339:20211015073700p:plain
https://analysis-navi.com/?p=2007 より引用

よくよく考えてみると、我々もカードゲームをするときは決定木で判断していないか?

「現在の手札にあれとこれがあって、相手の手札に○○が確定していて、残りライフが××で~」みたいに一つ一つ条件を確認しながら、最終的にプレイするカードを決めているはずだ。

決定木は古典的なアルゴリズムだが、カードゲームをする人間の思考回路と似ていると所から遊戯王との親和性は高いと思われる。

決定木の最適化

問題はどのように決定木を作成し、最適化するかという点である。 ニューラルネットワークは使えない。

次に記憶から浮かんできたのは「遺伝的アルゴリズム」である。 「遺伝的アルゴリズム」は複数のインスタンスを作成し、「交配」と「淘汰」を何世代も繰り返すことで解を得るアルゴリズムである。

実はこのアルゴリズムは最適解へ収束するという保証はない。 我々生物の仕組みを模倣しているので、ある程度良い方向に改善されることが期待できるが、基本的に突然変異に頼った博打アルゴリズムである。 また、複数のインスタンスを作成してそれぞれの”性能”を評価するため計算コストも高い。

こんな欠陥だらけの古典的アルゴリズムであるが、それでも私が期待するのはそれがいわゆる”調整”のプロセスに似ているからである。 ”調整”とは即ち、何回かの試行を通して裏目や新たな選択肢を見つける作業である。

いや待て。書いていて思ったが、”調整”のトライアンドエラープロセスはニューラルネットワークのほうが似てないか? いやでもニューラルネットワークも遅いしハイパーパラメータの調整も上手くいかないし・・・

まあ、なんか良い感じのアルゴリズム考えておきます。

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のライブラリに頼らないといけないし、若干VSCode+Jupyterでの使い勝手が悪いし(改行するごとに#を入力しなければならない)改善されてました!(2021/12/04)でPythonJuliaでいいかな~と。

アプリケーションレベルになるとJuliaは学術色が強いから選択肢から外れがち。結局残るのがPythonて感じ。 Juliaの多重ディスパッチはあるレベル以上のアプリケーションからは足かせになるイメージ。

日常の業務だとnode.jsのデフォルト非同期処理はあまりに面倒だし、Goも産業用プログラミング言語って感じ。 吐き出てきたエラーとか見てると、「ああ~これもGoで動いてんのか~」と普及率に結構驚く。

でもモダンなフロントエンド作るときはVue.js使うし、クロスプラットフォームのバイナリを生成したい時はGo使うから適材適所ってことね。

個人用のライトなアプリケーション作りたい私にはPythonがマッチしていたってだけ(動きはヘヴィーだけど)。