web-dev-qa-db-ja.com

100に加算される乱数:Matlab

[人口の数をさまざまな行列に分割していて、今のところ乱数を使用してコードをテストしたい。]

クイック質問みんなと事前にあなたの助けをありがとう-

私が使うなら;

 100*Rand(9,1)

これらの9つの数値を100に加算する最良の方法は何ですか?

合計が100になる0から100までの9つの乱数が欲しいのですが。

見つけられないようで、これを行う組み込みのコマンドはありますか?.

40
Tetra

私は間違いをよく目にします。特定の合計で乱数を生成するには、一様なランダムセットを使用し、それらをスケーリングするだけという提案があります。しかし、そのようにすると、結果は本当に一様にランダムになりますか?

この簡単なテストを2次元で試してください。巨大なランダムサンプルを生成し、それらを合計して1にスケーリングします。スケーリングにはbsxfunを使用します。

xy = Rand(10000000,2);
xy = bsxfun(@times,xy,1./sum(xy,2));
hist(xy(:,1),100)

それらが本当に均一にランダムである場合、x座標はy座標と同様に均一になります。どんな値でも等しく発生する可能性があります。実際には、2つのポイントを合計して1にするために、(x、y)平面で2つのポイント(0,1)、(1,0)を結ぶ線に沿って配置する必要があります。ポイントが均一になるためには、その線に沿ったすべてのポイントの可能性が等しくなければなりません。

xy histogram

スケーリングソリューションを使用すると、均一性が明らかに失敗します。その線上の任意のポイントは、等しく可能性が高くありません。 3次元でも同じことが起こります。ここの3次元図では、三角形の領域の中心にある点がより密にパックされています。これは不均一性を反映しています。

xyz = Rand(10000,3);
xyz = bsxfun(@times,xyz,1./sum(xyz,2));
plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.')
view(70,35)
box on
grid on

xyzplot

この場合も、単純なスケーリングソリューションは失敗します。それは単に、関心のあるドメインにわたって真に均一な結果を生成しません。

もっと上手くできる?はい、そうです。 2次元の簡単な解決策は、点(0,1)と1,0)を結ぶ線に沿った距離を指定する単一の乱数を生成することです。

t = Rand(10000000,1);
xy = t*[0 1] + (1-t)*[1 0];
hist(xy(:,1),100)

Uniform x+y = 1

単位正方形の方程式x + y = 1で定義される線に沿った任意の点が選択された可能性が高いことを示すことができます。これは、ナイスでフラットなヒストグラムに反映されています。

David Schwartzによって提案された並べ替えのトリックはn次元で機能しますか?明らかにそれは2次元で行われ、下の図は3次元で行われることを示唆しています。この問題について深く考えずに、問題のこの基本的なケースであるn次元で機能すると思います。

n = 10000;
uv = [zeros(n,1),sort(Rand(n,2),2),ones(n,1)];
xyz = diff(uv,[],2);

plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.')
box on
grid on
view(70,35)

Sort trick

Roger Staffordの貢献であるファイル交換から関数 randfixedsum をダウンロードすることもできます。これは、与えられた固定合計を使用して、ユニットハイパーキューブで真に均一なランダムセットを生成するためのより一般的なソリューションです。したがって、ユニット3キューブにあるポイントのランダムなセットを生成するには、それらの合計が1.25になるという制約を受けます...

xyz = randfixedsum(3,10000,1.25,0,1)';
plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.')
view(70,35)
box on
grid on

randfixedsum

80
user85109

簡単な方法の1つは、0から100までの8つの乱数を選択することです。リストに0と100を追加して、10の数値を与えます。それらを並べ替えます。次に、連続する数値の各ペア間の差を出力します。たとえば、以下は0から100までの8つの乱数です。

96、38、95、5、13、57、13、20

したがって、0と100を追加してソートします。

0、5、13、13、20、38、57、95、96、100

今引きます:

5-0 = 5
13-5 = 8
13-13 = 0
20-13 = 7
38-20 = 18
57-38 = 19
95-57 = 38
96-95 = 1
100-96 = 4

そして、あなたはそれを持っています、合計は100になる9つの数です:0、1、4、5、7、8、18、19、38。

63
David Schwartz

正しい答えを出すのに遅すぎることはありません

Sum(X1、...、XN)が1に等しくなるように範囲[0 ... 1]でX1 ... XNをサンプリングすることについて話しましょう。その後、100に再スケーリングできます。

これは ディリクレ分布 と呼ばれ、以下はそれからサンプリングするコードです。最も単純なケースは、すべてのパラメーターが1に等しい場合で、X1、...、XNのすべての周辺分布はU(0,1)になります。一般的に、パラメーターが1以外の場合、周辺分布にピークが生じる可能性があります。

----------------- here ---------------------から取得

ディリクレは、それらの合計で正規化された、単位スケールのガンマ確率変数のベクトルです。したがって、エラーチェックを行わなくても、次のようになります。

a = [1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0]; // 9 numbers to sample
n = 10000;
r = drchrnd(a,n)

function r = drchrnd(a,n)
  p = length(a);
  r = gamrnd(repmat(a,n,1),1,n,p);
  r = r ./ repmat(sum(r,2),1,p);
6

N-1個の数値のリストを取得し、0と100を挿入してN + 1個の数値のリストを作成し、リストを並べ替えて、合計N個の数値に差分します。

0
user2392848