How to generate a probability vector? - matlab

I would like to generate a vector of probabilities that is following some known distribution.
For example when I want the distribution to be uniform I can do in MATLAB:
N = 5;
proba = (1/(N))*ones(1, N);
What to do if I want to do it with Poisson distribution or Binomial distribution?

If you're looking for a solution that uses built-in MATLAB functions, you can look into random, which allows you to supply parameters to many types of well-known distributions.
For example, if you want to draw a M x N matrix of values from a binomial distribution with n trials and a p chance of success:
n=3; p=0.5; M=20; N=1;
random('Binomial',n,p,[M,N])
If you have a (discrete) probability distribution of your own creation, with the PMF given as a vector, you can sample from it by generating a random number r from a uniform distribution on [0,1] using r=rand() and then picking the first bin in the CMF which is greater than r.
x = [ 0 1 2 3 ];
PMF = [0.25 0.2 0.5 0.05];
CMF = cumsum(PMF);
N = 10000;
valuesDrawn = zeros(N,1);
for i = 1:N
r = rand();
for j = 1:length(PMF)
if r < CMF(j)
valuesDrawn(i) = x(j);
break;
end
end
end
hist(valuesDrawn);

Related

Generating two correlated uniform random variables in Matlab

Like the title suggests, I am facing difficulty in understanding how we generate two correlated uniform [0,1] random variables. I am new to the idea of copulas.
I am struggling to write a MATLAB code wherein I am required to generate two correlated uniform [0,1] random variables.
Generating correlated uniform random variables with Gaussian Copula
rho = .75; % Desired target correlation
N = 1000; % Number of samples
Z = mvnrnd([0 0],[1 rho; rho 1], N);
U = normcdf(Z); % Correlated U(0,1) random variables
scatterhist(U(:,1),U(:,2),'Direction','out') % Visualize (change `rho` to see impact)
Note: Method not guaranteed to hit target correlation exactly but should be close enough for many applications.
This can be very useful to quickly generate correlated distributions using the inverse transform method (either analytically or numerically). Both use cases illustrated below.
Analytical approach
lambda = 2; alpha = 2; beta = 3;
rho = -.35; N = 1000;
Z = mvnrnd([0 0],[1 rho; rho 1], N);
U = normcdf(Z);
X = (-1/lambda)*log(U(:,1)); % Inverse Transform for Exponential
Y = beta*(-log(U(:,2))).^(1/alpha); % Inverse Transform for Weibull
corr(X,Y)
scatterhist(X,Y,'Direction','out')
Numerical approach
% Parameters
alpha = 6.7; lambda = 3;
mu = 0.1; sigma = 0.5;
rho = 0.75; N = 1000;
% Make distributions
pd_X = makedist('Gamma',alpha,lambda);
pd_Y = makedist('Lognormal',mu,sigma);
Z = mvnrnd([0 0],[1 rho; rho 1], N);
U = normcdf(Z);
% Use Inverse Transform for marginal distributions (numerically)
X = icdf(pd_X,U(:,1)); % Inverse CDF for X
Y = icdf(pd_Y,U(:,2)); % Inverse CDF for Y
corr(X,Y)
scatterhist(X,Y,'Direction','out')
References:
Inverse Transform
Copulas
Gaussian copula:
Ross, Sheldon. (2013). Simulation. Academic Press, San Diego, CA, 5th edition. 103--105.
Modified related answer from here.

Generating complex antisymmetric matrix in Matlab

Is there any possibility to generate Gaussian random complex antisymmetric matrices in Matlab?
I have tried using randn(M). But that simply gives random matrices of Gaussian distribution.
This will deliver you a Gaussian random complex antisymmetric matrix M with numbers from 0 to x. If you change x, you change the upper limit of the RNG.
n = 5; %rows and columns
M = ones(n,n); %matrix initiation
x = 50; %limit of random number generator;
for i = 1 : n
M(i,:) = complex(round(50.*randn(1,n)),round(50.*randn(1,n))); %generate random number for the row;
M(:,i) = M(i,:).'; % take the same number and put it in the antisymmetric slot
end %for

How to draw random numbers from a gamma distribution without the Statistics Toolbox?

I am varying the signal strength for synthetic images. I need the signal to vary between 0 and 0.1, but I need to do this with a gamma distribution so that more of them fall around the .01/.02 range. The problem is that I am using the 2010 version of Matlab without the Statistics Toolbox that doesn't have the gamrnd function a part of its library.
Any and all help is greatly appreciated.
You can use the Inverse transform sampling method to convert a uniform distribution to any other distribution:
P = rand(1000);
X = gaminv(P(:),2,2); % with k = 2 and theta = 2
Here is a litle demonstration:
for k = [1 3 9]
for theta = [0.5 1 2]
X = gaminv(P(:),k,theta);
histogram(X,50)
hold on
end
end
Which gives:
Edit:
Without the statistics toolbox, you can use the Marsaglia's simple transformation-rejection method to generate random numbers from gamma distribution with rand and randn:
N = 10000; % no. of tries
% distribution parameters:
a = 0.5;
b = 0.1;
% Marsaglia's simple transformation-rejection:
d = a - 1/3;
x = randn(N,1);
U = rand(N,1);
v = (1+x./sqrt(9*d)).^3;
accept = log(U)<(0.5*x.^2+d-d*v+d*log(v));
Y = d*(v(accept)).*b;
Now Y is distributed like gamma(a,b). We can test the result using the gamrnd function:
n = size(Y,1);
X = gamrnd(a,b,n,1);
And the histograms of Y, and X are:
However, keep in mind that gamma distribution might not fit your needs because it has no specific upper bound (i.e. goes to infinity). So you may want to use another (bounded) distribution, like beta divided by 10.

Random Numbers with Gaussian and Uniform Distributions in matlab

I want generate a number in Gaussian and Uniform distributions in matlab.
I know this function randi and rand() but all of them are in normal (Gaussian) distribution. How can a generate a random number in uniform distribution?
Use rand(dimensions) for a Uniform Distribution between 0 and 1.
Use randn(dimensions) * sqrt(sigma) + mu for a Gaussian Distribution with a mean of mu and standard deviation of sigma.
randn is the function to generate Gaussian distributed variables (randi and rand produce uniformly distributed ones).
You can generate any distribution from rand().
For example , lets say you want to generate 100000 samples for rayleigh dist.The way to do this is that you invert the cdf of that particular function.The basic idea is that since the cdf has to be between 0 and 1 , we can find the value of the random variable by inputting the value of cdf b/w 0 and 1. So for rayleigh, it would be
for i = 1:100000
data(i) = (2*sigma^2 *(-(log(1 - rand(1,1)))))^.5;
end
You can do something similar for gaussian distribution.
Congrulations, you already generating pseudo-random numbers with a gaussian distribution. Normal distribution is a synonym for it.
The only other possible interpretation I can get from your question is that you want something that has mean != 0 and/or variance != 1. To do that, simply perform mean + sqrt(var) * randn(X).
It is true you can generate just about anything from rand but that it isn't always convenient, especially for some complicated distributions.
MATLAB has introduced Probability Distribution Objects which make this a lot easier and allow you to seamlessly access mean, var, truncate, pdf, cdf, icdf (inverse transform), median, and other functions.
You can fit a distribution to data. In this case, we use makedist to define the probability distribution object. Then we can generate using random.
% Parameters
mu = 10;
sigma = 3;
a = 5; b = 15;
N = 5000;
% Older Approaches Still Work
rng(1775)
Z = randn(N,1); % Standard Normal Z~N(0,1)
X = mu + Z*sigma; % X ~ Normal(mu,sigma)
U = rand(N,1); % U ~ Uniform(0,1)
V = a + (b-a)*U; % V ~ Uniform(a,b)
% New Approaches Are Convenient
rng(1775)
pdX = makedist('Normal',mu,sigma);
X2 = random(pdX,N,1);
pdV = makedist('Uniform',a,b);
V2 = random(pdV,N,1);
A reproducible example:
Support = (0:0.01:20)';
figure
s(1) = subplot(2,2,1)
h(1) = histogram(X,'Normalization','pdf')
xlabel('Normal')
s(2) = subplot(2,2,2)
h(2) = histogram(V,'Normalization','pdf')
xlabel('Uniform')
s(3) = subplot(2,2,3), hold on, box on
h(3) = histogram(X2,'Normalization','pdf')
plot(Support,pdf(pdX,Support),'r-','LineWidth',1.2)
xlabel('Normal (new)')
s(4) = subplot(2,2,4), hold on, box on
h(4) = histogram(V2,'Normalization','pdf')
plot(Support,pdf(pdV,Support),'r-','LineWidth',1.2)
xlabel('Uniform (new)')
xlim(s,[0 20])
References:
Uniform Distribution
Normal (Gaussian) Distribution
Following raj's answer: by using the Box-Muller Transform you can generate independent standard Normal/Gaussian random numbers:
N = 1e6; z = sqrt(-2*log(rand(N, 1))) .* cos(2*pi * rand(N, 1)); figure; hist(z, 100)
N = 1e6; z = sqrt(-2*log(rand(N, 1))) .* sin(2*pi * rand(N, 1)); figure; hist(z, 100)
If you want to apply the Inverse Transformation Method, you can use the Inverse Complementary Error Function (erfcinv):
N = 1e6; z = -sqrt(2) * erfcinv(2 * rand(1e6, 1)); figure; hist(z, 100)
But I hope randn works better.

Creating Gaussian random variable with MATLAB

By using randn function I want to create a Gaussian random variable X such that X ~ N(2,4) and plot this simulated PDF together with theoretic curve.
Matlab randn generates realisations from a normal distribution with zero mean and a standard deviation of 1.
Samples from any other normal distribution can simply be generated via:
numSamples = 1000;
mu = 2;
sigma = 4;
samples = mu + sigma.*randn(numSamples, 1);
You can verify this by plotting the histogram:
figure;hist(samples(:));
See the matlab help.
N = 1000;
x = [-20:20];
samples = 2 + 4*randn(N, 1);
ySamples = histc(samples,x) / N;
yTheoretical = pdf('norm', x, 2, 4);
plot(x, yTheoretical, x, ySamples)
randn(N, 1) creates an N-by-1 vector.
histc is histogram count by bins given in x - you can use hist to plot the result immediately, but here we want to divide it by N.
pdf contains many useful PDFs, normal is just one example.
remember this: X ~ N(mean, variance)
randn in matlab produces normal distributed random variables W with zero mean and unit variance.
To change the mean and variance to be the random variable X (with custom mean and variance), follow this equation:
X = mean + standard_deviation*W
Please be aware of that standard_deviation is square root of variance.
N = 1000;
x = [-20:20];
samples = 2 + sqrt(4)*randn(N, 1);
ySamples = histc(samples,x) / N;
yTheoretical = pdf('norm', x, 2, sqrt(4)); %put std_deviation not variance
plot(x, yTheoretical, x, ySamples)
A quick and easy way to achieve this using one line of code is to use :
mu = 2;
sigma = 2;
samples = normrnd(mu,sigma,M,N);
This will generate an MxN matrix, sampled from N(μ,𝜎), (= N(2,2) in this particular case).
For additional information, see normrnd.