- はじめに
ポケモンの攻撃種族値、特攻種族値、素早さ種族値などをたくさん並べると、中央付近に多く集まり、極端に低い値や極端に高い値は少なくなります。
たとえば、攻撃種族値で考えると、
攻撃 40 くらいのポケモン → 少ない
攻撃 80〜110 くらいのポケモン → 多い
攻撃 150 以上のポケモン → 少ない
という形になりやすいです。
この形は、正規分布に似ています。
ただし、ここで大事なのは次です。
攻撃種族値そのものが、必ず正規分布になるわけではない。
数学的に正しく言うなら、
攻撃種族値や素早さ種族値が、
多くの小さな要因の和として決まっているとみなせるなら、
中心極限定理により、分布は正規分布に近づく。
ということです。
つまり、種族値を
種族値 = 基本値 + 要因1 + 要因2 + 要因3 + ... + 要因n
のように考えると、中心極限定理が使えます。
- まず「種族値」を確率変数として見る
ポケモンの攻撃種族値を A とします。
たとえば、
ピカチュウの攻撃種族値
カイリューの攻撃種族値
ガブリアスの攻撃種族値
ミミッキュの攻撃種族値
ドラパルトの攻撃種族値
を、1匹ずつ取り出して並べるとします。
このとき、ランダムに1匹ポケモンを選んだときの攻撃種族値を
A
という確率変数として見ます。
同じように、素早さ種族値を
S
とします。
ここで確率変数とは、
選ぶポケモンによって値が変わる数
です。
攻撃種族値 A は、ポケモンを選ぶたびに値が変わります。
あるポケモンでは A = 55
別のポケモンでは A = 100
別のポケモンでは A = 135
というように変わるので、確率変数として扱えます。
- しかし種族値そのものは「1個の乱数」ではない
ポケモンのダメージ乱数なら、
0.85, 0.86, 0.87, ..., 1.00
のように、乱数倍率が直接あります。
一方、種族値はゲーム内で毎回ランダムに変わる値ではありません。
ガブリアスの攻撃種族値は毎回同じです。
したがって、攻撃種族値を中心極限定理で説明するには、少し見方を変える必要があります。
攻撃種族値を、次のような複数要因の和として考えます。
攻撃種族値
= 基本戦闘力
- 物理アタッカー補正
- 進化段階補正
- タイプ補正
- 体格補正
- 伝説・準伝説補正
- バランス調整補正
- その他の細かい補正
数式で書くと、
A = μ + X1 + X2 + X3 + ... + Xn
です。
ここで、
A : 攻撃種族値
μ : 全体の基準値
X1 : 進化段階による補正
X2 : 物理アタッカーとしての補正
X3 : 体格やモチーフによる補正
X4 : タイプ傾向による補正
...
Xn : 細かい調整項
と考えます。
このように、たくさんの小さな要因の合計として種族値を見ると、中心極限定理が登場します。
- 種族値モデルの例
攻撃種族値を、かなり単純化して次のように置きます。
A = 80 + X1 + X2 + X3 + X4 + X5 + X6
それぞれの意味を、ポケモン風に考えます。
X1 : 進化段階による補正
X2 : 物理アタッカー向け補正
X3 : 体格・筋力イメージ補正
X4 : タイプによる傾向補正
X5 : ゲームバランス用の調整
X6 : 個別キャラ性による調整
たとえば、進化後のポケモンは攻撃が高くなりやすいです。
X1 = +20
物理アタッカーとして作られていれば、さらに上がります。
X2 = +25
一方で、素早さや耐久に強みを振っているポケモンなら、攻撃は少し抑えられるかもしれません。
X5 = -10
このような補正が足し合わされて、最終的な攻撃種族値が決まると考えます。
重要なのは、
種族値は、1つの理由だけで決まるのではなく、
いくつもの小さな要因の合計として見られる
という点です。
この「和」という形が、中心極限定理とつながります。
- 中心極限定理とは何か
中心極限定理は、次のような定理です。
X1, X2, ..., Xn が独立で同じ分布に従う確率変数であり、
平均が μ、分散が σ^2 であるとする。
このとき、
Sn = X1 + X2 + ... + Xn
を標準化した
Zn = (Sn - nμ) / (σ√n)
は、n が大きくなると標準正規分布 N(0,1) に近づく。
数式だけ抜き出すと、
Zn = (X1 + X2 + ... + Xn - nμ) / (σ√n)
Zn → N(0,1)
です。
意味は次の通りです。
たくさんの小さなランダム要因を足すと、
合計値の分布は正規分布に近づく。
ここで重要なのは、元の Xi が正規分布である必要はないことです。
たとえば、各 Xi が次のような単純な分布でも構いません。
-5, 0, +5 のどれかを取る
または、
0, 1 のどちらかを取る
このような単純な乱数でも、たくさん足し合わせると、合計は正規分布に近づきます。
- なぜ「足す」と正規分布に近づくのか
直感的には、組み合わせの数が理由です。
たとえば、簡単な例として、次のような補正を考えます。
Xi = -1 または +1
これを10個足します。
S10 = X1 + X2 + ... + X10
このとき、最大値は
+10
です。
これは、10個すべてが +1 のときだけです。
+1 +1 +1 +1 +1 +1 +1 +1 +1 +1 = +10
このパターンは1通りしかありません。
一方、合計が0になるには、
+1 が5回
-1 が5回
になればよいです。
この並び方はたくさんあります。
...
つまり、
極端な値になる組み合わせは少ない
中央付近になる組み合わせは多い
ということです。
そのため、合計の分布は中央が高く、両端が低い山型になります。
この山型が、正規分布です。
- 攻撃種族値に当てはめる
攻撃種族値 A を、次のような要因の和とします。
A = μA + X1 + X2 + ... + Xn
ここで、
μA : 攻撃種族値の基準値
Xi : 攻撃に関する小さな補正
です。
たとえば、
X1 : 進化段階
X2 : 物理型か特殊型か
X3 : タイプ傾向
X4 : 体格
X5 : 素早さとの配分
X6 : 耐久との配分
X7 : 専用技や特性との兼ね合い
X8 : 世代ごとの調整
のように考えます。
完全に独立ではありませんが、「多くの要因が足される」という構造を見ると、中心極限定理の考え方を使えます。
その結果、攻撃種族値の分布は、
A ≒ N(平均, 分散)
のように近似できます。
つまり、
攻撃種族値は、平均付近に多く集まり、
極端に低い攻撃や極端に高い攻撃は少なくなる
という形になります。
- 素早さ種族値に当てはめる
素早さ種族値 S も同じように考えます。
S = μS + Y1 + Y2 + ... + Yn
ここで、
μS : 素早さ種族値の基準値
Yi : 素早さに関する小さな補正
です。
素早さの場合は、攻撃とは違う要因が関係します。
Y1 : 小型・軽量イメージ
Y2 : 高速アタッカー向け補正
Y3 : 進化段階
Y4 : タイプ傾向
Y5 : 耐久との配分
Y6 : 火力との配分
Y7 : 先制技や特性との兼ね合い
Y8 : ゲームバランス用の調整
このような補正が足されると、素早さ種族値も中央付近に集まりやすくなります。
極端に遅いポケモン → 少ない
中速ポケモン → 多い
極端に速いポケモン → 少ない
したがって、素早さ種族値も正規分布に似た形になりやすいです。
- ただし、ポケモン種族値は完全な正規分布ではない
ここは重要です。
ポケモンの種族値分布は、完全な正規分布にはなりません。
理由はいくつかあります。
第一に、種族値にはゲーム上の上限と下限があります。
攻撃種族値がマイナスになることはない
素早さ種族値が無限に大きくなることもない
正規分布は理論上、
-∞ から +∞
まで値を取ります。
しかし、種族値は有限の範囲に収まります。
第二に、ポケモンには役割があります。
高速アタッカー
鈍足高火力
耐久型
特殊アタッカー
物理受け
サポート型
このようなグループがあるため、全体の分布は1つのきれいな正規分布ではなく、複数の山が混ざった形になることがあります。
たとえば素早さなら、
鈍足帯
中速帯
高速帯
のように、いくつかの集まりが出ることがあります。
第三に、進化前ポケモンと最終進化ポケモンを一緒に集計すると、分布が歪みます。
進化前ポケモン → 種族値が低め
最終進化ポケモン → 種族値が高め
伝説ポケモン → 種族値が高め
これらを全部混ぜると、単純な正規分布からずれます。
したがって、正しくは次のように言うべきです。
攻撃や素早さの種族値は、
複数の要因の和として見られるため、
中心極限定理により正規分布に近い形を取りやすい。
ただし、役割・進化段階・上限下限・ゲーム調整の影響により、
完全な正規分布にはならない。
- 中心極限定理の証明に入る
ここから、中心極限定理を詳しく証明します。
まず、扱いやすくするために、次の形で考えます。
X1, X2, ..., Xn は独立で同じ分布に従う確率変数
E[Xi] = μ
Var(Xi) = σ^2
このとき、
Sn = X1 + X2 + ... + Xn
とします。
中心極限定理で示したいのは、
Zn = (Sn - nμ) / (σ√n)
が、n を大きくすると標準正規分布に近づくことです。
Zn → N(0,1)
- まず平均0、分散1に変換する
証明を簡単にするために、各 Xi を標準化します。
Yi = (Xi - μ) / σ
このとき、Yi の平均は0です。
E[Yi]
= E[(Xi - μ) / σ]
= (E[Xi] - μ) / σ
= (μ - μ) / σ
= 0
次に分散を計算します。
Var(Yi)
= Var((Xi - μ) / σ)
= (1 / σ^2) Var(Xi)
= (1 / σ^2) σ^2
= 1
したがって、
E[Yi] = 0
Var(Yi) = 1
です。
また、
Zn = (Sn - nμ) / (σ√n)
でした。
Sn = X1 + X2 + ... + Xn なので、
Zn
= (X1 + X2 + ... + Xn - nμ) / (σ√n)
分子を分けると、
Zn
= ((X1 - μ) + (X2 - μ) + ... + (Xn - μ)) / (σ√n)
さらに、
Yi = (Xi - μ) / σ
なので、
Zn = (Y1 + Y2 + ... + Yn) / √n
になります。
つまり、証明すべきことは次です。
E[Yi] = 0
Var(Yi) = 1
Zn = (Y1 + Y2 + ... + Yn) / √n
この Zn が N(0,1) に近づくことを示す。
- 特性関数を使う
中心極限定理の標準的な証明では、特性関数を使います。
確率変数 Y の特性関数を
φ(t) = E[e^(itY)]
と定義します。
ここで、
i : 虚数単位
t : 実数
E : 期待値
です。
特性関数を使う理由は、和が扱いやすくなるからです。
独立な確率変数 Y1, Y2 について、
φ(Y1 + Y2)(t) = φY1(t) φY2(t)
が成り立ちます。
つまり、
確率変数の和 → 特性関数では積
になります。
これは、信号処理でいうと、
畳み込みがフーリエ変換で積になる
という話に近いです。
- Y の特性関数をテイラー展開する
Y は平均0、分散1の確率変数とします。
E[Y] = 0
Var(Y) = 1
分散の定義より、
Var(Y) = E[Y^2] - {E[Y]}^2
です。
E[Y] = 0 なので、
Var(Y) = E[Y^2]
したがって、
E[Y^2] = 1
です。
特性関数は、
φ(t) = E[e^(itY)]
です。
ここで、指数関数をテイラー展開します。
e^x = 1 + x + x^2/2! + x^3/3! + ...
x = itY とすると、
e^(itY)
= 1 + itY + (itY)^2/2! + (itY)^3/3! + ...
ここで期待値を取ると、
φ(t)
= E[e^(itY)]
= E[1 + itY + (itY)^2/2! + ...]
期待値の線形性より、
φ(t)
= 1 + itE[Y] + (i^2 t^2 / 2)E[Y^2] + ...
ここで、
E[Y] = 0
E[Y^2] = 1
i^2 = -1
なので、
φ(t)
= 1 - t^2/2 + 小さい項
より正確には、
φ(t) = 1 - t^2/2 + o(t^2)
と書きます。
ここで、
o(t^2)
は、t → 0 のときに t^2 より小さくなる項を表します。
つまり、
φ(t) = 1 - t^2/2 + o(t^2)
が、証明の重要な準備です。
- Zn の特性関数を求める
次に、
Zn = (Y1 + Y2 + ... + Yn) / √n
の特性関数を求めます。
Zn の特性関数を
φZn(t) = E[e^(itZn)]
とします。
代入すると、
φZn(t)
= E[e^(it(Y1 + Y2 + ... + Yn)/√n)]
指数法則より、
e^(it(Y1 + Y2 + ... + Yn)/√n)
= e^(itY1/√n) e^(itY2/√n) ... e^(itYn/√n)
したがって、
φZn(t)
= E[e^(itY1/√n) e^(itY2/√n) ... e^(itYn/√n)]
ここで Y1, Y2, ..., Yn は独立なので、期待値は積に分解できます。
φZn(t)
= E[e^(itY1/√n)]
E[e^(itY2/√n)]
...
E[e^(itYn/√n)]
すべて同じ分布に従うので、
E[e^(itY1/√n)]
= E[e^(itY2/√n)]
= ...
= E[e^(itYn/√n)]
= φ(t/√n)
です。
したがって、
φZn(t) = {φ(t/√n)}^n
になります。
- φ(t/√n) を展開する
先ほど、
φ(t) = 1 - t^2/2 + o(t^2)
でした。
ここで、t の代わりに t/√n を入れます。
φ(t/√n)
= 1 - (t/√n)^2 / 2 + o((t/√n)^2)
整理すると、
φ(t/√n)
= 1 - t^2/(2n) + o(1/n)
です。
したがって、
φZn(t)
= {φ(t/√n)}^n
= {1 - t^2/(2n) + o(1/n)}^n
となります。
- 極限を取る
ここで、指数関数の基本極限を使います。
lim[n→∞] (1 + a/n)^n = e^a
今回の式は、
{1 - t^2/(2n) + o(1/n)}^n
です。
これは、
a = -t^2/2
に対応しています。
したがって、
lim[n→∞] {1 - t^2/(2n) + o(1/n)}^n
= e^(-t^2/2)
つまり、
lim[n→∞] φZn(t) = e^(-t^2/2)
です。
- e^(-t^2/2) は標準正規分布の特性関数
標準正規分布 N(0,1) の特性関数は、
e^(-t^2/2)
です。
いま、
φZn(t) → e^(-t^2/2)
を示しました。
つまり、Zn の特性関数は、標準正規分布の特性関数に近づきます。
特性関数は分布を一意に決めるので、
Zn → N(0,1)
です。
したがって、
Zn = (X1 + X2 + ... + Xn - nμ) / (σ√n)
は、標準正規分布に近づきます。
これで中心極限定理の基本形が示されました。
- 種族値モデルに戻す
攻撃種族値を、
A = μA + X1 + X2 + ... + Xn
とします。
各補正 Xi が、
平均 0
分散 σi^2
を持つ小さなランダム要因だと考えます。
説明を簡単にするため、同じ分布に従う場合を考えると、
E[Xi] = 0
Var(Xi) = σ^2
です。
このとき、
A - μA = X1 + X2 + ... + Xn
です。
中心極限定理より、
(A - μA) / (σ√n) ≒ N(0,1)
です。
したがって、
A ≒ N(μA, nσ^2)
となります。
つまり、攻撃種族値は、
平均 μA
分散 nσ^2
の正規分布に近い形で近似できます。
- 同じことを素早さ種族値でも書く
素早さ種族値を、
S = μS + Y1 + Y2 + ... + Yn
とします。
ここで、
μS : 素早さの基準値
Yi : 素早さに関する補正
です。
各 Yi が小さなランダム要因で、平均0、分散 τ^2 を持つなら、
E[Yi] = 0
Var(Yi) = τ^2
です。
このとき、
S - μS = Y1 + Y2 + ... + Yn
なので、中心極限定理より、
(S - μS) / (τ√n) ≒ N(0,1)
です。
したがって、
S ≒ N(μS, nτ^2)
となります。
つまり、素早さ種族値も、たくさんの小さな要因の和として見られるなら、正規分布に近い形になります。
- 攻撃と素早さを2次元で見る
攻撃種族値と素早さ種族値を同時に見ると、1匹のポケモンを2次元ベクトルで表せます。
v = (攻撃, 素早さ)
たとえば、
ガブリアス v = (130, 102)
ドラパルト v = (120, 142)
カビゴン v = (110, 30)
のように見られます。
このとき、攻撃と素早さをそれぞれランダム変数として、
A : 攻撃種族値
S : 素早さ種族値
とします。
要因の和で書くなら、
A = μA + X1 + X2 + ... + Xn
S = μS + Y1 + Y2 + ... + Yn
です。
この2つをまとめると、
V = (A, S)
です。
中心極限定理の多変量版を使うと、
V は2次元正規分布に近づく
と考えられます。
2次元正規分布では、データは楕円形に広がります。
攻撃が高く、素早さも高いポケモン
攻撃が高いが、素早さは低いポケモン
攻撃は低いが、素早さは高いポケモン
攻撃も素早さも中程度のポケモン
という分布を、平均ベクトルと共分散で表せます。
- 共分散の意味
攻撃と素早さの関係を見るには、共分散を使います。
Cov(A, S) = E[(A - μA)(S - μS)]
です。
意味は次の通りです。
Cov(A, S) > 0
攻撃が高いポケモンほど、素早さも高くなりやすい
Cov(A, S) < 0
攻撃が高いポケモンほど、素早さは低くなりやすい
Cov(A, S) ≒ 0
攻撃と素早さに強い直線的関係が少ない
ポケモンでは、攻撃と素早さが両方高い高速物理アタッカーもいます。
一方で、攻撃が高く素早さが低い重戦車型もいます。
そのため、全体では単純な正の相関や負の相関だけでは説明しきれません。
ただし、グループごとに分けると見え方が変わります。
高速アタッカーだけで見る
鈍足高火力だけで見る
最終進化だけで見る
伝説ポケモンを除いて見る
このように分けると、分布の形がより正規分布に近づくことがあります。
- なぜ全ポケモンを一気に見ると歪むのか
全ポケモンの攻撃種族値を一気に並べると、中心極限定理だけでは説明しにくい形になることがあります。
理由は、異なるグループを混ぜているからです。
たとえば、次のようなグループがあります。
進化前ポケモン
中間進化ポケモン
最終進化ポケモン
伝説ポケモン
幻のポケモン
メガシンカ
特殊アタッカー
物理アタッカー
耐久型
サポート型
これらは、それぞれ平均が違います。
進化前ポケモンの平均攻撃種族値と、伝説ポケモンの平均攻撃種族値は同じではありません。
そのため、全体分布は、
低めの山
中くらいの山
高めの山
が混ざった形になります。
これは、混合分布です。
全体分布
= グループ1の分布
- グループ2の分布
- グループ3の分布
- ...
です。
そのため、全体では完全な正規分布ではなく、
複数の正規分布が混ざった形
として見る方が自然です。
- この記事での主張を正確に言い直す
最初の文を、数学的に正しく言い直すと次のようになります。
ポケモンの攻撃や素早さの種族値を並べると、
平均付近に多く集まり、極端な値が少ない形になりやすい。
これは、種族値が多くの小さな要因の和として決まっていると見なせる場合、
中心極限定理によって正規分布に近づくと説明できる。
ただし、実際の種族値はゲーム上の調整、進化段階、役割、上限下限の影響を受けるため、
完全な正規分布ではなく、正規分布に似た形、または複数の正規分布が混ざった形になる。
この表現なら、ポケモンのデータ分析としても、数学記事としても自然です。
- 数式でまとめる
攻撃種族値を、
A = μA + X1 + X2 + ... + Xn
とする。
各補正が平均0、分散 σ^2 を持つとすると、
E[Xi] = 0
Var(Xi) = σ^2
である。
このとき、
E[A] = μA
また、
Var(A) = Var(X1 + X2 + ... + Xn)
独立なら、
Var(A) = Var(X1) + Var(X2) + ... + Var(Xn)
= nσ^2
中心極限定理より、
(A - μA) / (σ√n) ≒ N(0,1)
したがって、
A ≒ N(μA, nσ^2)
である。
同様に、素早さ種族値を、
S = μS + Y1 + Y2 + ... + Yn
とすると、
S ≒ N(μS, nτ^2)
である。
- Pythonで確認するなら
実際に考え方を確認するなら、次のようなシミュレーションができます。
import numpy as np
import matplotlib.pyplot as plt
ポケモンの攻撃種族値を「複数補正の和」として作る簡易モデル
np.random.seed(0)
num_pokemon = 10000
num_factors = 20
各補正を -5, 0, +5 からランダムに選ぶ
factors = np.random.choice([-5, 0, 5], size=(num_pokemon, num_factors))
基準攻撃種族値
base = 80
攻撃種族値モデル
attack = base + factors.sum(axis=1)
plt.hist(attack, bins=30, density=True)
plt.xlabel("Attack base stat")
plt.ylabel("Density")
plt.title("Attack base stat as sum of many small factors")
plt.show()
このコードでは、攻撃種族値を
80 + 20個の小さな補正の和
として作っています。
各補正は、
-5, 0, +5
のどれかです。
1つ1つの補正は正規分布ではありません。
しかし、20個足すと、分布は山型になります。
これが中心極限定理の見え方です。
- 実データ分析にするなら
実際のポケモン種族値データを使うなら、次の流れになります。
- ポケモンの種族値データを用意する
- 攻撃種族値だけを取り出す
- ヒストグラムを描く
- 平均と標準偏差を計算する
- 同じ平均・標準偏差の正規分布を重ねる
- どれくらい正規分布に近いかを見る
Pythonなら、流れは次のようになります。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
例: pokemon_stats.csv に Attack, Speed 列があるとする
df = pd.read_csv("pokemon_stats.csv")
attack = df["Attack"].dropna()
mu = attack.mean()
sigma = attack.std()
x = np.linspace(attack.min(), attack.max(), 300)
y = norm.pdf(x, mu, sigma)
plt.hist(attack, bins=30, density=True, alpha=0.5)
plt.plot(x, y)
plt.xlabel("Attack base stat")
plt.ylabel("Density")
plt.title("Attack base stat and normal approximation")
plt.show()
print("mean =", mu)
print("std =", sigma)
この分析をすると、
攻撃種族値は正規分布に近いのか
右に歪んでいるのか
複数の山があるのか
伝説ポケモンを除くと形が変わるのか
最終進化だけにすると形が変わるのか
を確認できます。
- 中心極限定理で説明できる部分と、できない部分
中心極限定理で説明しやすい部分は次です。
平均付近に多く集まる
極端な値が少なくなる
小さな要因の和から山型が生まれる
多くの補正を足すと正規分布に近づく
一方で、中心極限定理だけでは説明しにくい部分もあります。
伝説ポケモンが高種族値に偏る
進化前ポケモンが低種族値に偏る
高速アタッカーと鈍足高火力で分布が分かれる
ゲームバランス上、特定の値に集まりやすい
素早さ種族値は対戦上の意味が強く、意図的な調整を受けやすい
そのため、実データ分析では、
中心極限定理による正規近似
+
グループ別分析
+
混合分布
で考えるとよいです。
- まとめ
ポケモンの攻撃や素早さの種族値を並べると、正規分布に似た山型になることがあります。
その理由は、種族値を多くの小さな要因の和として見られるからです。
攻撃種族値
= 基準値
- 進化段階補正
- 物理型補正
- タイプ補正
- 体格補正
- ゲームバランス調整
- 個別キャラ性
- ...
このように、たくさんの補正を足す形になっているなら、中心極限定理により、合計値は正規分布に近づきます。
中心極限定理の要点は、
X1, X2, ..., Xn を足した Sn について、
Zn = (Sn - nμ) / (σ√n)
と標準化すると、
Zn → N(0,1)
です。
特性関数を使うと、
φ(t) = 1 - t^2/2 + o(t^2)
から、
φZn(t) = {φ(t/√n)}^n
→ e^(-t^2/2)
となり、これは標準正規分布の特性関数です。
したがって、
Zn → N(0,1)
が示されます。
ポケモン種族値に戻すと、
攻撃種族値 A ≒ N(μA, nσ^2)
素早さ種族値 S ≒ N(μS, nτ^2)
のように近似できます。
ただし、実際の種族値は完全な正規分布ではありません。
進化段階、役割、伝説ポケモン、ゲームバランス、上限下限などの影響があるため、現実のデータでは歪みや複数の山が出ます。
最終的には、次の理解が一番正確です。
ポケモンの攻撃や素早さの種族値は、
多くの小さな要因の和として見ると、
中心極限定理によって正規分布に近づくと説明できる。
しかし実データでは、
役割や進化段階ごとの違いが混ざるため、
完全な正規分布ではなく、
正規分布に似た形、または複数の正規分布の混合として見るのが自然である。