2技関係によるパーティ強さの予測(初代全ポケモン参加)【PokéAI】

前回の記事で、山登り法によるパーティの最適化をポケモン3匹のパーティについて実験しました。

select766.hatenablog.com

そこで生じた問題の1つは、探索空間が広すぎるためか最適化結果が芳しくないというものでした。 1匹のポケモンの構成パターンが仮に1億通り*1あるとして、3匹の組み合わせとなると1億の3乗となり、大幅に最適化が難しくなっている可能性があります。

解決策として、ランダムに探索を行うよりも有望なパターンに絞って探索を進める方法が考えられます。 例えば、現在の方法だと技「なみのり」を強力な「ふぶき」に置換した場合と明らかに弱い「みずでっぽう」に置換した場合を等確率で生成し、 ランダムに対戦させて強さを測る(それなりに時間がかかる)という方法になっています。 ここで明らかに良さそうな「ふぶき」のパターンを生成する確率を高めることで、探索の無駄を減らせるはずです。 そのための考え方として、経路探索におけるA*のように、解の良さを近似的に表現してくれるヒューリスティックの導入を考えます。 ここでは、パーティ構成を与えると、その強さの近似値を出力するような関数を作成します。 もともと山登り法で強いパーティを選択する方法は他のパーティと多数対戦させて勝率(レート)を計算するというものであり、 そのパーティ候補を作成するためのヒューリスティックなので、これより圧倒的に高速に計算できないと意味がありません。

そこで、パーティに含まれるポケモンや技に対して点数を与え、合計得点によって強さを予測(近似)する手法を提案します。 簡単に言えば、パーティにフーディンがいれば+10点、コイキングがいれば-10点、サイコキネシスを覚えていれば+5点…のようにパーティの要素それぞれに点数をつけることでその強さを予測しようという発想になります。

技術的には以前の記事の焼き直しになりますので、先にそちらをご覧ください。 以前との違いは、ポケモンの種類が20種類から151種類(初代全ポケモン)に拡張されたこと、回帰先が勝率から正規化されたレートに変更された点です。

select766.hatenablog.com

特徴量は上の記事と変わりませんが、ポケモン・技の種類が増えているので次元数は大きく増えています。該当する要素が1、それ以外が0となるベクトルで、正規化はしていません。

  • P
  • M
    • 単独の技 (165)
  • PP
  • MM
    • あるポケモンが覚えている2つの技の組 (165*(165-1)/2=13530)
  • PM
    • ポケモンと、それが覚えている技の組 (151*165=24915)

合計で50086次元となります。

データ

データは、ランダムに生成された10,000パーティを相互に対戦させて得たレートです。 パーティから対戦なしにレートを予測するモデルをリッジ回帰で学習します。 ライブラリはscikit-learnです。

入力となるパーティとレート(上に表示)の例を示します。上位、下位を抜粋しています。

2038.1734179741654
* ゲンガー (LV 50 HP 167/167)
  のしかかり ちきゅうなげ 10まんボルト メガトンキック 
  タッツー (LV 50 HP 137/137)
  みずでっぽう あわ スピードスター すてみタックル 
  カイリュー (LV 55 HP 216/216)
  のしかかり だいもんじ りゅうのいかり ふぶき 

2036.6117272435956
* サンダー (LV 50 HP 197/197)
  ドリルくちばし 10まんボルト かみなり ふきとばし 
  プテラ (LV 55 HP 204/204)
  つばさでうつ ねむる すてみタックル はかいこうせん 
  ゲンガー (LV 50 HP 167/167)
  さいみんじゅつ あやしいひかり ナイトヘッド どくどく 

2023.1601683063693
* バタフリー (LV 50 HP 167/167)
  ふきとばし サイコウェーブ ねんりき しびれごな 
  アーボック (LV 50 HP 167/167)
  あなをほる すてみタックル じわれ はかいこうせん 
  ゲンガー (LV 55 HP 182/182)
  サイコキネシス サイコウェーブ あやしいひかり かみなり 

873.1324613556571
* コイキング (LV 55 HP 138/138)
  はねる たいあたり 
  コクーン (LV 50 HP 152/152)
  かたくなる どくばり いとをはく 
  パラス (LV 50 HP 142/142)
  キノコのほうし つるぎのまい すてみタックル しびれごな 

869.9415352355768
* マルマイン (LV 55 HP 182/182)
  だいばくはつ ソニックブーム リフレクター はかいこうせん 
  タマタマ (LV 50 HP 167/167)
  さいみんじゅつ リフレクター どくのこな テレポート 
  コイキング (LV 50 HP 127/127)
  はねる たいあたり 

868.9717116445033
* コイキング (LV 50 HP 127/127)
  たいあたり はねる 
  ドガース (LV 50 HP 147/147)
  どくどく ヘドロこうげき じばく だいもんじ 
  トランセル (LV 55 HP 171/171)
  かたくなる たいあたり いとをはく 

リッジ回帰の精度

各特徴を用いた場合に、回帰精度がどう変化するかを調べました。 リッジ回帰のパラメータ"C"は、{1e-4, 1e-3, 1e-2, 1e-1, 1e0}の中から5-fold cross validationで最善のものを選択しました。特徴の組み合わせごとに別の値になっている場合があります。

精度は決定係数で表示しています。1に近いほど良い結果を意味します。

P M PP MM PM 決定係数
Y 0.509
Y 0.480
Y Y 0.749
Y 0.217
Y Y 0.482
Y 0.432
Y Y 0.494
Y Y Y Y 0.737
Y Y Y Y Y 0.769

すべての特徴量を使用した場合が一番いい結果となりました。PP特徴だけの場合は極端に精度が悪いことがわかりました。 PPはポケモンの組み合わせなので、10000次元ほどあるうちで1パーティでは3つしか要素がありません。10000パーティあっても各次元は平均3回程度しか使用されず、学習データ不足だといえます。

学習結果の観察

学習したモデルは線形モデルなので、各要素の重みから重要度を読み取ることができます。ここでは、正の値ならパーティを強くする方向に、負の値なら弱くする方向に作用している要素だとみなすことができます。

全特徴を利用して学習したモデルについて、特徴の種類ごとにtop10, worst10を表示しました。

P特徴

重み 意味
0.394 ゲンガー
0.362 ケンタロス
0.333 ギャラドス
0.314 ラプラス
0.310 カイリュー
0.268 スターミー
0.268 フリーザ
0.263 サンダー
0.259 カブトプス
0.256 オムスター
-0.312 プリン
-0.259 ニョロモ
-0.241 コラッタ
-0.237 ミニリュウ
-0.227 ヒトカゲ
-0.224 ゼニガメ
-0.217 コダック
-0.215 ケーシィ
-0.214 コンパン
-0.211 ズバット

ゲンガー・ケンタロスなどおなじみのポケモンが強いという結果です。5位にカイリューが来ています。ランダムに生成したパーティなので、ふぶきが多用されないことが上位に来られた理由だと思われます。 逆に言えば、強いパーティばかりの環境においてモデルを学習すれば違う値になるだろうと予想できます。 下位のほうは意外な結果です。コイキングトランセルが来るわけではないようです。

M特徴

重み 意味
0.339 ふぶき
0.281 サイコキネシス
0.259 ハイドロポンプ
0.241 ナイトヘッド
0.237 れいとうビーム
0.217 はなびらのまい
0.198 はかいこうせん
0.198 なみのり
0.195 10まんボルト
0.193 かえんほうしゃ
-0.361 じばく
-0.281 いとをはく
-0.236 だいばくはつ
-0.218 はねる
-0.214 ふきとばし
-0.204 テレポート
-0.203 こうそくいどう
-0.185 なきごえ
-0.181 にらみつける
-0.177 せいちょう

上位は強い技、下位は弱い技が順当に出ています。じばく・だいばくはつは適切なタイミングで使えば強力ですが、ランダムに発動しているため最悪です。 ここでトランセルが覚えるいとをはくや、コイキングが覚えるはねるがかなり負の大きな係数になっているので、 技だけで十分予測ができてしまいポケモンの側ではこれらの係数があまり大きくならなかったのかもしれません。

PP特徴

重み 意味
0.060 ニョロボン,ベトベター
0.060 オニスズメ,ペルシアン
0.059 ラッキー,ヒトデマン
0.056 リザードン,カメックス
0.055 コダック,アズマオウ
0.052 ガルーラ,ハクリュー
0.052 ピカチュウ,ウツボット
0.050 マルマイン,ナッシー
0.050 トランセル,サイドン
0.050 マタドガス,カビゴン
-0.068 ゼニガメ,アーボ
-0.060 ディグダ,ニャース
-0.060 スリープ,ミニリュウ
-0.057 エビワラー,ドガース
-0.056 トランセル,パラス
-0.056 ダグトリオ,スリープ
-0.051 ズバット,タマタマ
-0.050 リザード,ポッポ
-0.050 バタフリー,トサキント
-0.050 ニドラン♀,プリン

ポケモン同士の相性補完などが表現されることを期待したのですが、解釈しづらい結果です。係数が小さく、ほとんど役に立っていないという状況です。 ポケモンの行動がランダムなので、相性が悪いときに交代するなどの戦略が加味されていないという原因もありそうです。

MM特徴

重み 意味
0.161 だいばくはつ,じばく
0.142 ナイトヘッド,サイコキネシス
0.132 さいみんじゅつ,メガドレイン
0.129 サイコキネシス,でんじは
0.123 はかいこうせん,つるぎのまい
0.117 メガドレイン,ねむりごな
0.112 かげぶんしん,ナイトヘッド
0.112 さいみんじゅつ,サイコキネシス
0.112 いあいぎり,ちきゅうなげ
0.109 サイコウェーブ,10まんボルト
-0.188 はねる,たいあたり
-0.172 だいばくはつ,ナイトヘッド
-0.163 どくばり,いとをはく
-0.163 いとをはく,たいあたり
-0.157 さいみんじゅつ,じばく
-0.151 メガドレイン,じばく
-0.148 かげぶんしん,ふきとばし
-0.148 サイコウェーブ,じばく
-0.145 だいばくはつ,ねむる
-0.123 にらみつける,ふきとばし

意外にも、だいばくはつ,じばくの組が最上位です。M特徴でどちらも非常に大きい負の値ですが、両方覚えていたとしても片方を覚える以上に悪くならないということで補正がかかっているようです。 上位では有力な攻撃技と補助技の組み合わせが良く出てきているようです。

PM特徴

重み 意味
0.195 フリーザー,れいとうビーム
0.193 サンダー,10まんボルト
0.184 ゴースト,ナイトヘッド
0.183 フーディン,サイコキネシス
0.180 サンダー,ねむる
0.169 サンダース,かみなり
0.166 フリーザー,ふぶき
0.165 ナッシー,サイコキネシス
0.160 ファイヤー,ゴッドバード
0.159 ファイヤー,だいもんじ
-0.191 ゴースト,だいばくはつ
-0.182 ゲンガー,じばく
-0.181 ゴースト,じばく
-0.179 コイキング,たいあたり
-0.179 コイキング,はねる
-0.163 ゲンガー,だいばくはつ
-0.152 キャタピー,たいあたり
-0.152 キャタピー,いとをはく
-0.150 ヤドン,じわれ
-0.147 パウワウ,つのドリル

上位はタイプ一致攻撃技が主です。同じ技でも運用するポケモンとの相性のような部分を取り出せていることが期待できます。 下位は有用でない技が出てきています。じわれは一見強そうですが、初代では相手より素早くないと命中しないため、素早さが低いヤドンでは有効でないということでしょう。

定性的にも面白い結果が得られました。定量的にもある程度うまくいっているようなので、今後このモデルを探索に組み込んでみようと思います。

*1:ポケモン150種類×技候補30種類の4乗ぐらい

技術書典5の本を国会図書館に納本しました

先日、「技術書典5で頒布した本を国立国会図書館に納本した」との記事を見かけました。

note.mu

制度の概要については上の記事が詳しいのでそちらをご覧ください。

納本のお願い|国立国会図書館―National Diet Library

国会図書館にはあらゆる本が入っているとは聞いたことがありましたが、同人誌であっても納本は義務なんですね。しかも罰則規定あり。 同人誌を納本するという記事があえて存在するぐらいなので、ほとんどの人は納本していないと思われます。 「同人作家の9割は犯罪者!」という表現が成り立ちそうでちょっと怖いところです。

郵送でもいいらしいのですが、国会図書館に行ったことがなかったので見物がてら納本しに行きました。

国会図書館は国会議事堂のすぐ近くにあります。普通の入り口ではなくて、関係者用っぽい西口から入る必要がありました。

納本手続きのカウンターへ行き、現物を提出の上氏名・住所・書名などを書けばすぐに納本できました。

受領書がこちら。あとで郵送でももらえるようです。

f:id:select766:20181109172839j:plain

書名が長くてすみません。

これにて私の本は、日本が続く限り未来永劫残り続けるでしょう。なんか生きた証を残したような気分です(大袈裟)。

5月に同人誌を納本した方がいるのですが、国立国会図書館サーチにおいてタイトルで検索したら出てくるのか試してみました。

prehyou2015.hatenablog.com

プリキュアの数字ブログのほん (@kasumi): 2018|書誌詳細|国立国会図書館サーチ

ちゃんと出るようです。納本の時の書類に自分の名前は書いたのですが、本の発行者名などを書く場所はありませんでした。この辺は奥付などから入力されるのでしょうか? 自分の本がもし検索にかかるようになったら見ておきたいと思います。

納本した本は国会図書館で読めると思いますが、面倒だという方のために(?)オンラインで電子書籍を販売していますのでよろしければどうぞ。

select766.booth.pm

以下、2018-11-19追記

郵送で受領書が届きました。そして検索にもかかるようになっていました。これにて納本完結。

http://iss.ndl.go.jp/books/R100000002-I029322458-00

f:id:select766:20181119182814p:plain

3体構成での山登り法試行【PokéAI】

パーティに3体のポケモンを入れるという条件でのパーティ構成の最適化に着手しました。 手法は1体のみの時と同様の山登り法で、3体対応のための最低限のコードを足して動かしてみました。

山登り法は、パーティXがあるときに、その近傍となる少し変更されたパーティX1, X2, ...を生成し、それらの中で最良のものを採用するという処理を繰り返します。 1体のみの場合は、ポケモンの技をランダムに変更することをもって近傍を生成しました。ポケモン自体を変更すると、覚えられる技が違う都合で近傍ではない全く別物になってしまうため変更は行いませんでした。 3体への拡張では、3体のうち1体のポケモンの種類を変更しても近傍と呼べるため、ポケモンの変更も含めた近傍を生成するようにしました。 これにより、1体の時に問題となった、「初期値としてトランセルを選択したため最適化できない」という状況を脱することができます。

近傍パーティの生成部分をparty_generator.pyから抜粋します。

    def generate_neighbor_party(self, party: Party) -> Party:
        """
        近傍の(1匹の技を1個だけ変更するか、別のポケモンにする)パーティを生成する。
        :param party:
        :return:
        """
        pokests = [copy.deepcopy(poke.poke_static) for poke in party.pokes]
        target_idx = np.random.randint(len(pokests))
        if np.random.random() < self.neighbor_poke_change_rate:
            # ポケモンを新しいものに変更
            exclude_dexnos = {pokest.dexno for pokest in pokests}
            new_pokest = self._generate_poke(pokests[target_idx].lv, exclude_dexnos)
            pokests[target_idx] = new_pokest
        else:
            # 技を変更
            pokest = pokests[target_idx]
            moves = pokest.moves
            learnable_moves = self.db.get_leanable_moves(pokest.dexno, pokest.lv)
            for m in moves:
                learnable_moves.remove(m)
            if len(learnable_moves) == 0 and len(moves) == 1:
                # 技を1つしか覚えないポケモン(LV15未満のコイキング等)
                # どうしようもない
                pass
            elif len(learnable_moves) == 0 or (np.random.random() < self.neighbor_move_remove_rate and len(moves) > 1):
                # 技を消す
                moves.pop(randint_len(moves))
            elif np.random.random() < self.neighbor_move_add_rate and len(moves) < 4:
                # 技を足す
                moves.append(learnable_moves[randint_len(learnable_moves)])
            else:
                # 技を変更する
                new_move = learnable_moves[randint_len(learnable_moves)]
                moves[randint_len(moves)] = new_move
        return Party(pokests)

変更対象のポケモンをランダムに選択したのち、ある確率でポケモンの種類を変更、それ以外の場合は技を変更という仕組みです。 なお、ポケモンのレベルは55,50,50の3体としていますが、ポケモンの種類を変更する場合でもレベルは変えないようにしています。 パーティの初期値生成の際に、レベル55が先頭になるか否かはランダムに決定し、そこだけは最適化を経ても変更できない箇所ということになります。

コードを走らせて動作確認しました。 ランダムなパーティ1000個から上位20個を選択、山登り法で生成したパーティ1000個から上位20個を選択し、合計40パーティでレーティング戦を行いました。 バトル中の行動はすべてランダム(選択肢から等確率に選択)です。

ランダム生成のうち最大レート5パーティ

mean rate=1342.691788688345
1494.527433165117
* カビゴン (LV 50 HP 267/267)
  とっしん いわなだれ サイコキネシス じごくぐるま 
  モルフォン (LV 55 HP 193/193)
  しびれごな サイケこうせん はかいこうせん ソーラービーム 
  ゲンガー (LV 50 HP 167/167)
  すてみタックル メガドレイン 10まんボルト ナイトヘッド 

1461.9702040920563
* ドガース (LV 50 HP 147/147)
  だいばくはつ かみなり ねむる だいもんじ 
  フリーザー (LV 55 HP 215/215)
  ふぶき ゴッドバード れいとうビーム みずでっぽう 
  ガラガラ (LV 50 HP 167/167)
  れいとうビーム ちきゅうなげ しっぽをふる じごくぐるま 

1393.4091097140881
* ベトベトン (LV 50 HP 212/212)
  10まんボルト だいもんじ かみなり どくどく 
  フリーザー (LV 55 HP 215/215)
  リフレクター はかいこうせん ねむる れいとうビーム 
  オムスター (LV 50 HP 177/177)
  ふぶき ロケットずつき れいとうビーム とげキャノン 

1390.3376731078024
* ベロリンガ (LV 50 HP 197/197)
  ロケットずつき どくどく ちきゅうなげ ちょうおんぱ 
  ギャラドス (LV 55 HP 221/221)
  だいもんじ とっしん ふぶき れいとうビーム 
  ピクシー (LV 50 HP 202/202)
  フラッシュ 10まんボルト れいとうビーム ロケットずつき 

1383.3421505910833
* スターミー (LV 50 HP 167/167)
  でんじは すてみタックル バブルこうせん ひかりのかべ 
  フシギソウ (LV 50 HP 167/167)
  どくのこな ねむりごな すてみタックル メガドレイン 
  カビゴン (LV 55 HP 292/292)
  サイコキネシス どくどく いわなだれ ふぶき 

山登り法で生成のうち最大レート5パーティ

mean rate=1657.308211311655
1809.781500071635
* フーディン (LV 55 HP 177/177)
  サイケこうせん サイコキネシス 
  サイドン (LV 50 HP 212/212)
  じごくぐるま いわなだれ かみなり すてみタックル 
  サンダー (LV 50 HP 197/197)
  でんきショック ドリルくちばし どくどく かみなり 

1770.5616980873972
* ラプラス (LV 55 HP 259/259)
  ふぶき なみのり ねむる 10まんボルト 
  サンダース (LV 50 HP 172/172)
  10まんボルト すなかけ かみなり すてみタックル 
  ニドキング (LV 50 HP 188/188)
  ふぶき あばれる 

1743.8845340129867
* サンダー (LV 50 HP 197/197)
  10まんボルト かみなり ドリルくちばし 
  フーディン (LV 55 HP 177/177)
  とっしん サイケこうせん サイコキネシス はかいこうせん 
  ゴースト (LV 50 HP 152/152)
  10まんボルト サイコキネシス メガドレイン 

1742.8628701909133
* サンダー (LV 55 HP 215/215)
  ドリルくちばし 10まんボルト 
  ニョロボン (LV 50 HP 197/197)
  かげぶんしん れいとうビーム さいみんじゅつ 
  ガルーラ (LV 50 HP 212/212)
  のしかかり かいりき とっしん ちきゅうなげ 

1710.7054974571538
* サンダー (LV 55 HP 215/215)
  10まんボルト 
  ジュゴン (LV 50 HP 197/197)
  みずでっぽう どくどく ネコにこばん れいとうビーム 
  ピジョット (LV 50 HP 190/190)
  はかいこうせん そらをとぶ とっしん 

従来のふぶき無双とは異なり、サンダーが一番人気のようです。 最適化の際に技だけでなくポケモンの入れ替えもあるので、覚える技の選択肢が多いポケモンは技が十分最適化されずにほかのポケモンに入れ替えられてしまうのかもしれません。 1体のみの実験で最強クラスだったルージュラよりもサンダーのほうが覚える技が若干少ないので、もしかしたら影響があるのかもしれませんが何とも言えないところです。

また、上位20パーティでもヒトカゲナゾノクサなどの明らかに最適化不足のポケモンが入っている場合がありました。 1体のみの実験と同じように、山登り法で1回あたり10個の近傍パーティ生成、30回反復するようにしたのですが不十分かもしれません。 探索空間が広くなったので、パラメータを見直す必要がありそうです。

コマンド (git 0349f6a)

# グループA(ランダム)の生成
python -m pokeai.agent.make_random_pool group_a.bin 1000 --rule LVSUM155_3
python -m pokeai.agent.rate_random_policy group_a_rate.bin group_a.bin
# グループXの生成
python -m pokeai.agent.make_random_pool group_x.bin 1000 --rule LVSUM155_3
python -m pokeai.agent.rate_random_policy group_x_rate.bin group_x.bin
# グループBシードの生成
python -m pokeai.agent.make_random_pool group_b_seed.bin 1000 --rule LVSUM155_3
# グループBの最適化
python -m pokeai.agent.hill_climbing group_b.bin group_b_seed.bin group_x.bin group_x_rate.bin  --rule_params rule_params.yaml --neighbor 10 --iter  30 --history -j 3
python -m pokeai.agent.rate_random_policy group_b_rate.bin group_b.bin
# 各パーティの上位を選択
python -m pokeai.agent.filter_party group_a_top group_a --count 20
python -m pokeai.agent.filter_party group_b_top group_b --count 20
# レーティング
python -m pokeai.agent.rate_random_policy group_ab_top_rate.bin group_a_top.bin group_b_top.bin

パーティ構成の3体への拡張【PokéAI】

10月の段階ではパーティがポケモン1匹だけで構成されるという条件で実験を行いました。 これからはポケモンの交換という重要な戦略要素を組み込んでいきたいと思います。

今までは実験結果を逐次発表することができていなかったのですが、短い記事でもできるだけ出していって、将来的にまとめという形で本にしたいと思っています。

ルールは初代(赤・緑)で、今までパーティはLV55の1匹だったところをLV50,50,55の3匹を含むように変更します。

パーティのランダム生成・ランダムな技/交代選択により行動させてレーティングを行いました。 レーティングは、パーティ群の中で対戦させてイロレーティングにより決定します。

1000個のパーティを生成し、上位5、下位5パーティを示します。ポケモン名の上の数字がレートです。

2056.896465547251
* カビゴン (LV 50 HP 267/267)
  とっしん いわなだれ サイコキネシス じごくぐるま 
  モルフォン (LV 55 HP 193/193)
  しびれごな サイケこうせん はかいこうせん ソーラービーム 
  ゲンガー (LV 50 HP 167/167)
  すてみタックル メガドレイン 10まんボルト ナイトヘッド 

1950.2153269004948
* ベトベトン (LV 50 HP 212/212)
  10まんボルト だいもんじ かみなり どくどく 
  フリーザー (LV 55 HP 215/215)
  リフレクター はかいこうせん ねむる れいとうビーム 
  オムスター (LV 50 HP 177/177)
  ふぶき ロケットずつき れいとうビーム とげキャノン 

1926.7241752670257
* ドガース (LV 50 HP 147/147)
  だいばくはつ かみなり ねむる だいもんじ 
  フリーザー (LV 55 HP 215/215)
  ふぶき ゴッドバード れいとうビーム みずでっぽう 
  ガラガラ (LV 50 HP 167/167)
  れいとうビーム ちきゅうなげ しっぽをふる じごくぐるま 

1907.9802803141113
* ペルシアン (LV 50 HP 172/172)
  すてみタックル スピードスター ねむる のしかかり 
  サンダー (LV 55 HP 215/215)
  10まんボルト ふきとばし すてみタックル フラッシュ 
  オムスター (LV 50 HP 177/177)
  つのでつく にらみつける ハイドロポンプ ふぶき 

1877.3407709476965
* ラプラス (LV 50 HP 237/237)
  かいりき りゅうのいかり なみのり みずでっぽう 
  サンダー (LV 55 HP 215/215)
  ふきとばし ねむる すてみタックル スピードスター 
  ゴローニャ (LV 50 HP 187/187)
  のしかかり かたくなる あなをほる どくどく 
1003.3507871921275
* コクーン (LV 50 HP 152/152)
  かたくなる どくばり いとをはく 
  ロコン (LV 55 HP 158/158)
  かげぶんしん リフレクター ロケットずつき とっしん 
  ドガース (LV 50 HP 147/147)
  だいばくはつ スモッグ えんまく ヘドロこうげき 

999.0677204852898
* コラッタ (LV 50 HP 137/137)
  みずでっぽう しっぽをふる ひっさつまえば たいあたり 
  タッツー (LV 55 HP 149/149)
  ロケットずつき あわ かげぶんしん こうそくいどう 
  ゴローン (LV 50 HP 162/162)
  じばく かいりき いわおとし ねむる 

993.7741693273923
* コイキング (LV 55 HP 138/138)
  たいあたり はねる 
  ポニータ (LV 50 HP 157/157)
  ひのこ かげぶんしん ロケットずつき ふみつけ 
  ズバット (LV 50 HP 147/147)
  かみつく かげぶんしん きゅうけつ メガドレイン 

989.4486105119751
* ケーシィ (LV 50 HP 132/132)
  ねむる どくどく メガトンパンチ ロケットずつき 
  ゴース (LV 55 HP 149/149)
  したでなめる じばく ゆめくい メガドレイン 
  ゴローニャ (LV 50 HP 187/187)
  のしかかり ちきゅうなげ ねむる じばく 

933.9203855610987
* キャタピー (LV 55 HP 166/166)
  いとをはく たいあたり 
  ポッポ (LV 50 HP 147/147)
  すてみタックル かぜおこし すなかけ こうそくいどう 
  クサイハナ (LV 50 HP 167/167)
  しびれごな どくどく どくのこな かげぶんしん 

上位パーティは強そうなポケモンや技が並んでいます。 タイプのバランスもよさそうに見えますが、それがどの程度効いているかまではわかりません。

これをベースに、またパーティや行動の最適化アルゴリズムを動かしたいと思います。

コマンド (git 0349f6a)*1

python -m pokeai.agent.make_random_pool group_a.bin 1000 --rule LVSUM155_3
python -m pokeai.agent.rate_random_policy group_a_rate.bin group_a.bin

技術書典5 振り返り(当日編)

技術書典5に出展した「ヤマブキ計算所」の記録です。 前の記事からの続きです。当日のことを書きます。

select766.hatenablog.com

売り子

同人誌即売会で出展するのは初めてで、ワンオペは大変だと聞いていました。そのため売り子さんを呼びました。 昔からの知人で、コミケに出展したことがあり、今回の題材であるポケモンも知っているという人材です。 日帰り圏内とはいえ遠方なので、交通費+最低時給相当の数万円を謝礼として支払いました。

入場

サークル入場は行列もなくすぐにでき、設営を開始しました。 印刷所からの段ボールが来ていたので開封の儀を執り行いました。 印刷は期待通りできており、自分の本が完成した感動がありました。

質素ですがこんな感じで設営できました。 f:id:select766:20181015092201j:plain

周囲のサークル配置は深層学習系が集まっていました。特にゲームAIが3連続で、将棋、ぷよぷよポケモンの並びでした。細かい部分まで含めて配置されていたのが好印象でした。

頒布

11時に開場・頒布開始です。入り口から比較的近い場所だったからなのか、はたまた機械学習系が人気なのかすぐに人がたくさんやってきました。 一瞬売り子に任せて混む前に周囲のサークルのものを買っていたら、自分のサークルの最初の1冊が売れるのを見逃してしまいました。惜しいことをしました。

支払い方法として現金と技術書典公式の「かんたん後払い」を用意していました。最初のほうに来た人は結構「かんたん後払い」を利用されました。 事前にアプリを入れておく必要がありますが、意識が高い人が多かったのでしょう。 人は多かったとはいえ、秋葉原で開催していたときより空いていて動きやすそうでした。

内容に関するコメントもいただきました。本文ではさらっと書いていたのですが、(ゲームのルールの)シミュレータを作る部分が大変だよね、ということに気づいてくれた人が数人。 チョットデキル人との対話は楽しいですね。

技術書典なので、電子版単体でいいという人も多いかと思ったのですが紙の本のほうが大幅に売れ行きが良かったです。 予想よりはるかに売れるのが早く、1時間半ほどで紙の本が完売。持っててよかった電子版。

12時10分時点の売り上げ記録です(かんたん=かんたん後払いを利用)。70冊の紙の本が売切れようとしているところで電子版単体は5冊しか出ていませんでした。 f:id:select766:20181015093202j:plain

完売後、電子版が売れ始めました。14時ぐらいまでは結構忙しい感じでした。16時台はほとんど来ないか、立ち読みしても買わない人が多い感じでした。 一方、紙の本がないと分かるとあきらめる人もいたので若干機会損失でした。

最終的に紙の本70冊、電子版単体79冊が売れました。ここまで売れるとは想定外で、100冊印刷しておけばよかったです。

17時になってイベント終了、撤収となりました。

内側からの気づき

同人誌即売会に一般参加者としては何度も参加したことがあるのですが、サークル参加は初めてでした。出展側になって初めて気づいたこともいろいろあります。

  • 見本を数分かけてじっくり読む人がいる。
  • 目次が結構見られる。
  • カップル等で連れ立って行動している人が結構いる。一人が立ち読みするともう一人はやることがなくなるので、およそ複数人行動は不便なイベントだと思う。
  • モノクロ表紙は少ない。見劣りした。デザイン自由度が上がるほか、印刷だと結構コストが上がるので悩みどころ。
  • (最後の1時間の)16時台はほとんど売れない。このジャンルに興味があって来ている人はもういないのだろう。

売れ行き記録

売れた冊数の時系列推移を記録していたので発表します。売上表を不定期に撮影しておいて、タイムスタンプから照合しました。

f:id:select766:20181015094310p:plain

紙の本は一気に完売、電子版は終了近くまで単調に売れるという結果でした。

さいごに

サークル参加すると決めてから、初めての作業がたくさんあり苦労しました。 それでも満足いく本を作ることができ、しかも完売させることができました。大満足です。

今回の本の話題はここで終わりではなく、継続して研究するつもりでいます。 一方で追加で分かったことを本にした時には読者に前提知識が必要となるため、展示即売には向かない懸念もあります。 まずは研究を進めて、イベントの際にはまた考えることにします。

主催の皆様、イベントに来場された方々、どうもありがとうございました。良いイベントになりました。

技術書典5 振り返り(準備編)

2018年10月8日に、池袋サンシャインシティにて同人誌即売会「技術書典5」が開催されました。 この記事は、私が同人誌即売会に人生初のサークル参加を行った当イベントの記録を残すものです。

なお、頒布物はBOOTHにてオンライン販売しておりますので、今からでもご覧いただけます。 https://select766.booth.pm/items/1023247

出展経緯

机の向こう側に行きたい

私が初めて同人誌即売会に参加(購入側として)したのは、2010年夏のコミックマーケットコミケ)だったはずです。 最初に買ったのが何だったかは残念ながら忘れてしまったのですが、回数を重ねるたびに、ただ見て回るだけでなく「机の向こう側に行きたい」という気持ちが強くなりました。

技術書典

コミケはあまりに広大でどこから手を付けていいやらわからないという感じだったのですが、近年になって技術書典が開かれ、専門のIT技術をベースに何か出展できる可能性を感じました。 石橋を叩いて渡るタイプの人間なので、いきなり本を書いて印刷して売る、という作業を全部やるのは不安でした。そのためまずはコンテンツ自体を書く能力があるのかということを自分自身で試しました。 その結果が2017年12月にネットで公開した記事になります。

select766.hatenablog.com

無名の人がマニアックなPDFを公開しただけなので評判などが聞こえてきたわけではないものの、自分自身では一応行けるという感触を得ました。 第4回(2018年4月)の開催案内が出た際にはぜひ出展したいという気持ちが固まっていたのですが、本業の都合でそれどころじゃなさそうだったため見送ってしまいました。 6月20日に第5回の開催案内が出て、今度こそ挑戦してみることにしました。

出ると決めた後

同人誌を書くということそのものが目標だったので、ネタ自体にこだわりはありませんでした。 しかし、コンピュータ将棋の同人誌といえば山岡さんや澤田さんといった強力な人たちがいるので、あえてそこに割り込むよりは別の話題にすることにしました。 そういうわけで、少なくとも日本語圏では見かけない、ポケモン人工知能で解くネタを発表することにしました。 7月19日が応募締め切りだったので、それまでに発表内容の骨子ができれば、と思っていたのですが、技術的に難航して達成できませんでした。 今回の話題は既存のソフトウェア等の使い方の解説ではなく、学術論文に近い新たな技術の開発になるので、技術部分で失敗すると語るべきものがない事態に陥ります。 それでも「出したいから出す、締め切り駆動だ。」という精神で応募してしまいました。 人生いつ死ぬかわからないし、自分自身はいくら気を付けていても親族の介護などどうしようもない事態が起きて好きなことができなくなるかもしれません。 最悪のケースでも前年末の記事を改訂して印刷すれば体裁は整えられるので、応募しない理由がありませんでした。 一方で即売会に出展するというのは初めてのことがたくさんあるので、本のコンテンツのクオリティは頑張るものの、他の部分は保守的に進めました。

研究開発

今回の本の話題は、ポケモンバトルの戦略を人工知能技術で開発するというものでした。 まずはゲームのシミュレータ開発から始めました。データ構造の検討、技の仕様の情報収集など結構骨の折れる作業でした。 イベント当日に複数の訪問者から、「シミュレータを作るのが大変だったでしょう」と言われましたがまさにその通りです。

シミュレータができた後、そこに乗っけるAI部分の開発を行いました。 提案手法がそもそも良い成績を出せるのかというところが非常に不安でした。

執筆

8月23日、一部の実験が完了し、最低限語るべき内容ができました。本の執筆にとりかかりました。 取り急ぎ、カタログに印刷されるサークルカットの納入が8月末までということだったので、Windowsのペイントで作りました。 目を引くイラストを載せている人も多いのですが、私にはそういうスキルは欠けています。 文字情報だけにしても、何が書かれた本なのか最低限わかるように注意して作りました。 PowerPointなどで作れるともう少し楽だったのですが、ピクセル数でサイズが決まっているためうまく作れませんでした。 ラスタ画像の作り方に関するスキルをいずれは磨いていきたいところです。

9月3日、本文執筆開始。マークアップ言語として、技術系同人誌に向いていると思われるRe:VIEWシステムを使うことにしました。 ひたすら文字を書いて、9月19日に9割方執筆が完了しました。 一度書いただけだと論理関係が破綻していたり誤字脱字の嵐だったりするので、紙に印刷してファミレスで赤ペンを走らせました。 漢字変換のミスは商業出版でもよく見かけるので、この作業は非常に重要です。

その後図版などを作成し、最終調整をしました。図の位置がずれる問題が生じていたのですが、Re:VIEWコンパイル組版)環境としてセットアップが楽なdockerを使用していたため、ちょっと面倒な事態に陥りました。 コンパイルするたびにソフトウェアパッケージをインターネットからダウンロードするようになっており、レイアウトのパラメータを1個変えて試行錯誤するたびに1分程度かかったり、パッケージのサーバが一時的に落ちて作業不能になったりしました。環境は要改善です。 最終的にできたPDFをコンビニのプリンターで印刷し、数式や図が消えたり文字化けしたりしないことを確認しました。 最後に表紙をWordで作りました。例によってかっこいいイラストは描けないので主張点の箇条書きという形になりました。 イベント当日に周りを見るとカラー表紙が多く、見劣りした感じは否めません。

入稿

印刷所への入稿は私にとって未知の領域です。印刷所の選定ですが、印刷物の直接搬入ができる「ねこのしっぽ」か「日光企画」から選ぶことにしました。 Webサイトが初心者にわかりやすかったねこのしっぽを選びました。 印刷数を検討しました。9月20日時点で、技術書典サイトの被チェック数が25でした。twitterで過去のイベントでの売れ行きについて調べたところ、50冊は売れそうという感触でした。 印刷方式としてオンデマンドとオフセットがありましたが、オフセットが金銭的にお得なのは300部以上なので、オンデマンドにしました。 「オフセ本」という響きには憧れるのでいつかオフセット印刷にも挑戦したいですが、ジャンルを変えないと無理でしょう。 印刷部数の入力で、最初に予定した50部に見本用などの予備を足した60部にしようと思ったのですが、50・80・100という数でしか受け付けられなかったので80部にしました。 なお、当日はそのうち70部頒布しました。 見積もりの段階でページ数が確定している必要があるようでした。漫画本だと早い段階で決定する項目かと思いますが、TeXベースの技術書だと容易に変動するので実質的に原稿が完成した後でないと見積もりができません。 表紙・本文ともモノクロ印刷にしました。

表紙をどうやって入稿すればいいのか最初わかりませんでした。背表紙に印刷したり、紙の端まで色を塗るような場合には表紙・裏表紙がつながった大きな画像として作る必要があるみたいです。 今回はそこまで手が出せませんでしたが、単純に表紙・裏表紙に相当するB5サイズのPDFをWordで作り、hyosi_omote.pdf, hyosi_ura.pdfという名前で入稿すれば期待通りの印刷になりました。 本文はRe:VIEWで作成したPDFをそのまま入稿しました。印刷方式によりページ数が2の倍数または4の倍数である必要がありますが、今回は偶然はじめから条件を満たしていました。 紙質などの選択もできたのですが、よくわからないので標準的なものを選択しました。9月22日に入稿完了、10%割引期間内でした。

準備

本の入稿が終わり、それ以外のイベント準備を始めました。 本自体は当日会場へ直接搬入なので、中身の確認はできません。印刷が想定通りできていることを祈るだけです。 頒布の計画として、紙の本が売り切れておしまいになるのはもったいないので、電子版を用意することにしました。 一般参加側として、何度となく完売・救済策なしという自体に遭遇して残念な思いをしたのでそういうことが起きてほしくないと思いました。 技術的には、単にPDFをダウンロードするためのURLやパスワードを書いた紙を頒布することで実現します。 配る紙は名刺状のカードにしているサークルが多いようです。 ねこのしっぽの名刺印刷を使おうかと思ったのですが、PhotoShop形式での入稿が必要のようで、PhotoShopは持ってないし使ったこともないので諦めました。 ビジネス向けの名刺作成サービスのカスタマイズの範疇で実現するという手もあると思います。 今回は紙の本を頒布することをメインとして、ほかは最低限で済ませることにしました。 そのため、しおり状の普通の紙に必要な情報を書いたものを用意しました。 コンビニで印刷し、カッターで裁断しました。この方式なら最悪当日に不足しても生産可能です。

頒布価格等の設定ですが、読者の立場に立って考えました。 46ページ、モノクロの紙の本であれば500円が妥当なところです。 電子版を付けるのは特にコストがかからないので、利便性のために紙の本を買ったら電子版も入手可能という形にしました。 一方で紙の本は持ち帰るのが面倒なので電子版だけのほうがいい、という人もいると思いました。 そうしたときに、電子版単体が紙の本と同じ価格だと、損をした気分になるかと思い電子版は少し安くすることにしました。 特に紙の本が完売した後で選択肢がない場合は顕著です。 1冊当たりの印刷コストが250円程度であることを考慮し、紙の本+電子版は500円、電子版単体は300円という設定にしました。

頒布物以外に、100均でテーブルクロスや本立てなどのグッズを購入しました。また、twitterで数ページ分の画像と共に告知を行いました。 この辺の準備に関する情報は技術同人誌を書こう! アウトプットのススメを参考にしました。

当日編(執筆中)に続きます。

技術書典5 ヤマブキ計算所(え32) おしながき

2018年10月8日、池袋サンシャインシティにて開催される技術書典5での頒布物をお知らせします。

配置は「え32」です。サークル配置図はこちら

頒布物は技術書1点です。タイトルは「PokèAI ~人工知能の考えた最強のポケモン対戦戦略~(1)」となります。 表紙込み46ページで、紙の冊子は500円、電子版ダウンロードコードのみは300円で頒布します。 紙媒体は途中で売り切れる場合がありますのでご了承ください。 支払いは現金・かんたん後払いに対応しています。 また、会場に来られない方のため500円でオンライン販売(電子版のみ)を予定しております。

ポケモンバトルの戦略を人工知能に考えさせたらどんな戦略が生み出されるか?」というテーマで、 用いる技術の概要、ポケモンに応用する手法の提案および実装の解説、実験結果として生み出された戦略の考察を掲載しています。

今回は第1巻ということで、ゲームのルールは初代(赤・緑バージョン)に準拠し、ポケモン交換なしの1対1のバトルでの戦略を模索します。

表紙・目次および、各章から1ページずつこちらに載せておきます。

f:id:select766:20180929211409p:plainf:id:select766:20180929211355p:plainf:id:select766:20180929211400p:plain f:id:select766:20180929211835p:plainf:id:select766:20180929211842p:plainf:id:select766:20180929211847p:plain

皆様のお越しをお待ちしております。