Domanda

Matlab has the function randn to draw from a normal distribution e.g.

x = 0.5 + 0.1*randn() 

draws a pseudorandom number from a normal distribution of mean 0.5 and standard deviation 0.1.

Given this, is the following Matlab code equivalent to sampling from a normal distribution truncated at 0 at 1?

    while x <=0 || x > 1

    x = 0.5 + 0.1*randn();

    end
È stato utile?

Soluzione

Using MATLAB's Probability Distribution Objects makes sampling from truncated distributions very easy.

You can use the makedist() and truncate() functions to define the object and then modify (truncate it) to prepare the object for the random() function which allows generating random variates from it.

% MATLAB R2017a
pd = makedist('Normal',0.5,0.1)     % Normal(mu,sigma)
pdt = truncate(pd,0,1)              % truncated to interval (0,1)
sample = random(pdt,numRows,numCols)  % Sample from distribution `pdt`

Once the object is created (here it is pdt, the truncated version of pd), you can use it in a variety of function calls.

To generate samples, random(pdt,m,n) produces a m x n array of samples from pdt.


Further, if you want to avoid use of toolboxes, this answer from @Luis Mendo is correct (proof below).

Comparison of @Luis Mendo code results with theoretical results

figure, hold on
h = histogram(cr,'Normalization','pdf','DisplayName','@Luis Mendo samples');
X = 0:.01:1;
p = plot(X,pdf(pdt,X),'b-','DisplayName','Theoretical (w/ truncation)');

Altri suggerimenti

You need the following steps 1. Draw a random value from uniform distribution, u. 2. Assuming the normal distribution is truncated at a and b. get

u_bar = F(a)*u +F(b) *(1-u)

3. Use the inverse of F

epsilon= F^{-1}(u_bar)

epsilon is a random value for the truncated normal distribution.

Why don't you vectorize? It will probably be faster:

N = 1e5; % desired number of samples
m = .5; % desired mean of underlying Gaussian
s = .1; % desired std of underlying Gaussian
lower = 0; % lower value for truncation
upper = 1; % upper value for truncation

remaining = 1:N;
while remaining
    result(remaining) = m + s*randn(1,numel(remaining)); % (pre)allocates the first time
    remaining = find(result<=lower | result>upper);
end
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top