0

normrnd を使用して正規分布を持つ正規乱数行列を生成する関数があります。

             values(vvvv)= normrnd(0,0.2);

round1 からの出力は次のとおりです。 ans =

0.0210    0.1445    0.5171   -0.1334    0.0375   -0.0165       Inf   -0.3866   -0.0878   -0.3589

ラウンド 2 の出力は次のとおりです。 ans =

0.0667    0.0783    0.0903   -0.0261    0.0367   -0.0952    0.1724   -0.2723       Inf       Inf

ラウンド 3 の出力は次のとおりです。 ans =

0.4047   -0.4517    0.4459    0.0675    0.2000   -0.3328   -0.1180   -0.0556    0.0845       Inf

関数は 20 回繰り返されます。

関数が完全にランダムであることは明らかです。私が求めているのは、条件を追加することです。

私が必要としているのは、エントリの値が 0.2 から 0.3 の間である場合です。その値は次のラウンドで修正されます。関数 rand を使用して、残りのエントリのみが変更されます。

rand、randi、および randn が予測可能な数列を生成するように、非負の整数 sd を使用して乱数発生器をシードする rng(sd) を見つけました。

擬似乱数ジェネレーターのカスタム シードを設定する方法

しかし、マトリックスのいくつかのエントリを作成する方法のみが影響を受けます!!

別の問題: matlab r2009 では rng を使用できないようです確率と統計の複雑さを入力せずに同様のものを取得する方法

4

1 に答える 1

2

これは、これらすべての行列を実際に生成するよりも直接的に行うことができ、最終的な出力の分布について考えると、非常に簡単に行うことができます。

N(0, .2) で分布する確率変数が .2 から .3 の間にある確率は p ~= .092 です。

行列 X の最終出力の確率変数を呼び出します。ここで、これを n (20) 回行います。次に、(a) X が .2 から .3 の間にあり、早期に停止したか、(b) 最初の n-1 ドローで .2 から .3 の間の数字をドローしなかったので、得たものは何でも使用しました。 n回目の抽選で。

(b) が発生する確率は、ちょうど b=(1-p)^(n-1) です: [.2, .3] の外側に描画する独立したイベントは、確率 1-p で n-1 回発生しました。したがって、(a) の確率は 1-b です。

(b) が発生した場合は、 から数字を引くだけですnormrnd。(a) が発生した場合は、.2 から .3 の間であるという条件付きの通常の変数の値が必要です。これを行う 1 つの方法は、.2 と .3 の cdf 値を見つけ、その間の範囲から一様に描画し、逆 cdf を使用して元の数値を取得することです。

これを行うコード:

mu = 0;
sigma = .2;
upper = .3;
lower = .2;
n = 20;
sz = 15;

cdf_upper = normcdf(upper, mu, sigma);
cdf_lower = normcdf(lower, mu, sigma);
p = cdf_upper - cdf_lower;
b = (1-p) ^ (n - 1);

results = zeros(sz, sz);
mask = rand(sz, sz) > b; % mask value 1 means case (a), 0 means case (b)
num_a = sum(mask(:));

cdf_vals = rand(num_a, 1) * p + cdf_lower;
results(mask) = norminv(cdf_vals, mu, sigma);

results(~mask) = normrnd(mu, sigma, sz^2 - num_a, 1);

何らかの理由でこれを直接シミュレートしたい場合 (これには多くの無駄な労力が伴いますが、明らかに「統計の複雑さ」が気に入らないようです -- ちなみに、これは統計ではなく確率です)。最初の行列を生成し、目的の範囲に含まれない要素のみを置き換えることができます。例えば:

mu = 0;
sigma = .2;
n = 10;
m = 10;
num_runs = 20;
lower = .2;
upper = .3;

result = normrnd(mu, sigma, n, m);
for i = 1 : (num_runs - 1)
    to_replace = (result < lower) | (result > upper);
    result(to_replace) = normrnd(mu, sigma, sum(to_replace(:)), 1);
end

これらが同じであることを示すために、これを 1x1 行列に対して 100,000 回実行した経験的 CDF のプロットを次に示します。(つまり、両方の関数を 10 万回実行し、結果を保存してcdfplotから、x 軸の値と、取得した値の y 軸の値よりも小さい部分をプロットするために使用しました。)

それらは同一です。(実際、分布の同一性に対するKS 検定では、p 値が .71 になります。) しかし、直接的な方法は、実行がはるかに高速でした。

于 2012-04-06T19:56:08.660 に答える