5

SciPy の関数のドキュメントを理解するのに苦労しています。scipy.stats.hypergeom私のプログラムでは、さまざまなカードのデッキを検討し、さまざまなドローの確率を見つけようとします。クラスはhypergeomまさにこれを持っているようですが、そのドキュメントは、私が持っていない一連の用語知識を前提としています. グーグルで検索すると、ウィキペディアと Wolfram MathWorld にたどり着きます。どちらも、この種のことについて質問している場合、 Principia Mathematicaから先のすべてを読んでいて、少し復習する必要があると想定しているため、実際には役に立ちません。 . この問題は、「この特定のコードのチャンクを自分の問題に適用するにはどうすればよいか」であるためです。スタック オーバーフローに質問しています。

「 N枚のカードのデッキがあり、そのうちのM枚が対象のカードである場合、上位Q枚のカードに対象のカードのコピーが少なくとも 1 枚ある確率は?」という形式の問題があります。また、「 N枚のカードのデッキがあり、そのうちのM枚が対象のカードである場合、そのうちの 1 枚がコピーになる可能性が 90% になるには、デッキから何枚のカードを引かなければならないか」という形式の問題もあります。気になるカードは?」前者の問題は、SciPy のドキュメントに記載されている問題例に非常に近いですが、同じものではなく、メソッドのリストはすべて専門用語であり、実際にどれが必要なのかわかりません。また、後者のタイプの問題にどの方法を使用すればよいかわかりません。

のメソッドはscipy.stats.hypergeom実際に何をするのか、その引数は何なのか、それらを自分の問題にどのように適用できるのか? 私は適度に明るい高校生であり、数学の博士号取得者ではありません。

4

2 に答える 2

4
scipy.stats.hypergeom.pmf(k, M, n, N)

は次の確率を返します: n がマークされている M 枚のカードから、N 枚のカードを置換せずにランダムに選択すると、ちょうど k 枚のカードがマークされます。

したがって、(変数名を使用して)目的の答えを得ることができます

def pick_Q(N, M, Q):
    """
    Given a deck of N cards, where M are marked,
    and Q cards are taken randomly without replacement,
    return the probability that at least one marked card is taken.
    """
    return sum(scipy.stats.hypergeom.pmf(k, N, M, Q) for k in xrange(1,Q+1))

(1 枚のカードがマークされる確率、2 枚のカードがマークされる確率、3 枚のカードがマークされる確率の合計... N 枚のカードがマークされる確率)。

幸いなことに、より迅速な方法があります - 少なくとも 1 枚のマークされたカードが取られる確率は、マークされたカードが選ばれない確率の裏返しです。したがって、代わりに次のことができます

def pick_Q(N, M, Q):
    """
    Given a deck of N cards, where M are marked,
    and Q cards are taken randomly without replacement,
    return the probability that at least one marked card is taken.
    """
    return 1. - scipy.stats.hypergeom.pmf(0, N, M, Q)

2 番目の質問については、希望どおりの機能がないようです。しかし、あなたはで始めることができます

def how_many_to_pick(N, M, prob):
    """
    Given a deck of N cards, M of which are marked,
    how many do you have to pick randomly without replacement
    to have at least prob probability of picking at least one marked card?
    """
    for q in xrange(1, M+1):
        if pick_Q(N, M, q) >= prob:
            return q
    raise ValueError("Could not find a value for q")

編集:

scipy.stats.hypergeom.cdf(k, M, n, N)

M 枚のカードのデッキがあり、n 枚がマークされており、N 枚を交換せずに無作為に選び、マークされたカードがk 個以下になる確率を求めます。(これは .pmf の積分と考えることができます)

次に、 .sf(k, M, n, N) は .cdf の裏返しです。つまり、マークされたカードがk 枚以上選ばれる確率です。

例えば、

 k      pmf(k,52,13,4)   cdf(k,52,13,4)   sf(k,52,13,4)
     (exactly k picked)  ( <= k picked)   ( > k picked)
---  -----------------  ---------------  --------------
 0       0.303817527      0.303817527      0.696182473
 1       0.438847539      0.742665066      0.257334934
 2       0.213493397      0.956158463      0.043841537
 3       0.041200480      0.997358944      0.002641056
 4       0.002641056      1.000000000      0.000000000

編集2:

実際、これは pick_Q 関数の別の書き方を提供します - 「1 枚以上のマークされたカードを選ぶ」は「0 枚以上のマークされたカードを選ぶ」と言い換えることができます。

def pick_Q(N, M, Q):
    """
    Given a deck of N cards, where M are marked,
    and Q cards are taken randomly without replacement,
    return the probability that at least one marked card is taken.
    """
    return scipy.stats.hypergeom.sf(0, N, M, Q)
于 2012-07-02T01:57:44.507 に答える
2

これは、まったく使用せずに解決するのが難しい問題ではないことに注意してくださいscipy。10 個のアイテムのランダム順列があるとします。

4, 7, 2, 3, 0, 9, 1, 5, 6, 8

そして「勝者」のセット2, 4, 6。気にするのは勝者と敗者だけなので、表現を少し単純化できます。

1, 0, 1, 0, 0, 0, 0, 0, 1, 0

10 個の可能なアイテムと 3 個の勝者の任意のセットで同じことができます。10 個のアイテムの可能な順列が与えられれば、同じ単純化を実行できます。つまり、実際に起こっていることは、各順列が 3 つの勝利インデックスを「選択」し、デッキ内の勝者の可能な配置の数が1010! / (3! * 7!)あるということです。

ここで知る必要があるのは、勝者の可能な配置のうち、最初のQカードで少なくとも 1 人の勝者が得られる数です。最初のカードで正確に0の勝者が得られる配置の数を計算する方が簡単なのでQ、代わりにそれを計算します。したがって、最も具体的には、次のようなシーケンスの数が必要です (Q = 4 の場合)。

0, 0, 0, 0 | 0, 1, 0, 1, 1, 0

ここではシーケンスを分割しており、分割の前の値は常にゼロでなければなりません。そのようなシーケンスはいくつありますか? まあ、6 枚のカードに 3 人の勝者を含むシーケンスがあるのとまったく同じ数のシーケンスがあります。つまり 6 で 3 を選択します6! / (3! * 3!)

したがって、10 個の値のランダムな順列で、最初の 3 つの値に勝者が含まれない確率を取得するには、単純に次のように計算します。

(6 choose 3) / (10 choose 3)

逆オッズ (つまり、最初の 3 つのうち少なくとも 1 つに勝者が含まれるオッズ) を取得するには、次のようにします。

1 - (6 choose 3) / (10 choose 3)

total= Nwinners= M、およびtries=を使用した一般化Q:

1 - ((N - Q) chose M) / (N chose M)

Python では、次のようになります。

>>> def choose(n, x):
...     return reduce(mul, range(n, n - x, -1)) / math.factorial(x)
...
>>> def ntries_win_odds(total, winners, tries):
...     inv = (choose(total - tries, winners) / float(choose(total, winners)))
...     return 1 - inv

反対方向の解はそれほど難しくありません。与えられたとc = n choose xを解く「逆選択」関数が必要なだけです。ここにはアルゴリズムの改善の余地があると思いますが、これはうまくいきます:ncx

>>> def choose_x_pseudoinverse(target, x):
...     for n in itertools.count(start=x):
...         if choose(n, x) >= target:
...             return n

今、試行のために解決します:

odds = 1 - ((total - tries) chose winners) / (total chose winners)
(1 - odds) * (total choose winners) = ((total - tries) chose winners)
choose_x_inv((1 - odds) * (total choose winners), winners) = total - tries
tries = total - choose_x_inv((1 - odds) & (total choose winners), winners)

Pythonでは、それは

def ntries_from_odds(odds, total, winners):
    inv_odds = 1 - odds
    tCw = choose(total, winners)
    return total - choose_x_pseudoinverse(inv_odds * tCw, winners)  
于 2012-07-02T02:55:34.310 に答える