Rustで実装された、7並べ(Sevens)の強化学習プロジェクトです。ゲーム環境からニューラルネットワークの学習まで、外部ランタイム(Python等)に依存せず、100%Rustで完結しています。 useでエラーが出たら使用したいファイルを適切に指定してください。(ところどころ共有している部分があるので、useと使用したいメソッドを書き換えれば動きます)
・Pure Rust Implementation:ゲームロジックから学習ループまで全てRustで記述。
・High Performance: Google ColabのCPU環境において、RandomAgent対戦で 10000 game/secを超えるスループットを確認。(dqn_v1.4.0では100,000戦の学習が2時間で完了)
・Lightweight ML: Hugging Face製の機械学習フレームワークcandleを採用している。
・基本ルール:7を中心として隣接する数字を場に出し、先に手札を0にした順番で順位が決定する
・パス回数:3回まで可能。4回目のパスは出せるカードが無い時にのみ可能。4回目のパスをしたプレイヤーは即座にドボン。
・ドボン者のカードは公開情報となるが、場に繋がる数字までしか場には出されない(ドボン者が出てもゲーム続行)
・ドボンした順番で最下位から埋まる
・配られたカードの中にダイヤの7があった人が一番手となり、自分->下家->対面->上家->自分となる。また、全てのスートの7は開始時に場に自動で出される。
・全員があがるかドボンになった時点でゲーム終了
・Language: Rust
・ML Framework: candle "0.10.2" (by Hugging Face)
・RL Algorithm: Dueling DDQN / n-step RL
・lr-schedulerはCosineAnnealingWarmRestartsを実装しています
・unwrap()とexpect()について:コード内ではunwrap()とexpect()が使用されていますが、そこでエラーが出た場合は学習継続困難なため止めたほうが良く、複雑なエラーハンドリングを避けています。しかし、20万戦ほど回しても一度もexpect()を呼び出されていないため、安全は確認しております。
・ProcessorでRawStateをNNに入れる値に変換し、一括でTensorにしています。そのため、特徴量を変えたい場合は、Processorのwrite_buf()をいじってください。
図:random3体に対する勝率(dqn_v1.2.1)
ランダム相手ではあるが、出せるカードがあるなら自滅できないルールのため、それなりの勝率です。
正常に学習ができていることが確認できます
図:maskの扱いを変更しqnetにbuffer_layerを入れた後(dqn_v1.3.0)
v1.3.0では、平均着順は変わらないものの、2着率が上昇。次はラス率を下げつつトップを取る方法を工夫して教えたい
図:per実装後の勝率上昇
PERにより3着率が下がり、1着と2着が増えているのがわかる。PERの実装に成功した
図:モデルの軽量化と更新頻度の見直し後
学習を高速化したいため、residualblockを減らし、更新頻度も減らしたら結果的に強くなった。
おそらく、以前は表現力がありすぎたため過学習を起こしていたと思われる
図:トップ率が突き抜けた
バッチサイズを64->256にしたらめちゃくちゃ強くなりました
・DRNを完成させる




