スクリーンショット_0030-05-10_23

統計と確率とプログラム

こんちは。一応、大学の専攻は統計ですとなのれるくらいにはなってきたおかざわです。今回は統計をプログラムしてみました。

本読む時間が取れてない...ぐやじいです。

グラフとかプロットしたものは、Noteの仕様上見れないので、以下リンクをご確認ください。

同じデータに対して、全く同じ結果を出力するプログラムを決定的(deterministic)

確率を用いたプログラム

import random
def rollDie():
    return random.choice([1, 2, 3, 4, 5, 6])
​
def rollN(n):
    result = ''
    for i in range(n):
        result = result + str(rollDie())
    print(result)

rollN(6)
135661
推測統計
原理は、ランダムサンプルの性質が母集団全体の性質を代表する傾向にあるということ

import random
def flip(numFlips):
    heads = 0
    for i in range(numFlips):
        if random.choice(('H', 'T')) == 'H':
            heads += 1
        return heads/numFlips
    
def flipSim(numFlipsPerTrial, numTrials):
    fracHeads = []
    for i in range(numTrials):
        fracHeads.append(flip(numFlipsPerTrial))
    mean = sum(fracHeads)/len(fracHeads)
    return mean

print('mean=', flipSim(10, 1))
mean= 0.1

print('mean=', flipSim(10, 100))
mean= 0.050999999999999976

print('mean=', flipSim(100, 100000))
mean= 0.005004899999996898
ここで根拠にしているのが大数の法則(ベルヌーイの定理) 独立思考において、各思考で特定の事象が起こる確率をpとする(例:1回のコイン投げで主は0.5)

大数の法則とは、実際に思考を繰り返す中でその事象が起こる割合とpの差が試行の回数が無限に近づくとき0に収束するというもの。

注意したいのは、大数の法則が意味するところは、多くの人が考えているように結果に隔たりが出たときに、その隔たりが将来的にぎゃくの隔たりにより相殺されるということではない。 大数の法則の誤った解釈あh賭博者の誤謬(Gambler's fallacy)として知られる

賭博者の誤謬は、平均への回帰と誤解されることが多い。 平均への回帰(regression to the mean)とは、曲間な確率自称が怒ったあとであhより極端でない自称が起こりやすい。

import matplotlib.pyplot as plt
def regressToMean(numFlips, numTrials):
    fracHeads = []
    for t in range(numTrials):
        fracHeads.append(flip(numFlips))
    extremes, nextTrials = [], []
    for i in range(len(fracHeads) - 1):
        if fracHeads[i] < 0.33 or fracheads[i] > 0.66:
            extremes.append(fracHeads[i])
            nextTrials.append(fracHeads[i + 1])
            
    plt.plot(range(len(extremes)), extremes, 'ko', label = 'Next Trial')
    plt.plot(range(len(nextTrials)), nextTrials, 'k^', label = 'Next Trial')
    plt.axhline(0.5)
    plt.ylim(0,1)
    plt.xlim(-1, len(extremes) + 1)
    plt.xlabel('Extreme Example and Next Trial')
    plt.ylabel('Fraction Heads')
    plt.title('Regression to the Mean')
    plt.legend(loc = 'best')
    plt.show()

regressToMean(15, 40)

def flipPlot(minExp, maxExp):
    ratios, diffs, xAxis = [], [], []
    for exp in range(minExp, maxExp + 1):
        xAxis.append(2**exp)
    for numFlips in xAxis:
        numHeads = 0
        for n in range(numFlips):
            if random.choice(('H', 'T')) == 'H':
                numHeads += 1
        numTails = numFlips - numHeads
        try:
            ratios.append(numHeads/numTails)
            diffs.append(abs(numHeads - numTails))
        except ZeroDivisionError:
            continue
    pylab.title('Difference Between Heads and Tails')
    pylab.xlabel('Number of Flips')
    pylab.ylabel('Abs(#heads - #Tails)')
    pylab.plot(xAxis, diffs, 'k')
    pylab.figure()
    pylab.title('Heads/Tails Ratios')
    pylab.xlabel('Number of Flips')
    pylab.ylabel('#Heads/#Tails')
    pylab.plot(xAxis, ratios, 'k')
    
random.seed(0)
flipPlot(4, 20)
plt.show()

variance(X) =
∑xeX(x−μ)2|X|
∑xeX(x−μ)2|X|
variance(X) =
∑xeX(x−μ)2|X|
∑xeX(x−μ)2|X|
標準偏差

def variance(X):
    mean = sum(x)/len(X)
    tot = 0.0
    for x in X:
        tot += (x - mean)**2
    return tot/len(X)
​
def stdDev(X):
    return variance(X)**0.5

def makePlot(xVals, yVals, title, xLabel, yLabel, style, logX = False, logY = False):
    pylab.figure()
    pylab.title(title)
    pylab.xlabel(xLabel)
    pylab.ylabel(yLabel)
    pylab.plot(xVals, yVals, style)
    if logX:
        pylab.semilogx()
    if logY:
        pylab.semilogy()
        
def runTrial(numFlops):
    numHeads = 0
    for n in range(numFlips):
        if random.choice(('H', 'T')) == 'H':
            numHeads += 1
    numTails = numFlops - numHeads
    return(numHeads, numHeads)
​
def flipPlot1(minExp, maxExp, numTrials):
    ratiosMeans, diffsMeans, ratiosSDs, diffsSDs = [], [], [], []
    xAxis = []
    for exp in range(minExp, maxExp + 1):
        xAxis.append(2**exp)
    for numFlips in xAxis:
        ratios, diffs = [], []
        for t in range(numTrials):
            numHeads, numTails = runTrial(numFlips)
            ratios.append(numHeads/numTails)
            diffsMeans.append(sum(diffs)/numTrails)
            ratiosSDs.append(stdDev(ratio))
            diffsSDs.append(stdDev(diffs))
    numTrialsString = '('+ str(numTrails) + 'Trials)'
    title = 'Mean Heads/Tails Ratios' + numTrialsString
    makePlot(xAxis, ratiosMeans, title, 'number of flips', 'Mean Heads/Tails Ratios', 'ko', logX = True)
    title = 'SD Heads_Tails Ratios' + numTrialsString
    plt.show()
変動係数(confficient of variation)
標準偏差を平均で割ったものである。平均が異なるデータを比較するとき、変動係数は標準偏差より役に立つ

def CV(X):
    mean = sum(X)/len(X)
    try:
        return stdDev(x)/mean
    except ZeroDivisionError:
        return flaot('nan')
​
分布

import numpy as np
import matplotlib.pyplot as plt
vals = []
for i in range(1000):
    num1 = random.choice(range(0, 101))
    num2 = random.choice(range(0, 101))
    vals.append(num1 + num2)
plt.hist(vals, bins = 16)
plt.xlabel('Number of Occurences')
plt.show()

確率分布
ヒストグラムは度数分布(Frequency distribution)を表示する手法の1つだ。

確率分布(Probability distribution)により、確率変数の値がある範囲に含まれる確率を計算できるので相対頻度がワkラウ

確率分布は確率変数が離散であるか、連続であるかによって、離散確率分布と連続確率分布の2つに分けられる

離散確率変数(Discrete probability variable)はたとえばサイコロ投げのように有限集合上に値を取る。

連続確率変数(Continuous random variable)はたとえば時速0キロからその車の最高時速のように、任意の2つの次数にはさまれた区間にある無限この実数をとる

連続確率分布はややこしく、確率変数は無限この値を取りうるので、特定の値をとる確率は通常0となる。例えば、ある車が時速130.0042キロで走る確率は0だ。

このバイ、確率密度関数(Probability density function(PDF))を用いて説明する。PDFは確率変数が2つの値の間に含まれる確率を表す。確率変数の最小値と最大値の間で定義される関数が表す曲線である。

# 正規分布
#random.gauss(mu, sigma)

import scipy.integrate as integrate
print(scipy.integrate.quad(abs, 0, 5)[0])
12.5

# 経験則
def gaussian(x, sigma):
    factor1 = (1.0/sigma*((2*pylab.pi)**0.5))
    factor2 = pylab.e**-(((x-mu)**2)/(2*sigma**2))
    return factor1*factor2
​
def checkEmpirical(numTrials):
    for i in range(numTrials):
        mu = random.randint(-10, 10)
        sigma = random.randint(1, 10)
        print('For mu =',mu, 'and sigma =', sigma)
        for numStd in (1, 2, 3):
            area = scipy.integrate.quad(gaussian, mu-numStd*sigma, mu+numStd*sigma, (mu, sigma))[0]
            print('Fraction within ', numStd, 'std=', round(area, 4))
        checkEmpirical(3)

# # エラーバー
# pylab.errorbar(xVals, means, yerr = 1.96*pylab.array(sds))
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-77-ebbc0b6da7e2> in <module>()
      1 # エラーバー
----> 2 pylab.errorbar(x, means, yerr = 1.96*pylab.array(sds))

NameError: name 'x' is not defined

指数分布と幾何学分布

def clear(n, p, steps):
    numRemaining = [n]
    for t in range(steps):
        numRemaining.append(n*((1-p)**t))
    pylab.plot(numRemaining)
    pylab.xlabel('Time')
    pylab.ylabel('Mokecules Remaining')
    pylab.title('Clearance of Drug')

plt.show(clear(1000, 0.01, 1000))

# 幾何分布
def successfulStarts(successProb, numTrials):
    triesBeforeSuccess = []
    for t in range(numTrials):
        consecFailures = 0
        while random.random() > successProb:
            consecFailures += 1
        triesBeforeSuccess.append(consecFailures)
    return triesBeforeSuccess
​
probOfSuccess = 0.5
numTrials = 5000
distribution = successfulStarts(probOfSuccess, numTrials)
pylab.hist(distribution, bins = 14)
pylab.xlabel('Tries Before Success')
pylab.ylabel('Number of Occurrences Out of' + str(numTrials))
pylab.title('Probability of Starting Each Try =' + str(probOfSuccess))
plt.show()

ハッシュの衝突

def collisionProb(n, k):
    prob = 1.0
    for i in range(1, k):
        prob = prob * ((n - i)/n)
    return 1 - prob

def simInsertions(numIndices, numInsertions):
    choices = range(numIndices)
    used = []
    for i in range(numInsertions):
        hashVal = random.choice(choices)
        if hashVal in used:
            return 1
        else:
            used.append(hashVal)
    return 0def findProb(numIndices, numInsertions, numTrials):
    collisions = 0
    for t in range(numTrials):
        collisions += simInsertions(numIndices, numInsertions)
        return collisions/numTrials

collisionProb(1000, 50)
0.7122686568799875

findProb(1000, 50, 10000)
0.0001

collisionProb(1000, 200)
0.9999999994781328

findProb(1000, 200, 10000)
0.0001

​
​

いいなと思ったら応援しよう!