apostofes
apostofes

Reputation: 3743

How to sample from normal distribution?

If I have n sized mean vector, n sized variance vector, then how do I do this?

z ∼ N (μ, σ)
import torch
x = torch.randn(3, 3)
mu = x.mean()
sigma = x.var()

What do I do to get z?

Upvotes: 3

Views: 3536

Answers (2)

Jiho Choi
Jiho Choi

Reputation: 1321

Updated Solution for 2023

Simply using torch.normal(mean=mean_vector, std=std_vector) would work.

The method described above is correct, but another good way of doing it is to use torch.normal().

Below is an example of sampling from a normal distribution with mean and variance of tensors.

An example is shown below.

PyTorch
import torch

a = torch.tensor([1,  2,  3,  4 * 2, 2])
b = torch.tensor([5,  6,  7,  8 * 2, 2])
c = torch.tensor([5,  6,  7,  8 * 2, 2])
d = torch.tensor([9, 10, 11, 12 * 2, 2])

stacked_vectors = torch.stack([a, b, c, d]).float()  # 2d tensor
mean_vector = stacked_vectors.mean(dim=0)
std_vector = stacked_vectors.std(dim=0)

# --------------------------------------------------------------
# Sampling
# --------------------------------------------------------------
sampled1 = torch.normal(mean=mean_vector, std=std_vector)  # <--
sampled2 = torch.normal(mean=mean_vector, std=std_vector)
# --------------------------------------------------------------

print("mean_vector:", mean_vector)
print("std_vector:", std_vector)
print(sampled1)
print(sampled2)
Results

mean_vector: tensor([ 5., 6., 7., 16., 2.])
std_vector: tensor([3.2660, 3.2660, 3.2660, 6.5320, 0.0000])
tensor([ 3.5221, -0.0818, 5.1410, 13.2573, 2.0000])
tensor([ 6.2393, 6.0634, 2.4302, 20.4233, 2.0000])

Upvotes: 1

Shai
Shai

Reputation: 114966

If you want to sample from a normal distribution with mean mu and std sigma then you can simply

z = torch.randn_like(mu) * sigma + mu

If you sample many such z their mean and std will converge to sigma and mu:

mu = torch.arange(10.)

Out[]: tensor([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])

sigma = 5. - 0.5 * torch.arange(10.)

Out[]: tensor([5.0000, 4.5000, 4.0000, 3.5000, 3.0000, 2.5000, 2.0000, 1.5000, 1.0000, 0.5000])

z = torch.randn(10, 1000000) * sigma[:, None] + mu[:, None]

z.mean(dim=1)
Out[]:
tensor([-5.4823e-03,  1.0011e+00,  1.9982e+00,  2.9985e+00,  4.0017e+00,
         4.9972e+00,  6.0010e+00,  7.0004e+00,  7.9996e+00,  9.0006e+00])

z.std(dim=1)
Out[]:
tensor([4.9930, 4.4945, 4.0021, 3.5013, 3.0005, 2.4986, 1.9997, 1.4998, 0.9990,
        0.5001])

As you can see when you sample 1,000,000 elements from the distribution the sample mean and std are close to the original mu and sigma you started with.

Upvotes: 2

Related Questions