2017-11-17 7 views
0

私は、C#で多項分布からサンプルする簡単な方法を実装したいと考えました(最初の引数はサンプルしたい整数の配列で、2番目はそれらの整数を選択する確率です)。C#で多項式からサンプルする簡単な方法は何が問題なのですか?

これをpythonでnumpyで行うと、結果は意味をなさないことになります。

np.random.choice(np.array([1,2,3,4,5,6]),p=np.array([.624,.23,.08,.04, .02, .006]),size=len(b)) 

私はC#で、以下の実施をしようとすると、(かなり簡単逆多項のためのサンプリングを変換する、しかし、いくつかの3者など1の(確率62%)、2者の束、

の多くを得ます唯一のランダム変数に依存している)、私は本当に奇妙な結果を得る。 1000のサンプルすべてについて、私は多くの場合、すべて1を見つけるでしょう。時々、私はすべての3(!! ??)を見つけるでしょう。結果は、あなたが期待するものと決して同じではありません(そして、あなたがPythonの機能から何を得るのか - あなた自身でそれを数回試してみてください)。これらのプリミティブに依存しているので、これは本当に恐ろしいことです。誰かがC#バージョンで何が間違っているのかについての洞察を持っていますか?

static void Main(string[] args) 
    { 
     int[] iis = new int[7]; 
     int[] itms = new int[] { 1, 2, 3, 4, 5, 6 }; 
     double[] probs = new double[] { .624, .23, .08, .04, .02, .006 }; 
     for (int i = 0; i < 1000; i++) 
     { 
      iis[MultinomialSample(itms, probs)] += 1; 
     } 

     foreach (var ii in iis) 
     { 
      Console.Write(ii + ","); 
     } 

     Console.Read(); 
    } 


    private static int MultinomialSample(int[] s, double[] ps) 
    { 
     double[] cumProbs = new double[ps.Length]; 
     cumProbs[0] = ps[0]; 

     for (int i = 1; i < ps.Length; i++) 
     { 
      cumProbs[i] = cumProbs[i - 1] + ps[i]; 
     } 

     Random random = new Random(); 
     double u = random.NextDouble(); 

     for (int i = 0; i < cumProbs.Length - 1; i++) 
     { 
      if (u < cumProbs[i]) 
      { 
       return s[i]; 
      } 
     } 

     return s[s.Length - 1]; 
    } 
+2

private static Random random = new Random();またはそれは一度だけ初期化されるだろうMainから引数としてメソッドに渡し:Randomプライベートクラスフィールドを作るのいずれか試してみてください。これらの呼び出しが非常に接近している場合、 'Random'は同じシード(システムクロックに基づいて)で初期化されます。 privateクラスのフィールドを 'Random'にするか、' Private static Random random = new Random(); 'メソッドを' Main'の引数としてメソッドに渡してください。ここで一度だけ初期化されます。 –

答えて

1

あなたはRandomあなたがMultinomialSampleを呼び出すたびに初期化しています。これらのコールが非常に近い場合、Randomは同じシード(システムクロックに基づいて)で初期化されます。あなたが `あなたが` MultinomialSample`を呼び出すRandom`たびに初期化している

private static Random random = new Random(); 

private static int MultinomialSample(IReadOnlyList<int> sample, 
    IReadOnlyList<double> probabilities) 
{ 
    var cumProbs = new double[probabilities.Count]; 
    cumProbs[0] = probabilities[0]; 

    for (var i = 1; i < probabilities.Count; i++) 
    { 
     cumProbs[i] = cumProbs[i - 1] + probabilities[i]; 
    } 

    for (var i = 0; i < cumProbs.Length - 1; i++) 
    { 
     if (random.NextDouble() < cumProbs[i]) 
     { 
      return sample[i]; 
     } 
    } 

    return sample[sample.Count - 1]; 
} 

private static void Main() 
{ 
    var iis = new int[7]; 
    var items = new[] {1, 2, 3, 4, 5, 6}; 
    var probabilities = new[] {.624, .23, .08, .04, .02, .006}; 

    for (int i = 0; i < 1000; i++) 
    { 
     iis[MultinomialSample(items, probabilities)] ++; 
    } 

    Console.WriteLine(string.Join(", ", iis)); 

    Console.WriteLine("\nDone!\nPress any key to exit..."); 
    Console.ReadKey(); 
} 
関連する問題