日本※で一番※ポーカーが上手い※のは誰か計算してみた（TrueSkill）～理論編～

# 記事へのリンク
1. 理論編（←本記事）
2. [実装編](https://qiita.com/syym88/items/be75914c742dcdca33ae)
3. [評価編](https://qiita.com/syym88/items/2359a250d4145da31f33)

# 本記事におけるお断り
本記事は筆者が自学自習のためにデータ取得から計算までを行ったものです。特定の団体や個人から許可許諾はとっていないため、もし内容に問題があるとお考えの場合にはご連絡いただければ幸いです。
また、タイトルにもある通り、単純に強い、上手いを判断するのが困難であるポーカーにおけるスキルの『推定』がやりたかったことです。
本記事を通じて少しでもポーカーに興味を持ってアミューズメントやオンラインでポーカーを始めたいと思う人が増えれば何よりです。

#なんでこんなことしようと思ったのか
pandasを勉強する機会があり、継続学習のために興味がある領域でお勉強＆アウトプットしたかったらです。
あと、ポーカーというかなり運の要素が入るゲームにおいて実力を正確に計算する事が出来るのかという点は昔から興味がありました。
昔社交ダンスの試合結果100万件をELOレーティングで計算したりと、何かと順位を元にした実力推定は興味があったのです。

#背景の説明
### ポーカー
現在世界ではテキサスホールデムという種目が最も主流でありプレイ人口も多いです。
本記事では今後ポーカー＝ノーリミットテキサスホールデムという前提で記述します。
5枚引いて、好きな枚数チェンジして、勝負！ではなく、裏向きの自分しか使えない2枚＋全員が使える5枚のうち好きな5枚を使って勝負！
という感じのルールです。詳細は以下URLよりぜひご覧ください！
https://ja.wikipedia.org/wiki/%E3%83%86%E3%82%AD%E3%82%B5%E3%82%B9%E3%83%BB%E3%83%9B%E3%83%BC%E3%83%AB%E3%83%87%E3%83%A0
### 日本のポーカー事情
**ご存知のとおり日本において賭博は違法です。**そんな中どのように日本のプレイヤーはポーカーを楽しんでいるかというと、大きく3つに分けられます。

1. アミューズメント施設で遊ぶ
2. オンラインゲームで遊ぶ
3. 海外のカジノに行って遊ぶ

それぞれざっくり言うと以下のような特徴があります。

| 名称 | 特徴 | 代表的な場所 | データの有無 |
|:-:|:-:|:-:|:-:|
| 1.アミューズメント施設  | ゲームセンターと同じような仮想チップを使ってゲームを楽しむ。換金は出来ないが大きな大会ではスポンサーから商品が出る事もある。  | アキバギルド、東京dePoker、カジノクエスト、パラハetc  | 全順位データ公開  |
| 2.オンラインゲーム  | モバイルやPCから遊べる。一部サイトではお金を賭けて遊べてしまったりするが、合法か違法かはグレーなので自己責任。  | PokerStars、Zynga、PokerPoker  | 一部開発者のみに限定公開  |
|3. 海外のカジノ  | カジノが有ってポーカーが遊べる国に行けば合法的にお金を賭けてポーカーが出来る。全てのカジノでポーカーが出来るわけではない（むしろ全体でみると少ない？）ので注意。 | ラスベガス、マカオ、韓国、マニラ、バルセロナ、モナコetc  | 入賞者のみ公開 |

今回、**「1.アミューズメント施設で遊ぶ」**という試合結果をもとにして計算を行いました。
なぜかと言うと、データが公開された状態で十分な量存在していることと、結果に対する肌感があるため自分でも計算結果を一定評価出来るからです。

#計算手法
今回は「総当たり式ELOレーティング」と「TrueSkill」の2つの方法で計算を行いました

## 総当たり式ELOレーティング
ELOレーティングはチェスの実力評価のために開発された（恐らく）最古の実力を定量化するためのアルゴリズムです。
https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%AD%E3%83%AC%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0

ただし、**1vs1の試合結果しか計算出来ない**ため、将棋・チェス・ボクシング・剣道etcの競技では単純に適用可能なのですが、
ポーカー、ゴルフ、競馬、社交ダンスetcの様な**複数のプレイヤーが同時に競技を行い順位がつく**競技に適用するためには工夫が必要です。

その工夫が「総当たり式」であり、端的に言えば1試合の参加者を全2人の組み合わせに分解してそれぞれで勝敗を計算してしまおう、という考えです。
例：ABCDEの5人が100m走を走り、CABEDの順位だったとする
- AvsB：Aの勝ち、Bの負け
- AvsC：Cの勝ち、Aの負け
- （略）
- DvsE：Eの勝ち、Dの負け

といった感じでそれぞれの結果を計算し最終的に合算します
計算式については上記Wikipediaリンクに詳細がありますが、抜粋するとこんな感じです。
### 勝率の計算
Aさん（レーティング1700）とBさん（レーティング1500）が対戦する場合を考えます
まずAさんとBさんの対戦した時の勝率を計算します
Aさんから見た勝率は以下の式より約76%と計算できます

```math
W_{ab} = \frac{1}{10^{(R_B-R_A)/400}+1} 
```
### レーティング変動を計算
上記で算出した勝率をもとに、試合後のレーティング（R'）がどの程度変動するか計算します。

```math
R'_A = R_A + K \times W_{BA}
```
```math
R'_B = R_B - K \times W_{BA}
```
###定数パラメーター
ELOレーティングの計算において、3つのパラメータを決定する必要があります。

- 初期レーティング：多くの場合1500と設定されていますが好きな数字でOK
- 初期レーティングに対する勝敗比：多くの場合400と置かれています。初期レーティングに対して乖離しすぎていないければOKの認識
- 変動率（K）：1回の試合結果でどの程度レーティングを変動させるのかのパラメータです。32が一般的と言われていますが、競技の特性によってここの値を適正に変える必要があります。試合頻度が高い、1対1ではなく順位式の競技、運の要素が大きい競技、などの場合にはKの値を小さく設定するのが良いです

###計算してみた結果から言うと・・・
とてもではないが使いものになりませんでした。。。
理由はいくつか考えられますが、ポーカーのようなどんな実力者でもかなりの頻度で初心者に負けうる様な競技の場合
レーティングが1回の勝敗に大きく左右されすぎるため、人数が多い試合においては1回の負け/勝ちであまりに大きな変動となってしまう事がわかりました。
例として100人程度の規模である程度の実力者が下位20%くらいの順位だと一発で-2000くらいの変動を食らっていました。
では大きく変動しすぎないようにKを下げれば良いかと言われると、今度は少人数の試合で全く動かなくなるためこれもよろしくない。
では人数にKを反比例させる、等考えられますがそうすると1試合の価値が変わる事になりこれもどうかと。。。
![syelo.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303315/8bd254f0-f521-a7ac-ba93-d82cb7837643.png)
ちなみにこちらは私の約80回あまりの試合ごとの変動をプロットしたものです。
見ての通り、概ね1500より高い位置に居ますが、最後の方で大きくマイナスを食らった結果、
残念ながら1500未満の結果となりました。（悲しい）

# TrueSkill
TrueSkillはマイクロソフト謹製のスキル推定アルゴリズムです。
XBoxのゲーム内マッチングで利用する目的で開発され、**マイクロソフトが特許を持っており商用利用には許諾が必要です**
日本語記事だとQiita内では以下2つが大変参考になりました。
数学が苦にならない人は1つめの記事を苦手な方は2番目の記事を読むと大変わかりやすいと思います

[誰でも分かるTrueSkill](https://qiita.com/kkjk21/items/aac8e26a2e68c4659c62)
[TrueSkill「まだ Elo レーティングで消耗してるの?」](https://qiita.com/BlueRayi/items/f994bb67e0dc5723c2a1)

以下2つめの記事より引用した特徴です
>- 収束が早い。 レーティングに初めて参加するプレイヤーの実力を推定するのに何度も何度も不適当なマッチングで対戦する必要がない。
>- 複数人による対戦に対応している。 勝ちか負けかのみならず順位を定めるようなゲームやチーム戦1のゲームにも使用できる。
>- ゲームへの参加に重み付けができる。 例えばチームメンバーのひとりが回線トラブルにより途中でゲームから抜けた場合でも適用できる。
>- ~~Microsoft の息がかかっている。 特許申請と商標登録がなされており、なんとなく手が出しづらい。 あと一部の狂信的 OSS 主義者が憤死する。~~

###TrueSkillの概要
※ここから先の説明は数学素人の筆者が理解しやすさ重視で記載しているので誤っている箇所があるかもしれません
ELOレーティングは1回スキルの計算が終わると、「今回は良い結果だったからあなたのレーティングは1500⇒1600にアップしました」という様に具体的なスキルの数値を示します。
これを複数回繰り返すことで本来のスキルに収束してゆく、という考え方です。
一方TrueSkillは1回スキルの計算が終わると、「今回は良い結果だったからあなたのレーティングは、試合前は1200～1800の間のどこかで中央の1500である可能性が最も高かったけど、計算後は1400～1700の間のどこかで中央値の1550である可能性が最も高くなるとわかりました」という様にスキルを確率分布で示します。

数学に詳しい方はお気づきかと思いますが、これは正規分布で表現されているという事です。
TrueSkillで計算が進むとは、正規分布の中央の値（μ）が左右に動きその人のスキルに近づいてゆき、更に正規分布の範囲が狭まり（σ）その人のスキルの幅が確定してゆく。
といった過程を経て最終的なスキルが算出されます
![sy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303315/eee93aeb-cc1f-36c9-7386-0c139bbd7434.png)

こちらもELOレーティングと同様に私自身の計算過程である約80試合の計算過程をプロットしたものです。
低くて横に広いグラフが最初の状態、高くて横に狭いグラフが最終的な状態です。
見れば分かる通り私はグラフの中央が右方向に動いているため、一応計算上は強い人、ということになります。
（一応計算上は、です。。。）

# 次の記事
次の記事では、どのように上記理論を実装したのか簡単に記載したいと思います。
そして最後に計算結果から分析結果をまとめて記載したいと思います。
ちなみに実名（ポーカーの場合はポーカーネームというニックネーム）を公表すると色々問題になりそうなのですが、
どうしようかは現在まだ決めていません。。。

もし現時点で自分の値を知りたい方はTwitterで本人までDMいただければこっそり教えます！