How to get a uniform distribution in a range [r1,r2] in PyTorch?
Question:
I want to get a 2-D torch.Tensor
with size [a,b]
filled with values from a uniform distribution (in range [r1,r2]
) in PyTorch.
Answers:
If U
is a random variable uniformly distributed on [0, 1], then (r1 - r2) * U + r2
is uniformly distributed on [r1, r2].
Thus, you just need:
(r1 - r2) * torch.rand(a, b) + r2
Alternatively, you can simply use:
torch.FloatTensor(a, b).uniform_(r1, r2)
To fully explain this formulation, let’s look at some concrete numbers:
r1 = 2 # Create uniform random numbers in half-open interval [2.0, 5.0)
r2 = 5
a = 1 # Create tensor shape 1 x 7
b = 7
We can break down the expression (r1 - r2) * torch.rand(a, b) + r2
as follows:
torch.rand(a, b)
produces an a x b
(1×7) tensor with numbers uniformly distributed in the range [0.0, 1.0).
x = torch.rand(a, b)
print(x)
# tensor([[0.5671, 0.9814, 0.8324, 0.0241, 0.2072, 0.6192, 0.4704]])
(r1 - r2) * torch.rand(a, b)
produces numbers distributed in the uniform range [0.0, -3.0)
print((r1 - r2) * x)
tensor([[-1.7014, -2.9441, -2.4972, -0.0722, -0.6216, -1.8577, -1.4112]])
(r1 - r2) * torch.rand(a, b) + r2
produces numbers in the uniform range [5.0, 2.0)
print((r1 - r2) * x + r2)
tensor([[3.2986, 2.0559, 2.5028, 4.9278, 4.3784, 3.1423, 3.5888]])
Now, let’s break down the answer suggested by @Jonasson: (r2 - r1) * torch.rand(a, b) + r1
- Again,
torch.rand(a, b)
produces (1×7) numbers uniformly distributed in the range [0.0, 1.0).
x = torch.rand(a, b)
print(x)
# tensor([[0.5671, 0.9814, 0.8324, 0.0241, 0.2072, 0.6192, 0.4704]])
(r2 - r1) * torch.rand(a, b)
produces numbers uniformly distributed in the range [0.0, 3.0).
print((r2 - r1) * x)
# tensor([[1.7014, 2.9441, 2.4972, 0.0722, 0.6216, 1.8577, 1.4112]])
(r2 - r1) * torch.rand(a, b) + r1
produces numbers uniformly distributed in the range [2.0, 5.0)
print((r2 - r1) * x + r1)
tensor([[3.7014, 4.9441, 4.4972, 2.0722, 2.6216, 3.8577, 3.4112]])
In summary, (r1 - r2) * torch.rand(a, b) + r2
produces numbers in the range [r2, r1), while (r2 - r1) * torch.rand(a, b) + r1
produces numbers in the range [r1, r2).
torch.FloatTensor(a, b).uniform_(r1, r2)
To get a uniform random distribution, you can use
torch.distributions.uniform.Uniform()
example,
import torch
from torch.distributions import uniform
distribution = uniform.Uniform(torch.Tensor([0.0]),torch.Tensor([5.0]))
distribution.sample(torch.Size([2,3])
This will give the output, tensor of size [2, 3].
Please Can you try something like:
import torch as pt
pt.empty(2,3).uniform_(5,10).type(pt.FloatTensor)
This answer uses NumPy to first produce a random matrix and then converts the matrix to a PyTorch tensor. I find the NumPy API to be easier to understand.
import numpy as np
torch.from_numpy(np.random.uniform(low=r1, high=r2, size=(a, b)))
See this for all distributions: https://pytorch.org/docs/stable/distributions.html#torch.distributions.uniform.Uniform
This is the way I found works:
# generating uniform variables
import numpy as np
num_samples = 3
Din = 1
lb, ub = -1, 1
xn = np.random.uniform(low=lb, high=ub, size=(num_samples,Din))
print(xn)
import torch
sampler = torch.distributions.Uniform(low=lb, high=ub)
r = sampler.sample((num_samples,Din))
print(r)
r2 = torch.torch.distributions.Uniform(low=lb, high=ub).sample((num_samples,Din))
print(r2)
# process input
f = nn.Sequential(OrderedDict([
('f1', nn.Linear(Din,Dout)),
('out', nn.SELU())
]))
Y = f(r2)
print(Y)
but I have to admit I don’t know what the point of generating sampler is and why not just call it directly as I do in the one liner (last line of code).
Comments:
- sampler are good for it’s so you can transform/compose/cache/etc distributions. see https://arxiv.org/abs/1711.10604, and the top of the docs of https://pytorch.org/docs/stable/distributions.html# and https://arxiv.org/abs/1506.05254
- you can feed in tensors to uniform to let it know the high dimensional interval (hypercube) to generate the uniform samples (that’s why it receives tensors as input rather than simply numbers)
Reference:
Utilize the torch.distributions
package to generate samples from different distributions.
For example to sample a 2d PyTorch tensor of size [a,b]
from a uniform distribution of range(low, high)
try the following sample code
import torch
a,b = 2,3 #dimension of the pytorch tensor to be generated
low,high = 0,1 #range of uniform distribution
x = torch.distributions.uniform.Uniform(low,high).sample([a,b])
PyTorch has a number of distributions built in. You can build a tensor of the desired shape
with elements drawn from a uniform distribution like so:
from torch.distributions.uniform import Uniform
shape = 3,4
r1, r2 = 0,1
x = Uniform(r1, r2).sample(shape)
Pytorch (now?) has a random integer function that allows:
torch.randint(low=r1, high=r2, size=(1,), **kwargs)
and returns uniformly sampled random integers of shape size in range [r1, r2).
https://pytorch.org/docs/stable/generated/torch.randint.html
I want to get a 2-D torch.Tensor
with size [a,b]
filled with values from a uniform distribution (in range [r1,r2]
) in PyTorch.
If U
is a random variable uniformly distributed on [0, 1], then (r1 - r2) * U + r2
is uniformly distributed on [r1, r2].
Thus, you just need:
(r1 - r2) * torch.rand(a, b) + r2
Alternatively, you can simply use:
torch.FloatTensor(a, b).uniform_(r1, r2)
To fully explain this formulation, let’s look at some concrete numbers:
r1 = 2 # Create uniform random numbers in half-open interval [2.0, 5.0)
r2 = 5
a = 1 # Create tensor shape 1 x 7
b = 7
We can break down the expression (r1 - r2) * torch.rand(a, b) + r2
as follows:
torch.rand(a, b)
produces ana x b
(1×7) tensor with numbers uniformly distributed in the range [0.0, 1.0).
x = torch.rand(a, b)
print(x)
# tensor([[0.5671, 0.9814, 0.8324, 0.0241, 0.2072, 0.6192, 0.4704]])
(r1 - r2) * torch.rand(a, b)
produces numbers distributed in the uniform range [0.0, -3.0)
print((r1 - r2) * x)
tensor([[-1.7014, -2.9441, -2.4972, -0.0722, -0.6216, -1.8577, -1.4112]])
(r1 - r2) * torch.rand(a, b) + r2
produces numbers in the uniform range [5.0, 2.0)
print((r1 - r2) * x + r2)
tensor([[3.2986, 2.0559, 2.5028, 4.9278, 4.3784, 3.1423, 3.5888]])
Now, let’s break down the answer suggested by @Jonasson: (r2 - r1) * torch.rand(a, b) + r1
- Again,
torch.rand(a, b)
produces (1×7) numbers uniformly distributed in the range [0.0, 1.0).
x = torch.rand(a, b)
print(x)
# tensor([[0.5671, 0.9814, 0.8324, 0.0241, 0.2072, 0.6192, 0.4704]])
(r2 - r1) * torch.rand(a, b)
produces numbers uniformly distributed in the range [0.0, 3.0).
print((r2 - r1) * x)
# tensor([[1.7014, 2.9441, 2.4972, 0.0722, 0.6216, 1.8577, 1.4112]])
(r2 - r1) * torch.rand(a, b) + r1
produces numbers uniformly distributed in the range [2.0, 5.0)
print((r2 - r1) * x + r1)
tensor([[3.7014, 4.9441, 4.4972, 2.0722, 2.6216, 3.8577, 3.4112]])
In summary, (r1 - r2) * torch.rand(a, b) + r2
produces numbers in the range [r2, r1), while (r2 - r1) * torch.rand(a, b) + r1
produces numbers in the range [r1, r2).
torch.FloatTensor(a, b).uniform_(r1, r2)
To get a uniform random distribution, you can use
torch.distributions.uniform.Uniform()
example,
import torch
from torch.distributions import uniform
distribution = uniform.Uniform(torch.Tensor([0.0]),torch.Tensor([5.0]))
distribution.sample(torch.Size([2,3])
This will give the output, tensor of size [2, 3].
Please Can you try something like:
import torch as pt
pt.empty(2,3).uniform_(5,10).type(pt.FloatTensor)
This answer uses NumPy to first produce a random matrix and then converts the matrix to a PyTorch tensor. I find the NumPy API to be easier to understand.
import numpy as np
torch.from_numpy(np.random.uniform(low=r1, high=r2, size=(a, b)))
See this for all distributions: https://pytorch.org/docs/stable/distributions.html#torch.distributions.uniform.Uniform
This is the way I found works:
# generating uniform variables
import numpy as np
num_samples = 3
Din = 1
lb, ub = -1, 1
xn = np.random.uniform(low=lb, high=ub, size=(num_samples,Din))
print(xn)
import torch
sampler = torch.distributions.Uniform(low=lb, high=ub)
r = sampler.sample((num_samples,Din))
print(r)
r2 = torch.torch.distributions.Uniform(low=lb, high=ub).sample((num_samples,Din))
print(r2)
# process input
f = nn.Sequential(OrderedDict([
('f1', nn.Linear(Din,Dout)),
('out', nn.SELU())
]))
Y = f(r2)
print(Y)
but I have to admit I don’t know what the point of generating sampler is and why not just call it directly as I do in the one liner (last line of code).
Comments:
- sampler are good for it’s so you can transform/compose/cache/etc distributions. see https://arxiv.org/abs/1711.10604, and the top of the docs of https://pytorch.org/docs/stable/distributions.html# and https://arxiv.org/abs/1506.05254
- you can feed in tensors to uniform to let it know the high dimensional interval (hypercube) to generate the uniform samples (that’s why it receives tensors as input rather than simply numbers)
Reference:
Utilize the torch.distributions
package to generate samples from different distributions.
For example to sample a 2d PyTorch tensor of size [a,b]
from a uniform distribution of range(low, high)
try the following sample code
import torch
a,b = 2,3 #dimension of the pytorch tensor to be generated
low,high = 0,1 #range of uniform distribution
x = torch.distributions.uniform.Uniform(low,high).sample([a,b])
PyTorch has a number of distributions built in. You can build a tensor of the desired shape
with elements drawn from a uniform distribution like so:
from torch.distributions.uniform import Uniform
shape = 3,4
r1, r2 = 0,1
x = Uniform(r1, r2).sample(shape)
Pytorch (now?) has a random integer function that allows:
torch.randint(low=r1, high=r2, size=(1,), **kwargs)
and returns uniformly sampled random integers of shape size in range [r1, r2).
https://pytorch.org/docs/stable/generated/torch.randint.html