確率統計¶
確率統計機能のモジュールである sympy.stats を調べてみよう。
Note
本文中のすべての IPython セッション中のサンプルコードで、以下のインポートおよび出力書式設定が済んでいるものとする。
from sympy.stats import *
init_printing(pretty_print=False)
確率変数¶
from sympy.stats import * を実行すると、クラスというよりは関数がインポートされる。確率変数生成関数と統計的関数の二種類に分類して見ていくと効率が良さそうだ。ここに記すいくつかの関数については、演習のコーナーにて実際に動作を確かめる。
確率変数生成関数¶
まずは確率変数生成関数を表に示す。
関数 |
確率空間 |
説明 |
|---|---|---|
Bernoulli |
SingleFinitePSpace |
|
Binomial |
SingleFinitePSpace |
|
Coin |
SingleFinitePSpace |
コイントスをモデル化した確率変数。 |
Die |
SingleFinitePSpace |
偏りのないサイコロをモデル化した確率変数。 |
DiscreteUniform |
SingleFinitePSpace |
|
FiniteRV |
SingleFinitePSpace |
有限確率変数を密度を表現する |
Hypergeometric |
SingleFinitePSpace |
|
Rademacher |
SingleFinitePSpace |
|
Arcsin |
SingleContinuousPSpace |
|
Benini |
SingleContinuousPSpace |
|
Beta |
SingleContinuousPSpace |
|
BetaPrime |
SingleContinuousPSpace |
|
Cauchy |
SingleContinuousPSpace |
|
Chi |
SingleContinuousPSpace |
|
ChiNoncentral |
SingleContinuousPSpace |
|
ChiSquared |
SingleContinuousPSpace |
|
Dagum |
SingleContinuousPSpace |
|
Erlang |
SingleContinuousPSpace |
|
Exponential |
SingleContinuousPSpace |
|
FDistribution |
SingleContinuousPSpace |
|
FisherZ |
SingleContinuousPSpace |
|
Frechet |
SingleContinuousPSpace |
|
Gamma |
SingleContinuousPSpace |
|
GammaInverse |
SingleContinuousPSpace |
|
Kumaraswamy |
SingleContinuousPSpace |
|
Laplace |
SingleContinuousPSpace |
|
Logistic |
SingleContinuousPSpace |
|
LogNormal |
SingleContinuousPSpace |
|
Maxwell |
SingleContinuousPSpace |
|
Nakagami |
SingleContinuousPSpace |
|
Normal |
SingleContinuousPSpace |
|
Pareto |
SingleContinuousPSpace |
|
QuadraticU |
SingleContinuousPSpace |
|
RaisedCosine |
SingleContinuousPSpace |
|
Rayleigh |
SingleContinuousPSpace |
|
StudentT |
SingleContinuousPSpace |
|
Triangular |
SingleContinuousPSpace |
|
Uniform |
SingleContinuousPSpace |
|
UniformSum |
SingleContinuousPSpace |
|
VonMises |
SingleContinuousPSpace |
|
Weibull |
SingleContinuousPSpace |
|
WignerSemicircle |
SingleContinuousPSpace |
|
Geometric |
SingleDiscretePSpace |
|
Poisson |
SingleDiscretePSpace |
確率空間クラスについては後述する。
統計的関数¶
すべての確率変数生成関数の戻り値は RandomSymbol というクラスのオブジェクトである。ここでは X, Y などを RandomSymbol オブジェクトまたはそれから構成される式とする。このオブジェクトの利用法は、そのメソッドを呼び出すというよりは、次に示す各種確率統計的関数の引数として用いる。
関数 |
説明 |
別名 |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
クラス¶
ユーザーがクラスを直にアクセスすることはどうやらまれなようだが、理解を深めるには、これらの表に出てこないクラス群を調べるのもよいだろう。
確率分布モデルクラス¶
確率分布モデルを表現するクラスのごく簡単なクラス図を次に記す。これらの確率分布クラスは、前述の各種同じ名前からなる確率変数生成関数によってオブジェクト化され、それから、分布に対応する確率空間クラスのオブジェクトを生成する。
ContinuousDistribution
SingleContinuousDistribution
ArcsinDistribution
BeniniDistribution
BetaDistribution
BetaPrimeDistribution
CauchyDistribution
ChiDistribution
ChiNoncentralDistribution
ChiSquaredDistribution
ContinuousDistributionHandmade
DagumDistribution
ExponentialDistribution
FDistributionDistribution
FisherZDistribution
FrechetDistribution
GammaDistribution
GammaInverseDistribution
KumaraswamyDistribution
LaplaceDistribution
LogisticDistribution
LogNormalDistribution
MaxwellDistribution
NakagamiDistribution
NormalDistribution
ParetoDistribution
QuadraticUDistribution
RaisedCosineDistribution
RayleighDistribution
StudentTDistribution
TriangularDistribution
UniformDistribution
UniformSumDistribution
VonMisesDistribution
WeibullDistribution
WignerSemicircleDistribution
SingleDiscreteDistribution
PoissonDistribution
GeometricDistribution
SingleFiniteDistribution
BernoulliDistribution
BinomialDistribution
DieDistribution
DiscreteUniformDistribution
FiniteDistributionHandmade
HypergeometricDistribution
RademacherDistribution
ここにあるほとんどすべてのクラスは、次のクラスを共通基底クラスとしている。
BasicSymPy の主要クラスに共通する基底クラスであり、いまさら説明はしない。
NamedArgsMixin当モジュールで定義された補助クラスであり、オブジェクトに対して演算子
[]で属性値にアクセスすることができるようにするものだ。
大量にある分布モデルクラスは、それらの基底クラスによって次の三系統に分類できることがわかる:
SingleContinuousDistribution連続分布。
定義域は
Interval(-oo, oo)すなわち実数である。派生クラスでは事情が異なるかもしれない。オブジェクトに対する丸括弧呼び出しでメソッド
pdfを呼び出す。メソッドとして
pdf,cdf,sample,expectationがある。デバッグ用途だと思うが静的メソッド
checkがある。
SingleDiscreteDistribution離散分布。
定義域は
S.Integersすなわち整数である。あとは
SingleContinuousDistributionで記した各項目と同じ。
SingleFiniteDistribution有限分布。これだけ毛色が異なる。
オブジェクトに対する丸括弧呼び出しでメソッド
pdfを呼び出す。メソッドとして
pdfがある。辞書オブジェクトのような振る舞いをするようだ。
定義域クラス¶
ここではある確率密度関数の定義域を domain と呼ぶものと解釈する。
クラス RandomDomain を基底クラスとする継承関係を図に示したいが、複雑なダイヤモンド型継承を多用しているので、アスキーアートでは厳しいものがある。素朴な表でごまかす。
クラス |
直接基底クラス |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- クラス
RandomDomain ある確率密度関数の定義域を表現するクラスのための基底クラス。
プロパティー
self.symbolsプロパティー
self.set演算子
inをオブジェクトに対して適用できることになっている。メソッド
integrate(expr)を各派生クラスが実装する。この戻り値が何らかの確率密度関数を示すようになる。
確率空間クラス¶
クラス PSpace を基底クラスとする継承関係を図に示したいが、こちらも少々のダイヤモンド継承関係があるので表でごまかす。
クラス |
直接基底クラス |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- クラス
PSpace 確率空間を表現するクラス。
プロパティーとして
domain,density,values,symbolsがある。メソッドとして
compute_density,integrate,probability,sample,whereがある。
ユーザーはこれらには直接触れずに、先述の統計的関数によって間接的に利用する。
クラス RandomSymbol¶
クラス RandomSymbol は確率空間クラスのメソッド values 系の戻り値の型として利用されている。このオブジェクトを関数 P, E の引数として指定する。
このオブジェクトはユーザーが直接生成するというよりは、前述の確率変数生成関数の戻り値として得られる。
演習¶
次の文書からいくつか例題を拝借した:
確率変数生成関数に name を指定するのが存外面倒なので、以下、特に問題がなければ X で通す。
関数 probability で確率を評価する¶
短い別名 P が付いているので、対話型コードでは主にこちらを採用する。
In [1]: X = Normal('X', mean=0, std=1)
In [2]: simplify(P(X < 3))
Out[2]: erf(3*sqrt(2)/2)/2 + 1/2
[1]
Normalの各引数はデフォルト引数として定義して欲しいという気がする。あと引数が「期待値・分散」ではなく「期待値・標準偏差」であることに注意を要する。
In [1]: X = Poisson('X', symbols('m', positive=True))
In [2]: P(X <= 3)
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
<ipython-input-44-251995f355a4> in <module>()
----> 1 P(X <= 3)
D:\home\yojyo\devel\sympy\sympy\stats\rv.py in probability(condition, given_condition, numsamples, evaluate, **kwargs)
619
620 # Otherwise pass work off to the ProbabilitySpace
--> 621 result = pspace(condition).probability(condition, **kwargs)
622 if evaluate and hasattr(result, 'doit'):
623 return result.doit()
D:\home\yojyo\devel\sympy\sympy\stats\rv.py in probability(self, condition)
161
162 def probability(self, condition):
--> 163 raise NotImplementedError()
164
165 def integrate(self, expr):
NotImplementedError:
[1][2] どうも
Poissonは動作しにくい傾向がある。
In [1]: X = Normal('X', 0, 1)
In [2]: P((X - 1)**2 <= 3*X)
Out[2]: -erf(sqrt(2)*(-sqrt(21)/2 + 5/2)/2)/2 + erf(sqrt(2)*(sqrt(21)/2 + 5/2)/2)/2
In [1]: X = Die('X', 3)
In [2]: P(Or(X**2 > 3, abs(X) < 1))
Out[2]: 2/3
次の例は数値計算になってしまっているが、真の値は \(\frac{1}{e}\) だ。
In [1]: X = Laplace('X', 0, 1/2)
In [2]: P(X**2 > 1, X > Rational(1, 2))
Out[2]: 0.367879441171442
関数 expectation で期待値または平均値を評価する¶
正式な関数名は expectation であるが、略名 E が与えられている。SymPy では自然対数の底にもこの名前が付いているので注意。冒頭に述べたインポート文でこれが上書きされる。
In [1]: X = Normal('X', 0, 1)
In [2]: E(2*X + 3)
Out[2]: 3
In [1]: X = Poisson('X', symbols('m', positive=True))
In [2]: E(X**2 + 7*X + 8)
Out[2]: m*(m + 1) + 7*m + 8
In [1]: X = DiscreteUniform('X', symbols('a, b, c, d'))
In [2]: E(X)
Out[2]: a/4 + b/4 + c/4 + d/4
確率密度関数を評価する¶
確率密度関数は下のように pspace オブジェクトを経由しないとアクセスできないのか。
In [1]: X = Normal('X', 0, 1)
In [2]: X.pspace.pdf
Out[2]: sqrt(2)*exp(-X**2/2)/(2*sqrt(pi))
余裕があればプロットする。
累積分布関数を評価する¶
累積分布関数を得るにはフリー関数 cdf を用いる。
In [1]: cdf(Weibull('X', 2, 5), 4)
Out[1]: Lambda(_z, Piecewise((1 - exp(-_z**5/32), _z >= 0), (0, True)))
In [2]: cdf(Normal('X', 0, 1))(0.2).evalf()
Out[2]: 0.579259709439103
標本点を抽出する¶
分布から標本点を抽出すると、毎回結果が異なる。
In [1]: X = Normal('X', 0, 1)
In [2]: [i for i in sample_iter(X, numsamples=10)]
Out[2]: [-1.04146627871984, 0.363794003745111, -1.13748652670554, 1.048567943992, -0.479638133723148, 1.29475387658596, -1.15722394615277, 1.57550171698866, -0.545623114068184, -1.52095054404692]
関数 moment でモーメントを評価する¶
ここでは二次のモーメントを計算する。
In [1]: moment(DiscreteUniform('X', symbols('x1:4')), 2)
Out[1]: x1**2/3 + x2**2/3 + x3**2/3
In [2]: simplify(moment(Normal('X', symbols('mu'), symbols('sigma', positive=True)), 2))
Out[2]: mu**2 + sigma**2
分散と標準偏差を評価する¶
関数 variance は E((X - E(X))**2) と同じ値を計算する。
関数 standard_deviation は単に variance の正の平方根を返す。短い別名
std が宣言されている。
数値計算の例を示す。
In [1]: X = DiscreteUniform('X', [1.21, 3.4, 2, 4.66, 1.5, 5.61, 7.22])
In [2]: variance(X)
Out[2]: 4.42390612244898
In [3]: std(X)
Out[3]: 2.10330837550013
関数 covariance で共分散を評価する¶
あまりやることがない。
In [1]: X, Y = DiscreteUniform('X', symbols('a b')), DiscreteUniform('Y', symbols('x y'))
In [2]: covariance(X, Y)
Out[2]: (-a/2 + b/2)*(-x/2 + y/2)/4 + (-a/2 + b/2)*(x/2 - y/2)/4 + (a/2 - b/2)*(-x/2 + y/2)/4 + (a/2 - b/2)*(x/2 - y/2)/4
関数 correlation で相関を評価する¶
これもあまりやることがない。
In [1]: X, Y = DiscreteUniform('X', symbols('a b')), DiscreteUniform('Y', symbols('x y'))
In [2]: correlation(X, Y)
Out[2]: ((-a/2 + b/2)*(-x/2 + y/2)/4 + (-a/2 + b/2)*(x/2 - y/2)/4 + (a/2 - b/2)*(-x/2 + y/2)/4 + (a/2 - b/2)*(x/2 - y/2)/4)/(sqrt((-a/2 + b/2)**2/2 + (a/2 - b/2)**2/2)*sqrt((-x/2 + y/2)**2/2 + (x/2 - y/2)**2/2))
関数 cmoment で中央モーメントを評価する¶
色々な確率分布の二次の中央モーメントを評価しよう。
In [1]: cmoment(DiscreteUniform('X', symbols('x1:4')), 2)
Out[1]: (-x1/3 - x2/3 + 2*x3/3)**2/3 + (-x1/3 + 2*x2/3 - x3/3)**2/3 + (2*x1/3- x2/3 - x3/3)**2/3
In [2]: simplify(cmoment(Gamma('X', symbols('alpha', positive=True), symbols('beta', positive=True)), 2))
Out[2]: alpha*beta**2
In [3]: cmoment(Normal('X', symbols('mu'), symbols('sigma', positive=True)), 2)
Out[3]: sigma**2
関数 smoment で標準化モーメントを評価する¶
関数 smoment は n 次の中央モーメントを標準偏差の n 乗で割った値を評価する。歪度や尖度を評価する関数の実装にはこれを利用する。
この関数を直接利用する例は見当たらない。
関数 skewness で歪度を評価する¶
関数 skewness は三次の smoment を評価する。この指標は例えば戻り値の符号でグラフの裾野が広いほうがわかる。
In [1]: skewness(DiscreteUniform('X', symbols('a b c')))
Out[1]: ((-a/3 - b/3 + 2*c/3)**3/3 + (-a/3 + 2*b/3 - c/3)**3/3 + (2*a/3 - b/3- c/3)**3/3)/((-a/3 - b/3 + 2*c/3)**2/3 + (-a/3 + 2*b/3 - c/3)**2/3 + (2*a/3 - b/3 - c/3)**2/3)**(3/2)
In [2]: skewness(ChiSquared('X', 10))
Out[2]: 2*sqrt(5)/5
In [3]: skewness(Exponential('X', symbols('mu', positive=True)))
Out[3]: 2
In [4]: skewness(Normal('X', 0, 1))
Out[4]: 0