53

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.

iacob
  • 20,084
  • 6
  • 92
  • 119
Bishwajit Purkaystha
  • 1,975
  • 7
  • 22
  • 30
  • 1
    idk if it's just me but I find that `torch.rand` is very bad naming. I'd have no idea if it's Gaussian or Uniform without looking at the docs (that btw take ages to load for some reason on a browser). – Charlie Parker Jul 13 '20 at 16:08
  • 3
    scratch my previous comment. Use this: `r2 = torch.torch.distributions.Uniform(low=lb, high=ub).sample((num_samples,Din)) ` – Charlie Parker Jul 15 '20 at 16:44

9 Answers9

87

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:

  1. torch.rand(a, b) produces an a x b (1x7) 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]])
  1. (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]])
  1. (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

  1. Again, torch.rand(a, b) produces (1x7) 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]])
  1. (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]])
  1. (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).

stackoverflowuser2010
  • 38,621
  • 48
  • 169
  • 217
BiBi
  • 7,418
  • 5
  • 43
  • 69
  • 9
    shouldn't it be the other way round? I.e. (r2-r1)*torch.rand(a,b) + r1? – Jonasson Nov 05 '18 at 12:11
  • 1
    Isn’t it the same? – BiBi Nov 05 '18 at 12:32
  • @Jonasson: I think your answer is the better one. – stackoverflowuser2010 Jan 05 '20 at 22:15
  • @BiBi: No, they are not the same. I expanded your answer to give a more thorough explanation. Your answer produces numbers in the range `[r2, r1)`, while @Jonasson's answer produces numbers in the range `[r1, r2)`. Note that the intervals are half-open, meaning that your answer will never produce `r1` as a value, while @Jonasson's answer will. – stackoverflowuser2010 Jan 05 '20 at 22:18
  • I still don't understand why there isn't something like torch.uniform like there is is for Numpy. – Charlie Parker Jul 13 '20 at 16:06
  • idk if it's just me but I find that `torch.rand` is very bad naming. I'd have no idea if it's Gaussian or Uniform without looking at the docs (that btw take ages to load for some reason on a browser). – Charlie Parker Jul 13 '20 at 16:08
  • 1
    @stackoverflowuser2010 any single value in a continuous distribution has zero probability, so PDF's defined on a closed, open, or half open interval are [all equivalent](https://stats.stackexchange.com/questions/140805/in-the-definition-of-probability-density-function-does-it-matter-if-the-interva). – iacob Mar 12 '21 at 12:39
  • 1
    @CharlieParker [there is:](https://stackoverflow.com/a/66600118/9067615) `torch.distributions.uniform.Uniform()` – iacob Mar 12 '21 at 12:39
  • @iacob : Look at the APIs, not the math. – stackoverflowuser2010 Mar 12 '21 at 16:54
31
torch.FloatTensor(a, b).uniform_(r1, r2)
rafaelvalle
  • 6,683
  • 3
  • 34
  • 36
9

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]) 
Gaurav Shrivastava
  • 905
  • 12
  • 19
3

Please Can you try something like:

import torch as pt
pt.empty(2,3).uniform_(5,10).type(pt.FloatTensor)
Machavity
  • 30,841
  • 27
  • 92
  • 100
Sunil
  • 171
  • 2
  • 4
3

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) 
iacob
  • 20,084
  • 6
  • 92
  • 119
2

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].

2

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)))
stackoverflowuser2010
  • 38,621
  • 48
  • 169
  • 217
0

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:


Reference:

Machavity
  • 30,841
  • 27
  • 92
  • 100
Charlie Parker
  • 5,884
  • 57
  • 198
  • 323
0

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

LSgeo
  • 321
  • 3
  • 6