2011年7月21日木曜日

ランダムの妥当性とは?~その2

前回はランダムを発生させるところまでやったのだが、発生するランダムな値が本当にランダムかわからないという問題があることがわかったので、今回は少し検証してみようと思う。

まずは、発生している値の平均値が10であるか検証。
これ基本です。


def getAverage = {map ->
    def size = map.size
    def sum = withPool {
        map.parallel
        .map{it.value}
        .reduce{s, i ->
            s + i
        }
    }
    sum / size as double
}

def testMap = [[key:1,value:11], [key:2,value:9], [key:3,value:10]]
assert 10.0 == getAverage(testMap)


下のassertは平均値を算出したメソッドが妥当かテストしているだけです。
では、おもむろにテストしてみる。


10.times{
    assert 10.0 == getAerage(getRandom(20 * 10))
}


とりあえず、大丈夫なようだ。

つぎは分散を算出する。これも基本です。


def getSigmaSquare = { map, avg ->
    def size = (map.size <= 2)? 2 : map.size
    def sum = withPool{
        map.parallel
        .map{
            def dif = it.value - avg as double
            dif * dif
        }
        .reduce{s, i ->
            s + i
        }
    }
    sum / (size - 1) as double
}

def testMap = [[key:1,value:11], [key:2,value:9], [key:3,value:10]]
assert 1.0 == getSigmaSquare(testMap, 10)


下のassertは分散を算出したメソッドが妥当かテストしているだけです。
では、おもむろに実行してみる。

10.times{num ->
    def rand = getRandom(10 * 20)
    def avg = getAverage(rand)
    def sigs = getSigmaSquare(rand, avg)
    def sigm = Math.sqrt(sigs)
    println sprintf("num : %2d / avg : %5.1f / sigs : %5.1f / sigm : %4.1f", num, avg, sigs, sigm)
}


実行結果


num :  0 / avg :  10.0 / sigs :  11.8 / sigm :  3.4
num :  1 / avg :  10.0 / sigs :  10.5 / sigm :  3.2
num :  2 / avg :  10.0 / sigs :  16.1 / sigm :  4.0
num :  3 / avg :  10.0 / sigs :  10.6 / sigm :  3.3
num :  4 / avg :  10.0 / sigs :  10.3 / sigm :  3.2
num :  5 / avg :  10.0 / sigs :  11.6 / sigm :  3.4
num :  6 / avg :  10.0 / sigs :   9.9 / sigm :  3.1
num :  7 / avg :  10.0 / sigs :  10.8 / sigm :  3.3
num :  8 / avg :  10.0 / sigs :   8.5 / sigm :  2.9
num :  9 / avg :  10.0 / sigs :   5.3 / sigm :  2.3


発生した値はだいたい、10 ± 3.5 程度にあるということになるのだろうか。

0 件のコメント:

コメントを投稿