Shuffling a Tensor

username: brookisme
cooked: <p>Hi Everyone -</p>
<p>Is there a way to shuffle/randomize a tensor.  Something equivalent to numpy’s <a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.shuffle.html" rel="nofollow noopener"><code>random.shuffle</code></a>.</p>
<p>Thanks!</p>

username: asml
cooked: <p>Just index with a tensor of random indices.</p>

username: ptrblck
cooked: <p>You could use <code>torch.randperm</code> to create random indices and then index it using <a class="mention" href="/u/asml">@asml</a>’s suggestion.</p>

username: brookisme
cooked: <p><a class="mention" href="/u/asml">@asml</a> , <span class="mention">@ptrbick</span> - thanks both.  is something like this</p>
<pre><code class="lang-auto">t=torch.tensor([[1,2],[3,4]])
r=torch.randperm(2)
c=torch.randperm(2)
t=t[r][:,c]
</code></pre>
<p>The most elegant solution? Its simple enough but the indexing in <code>t[r][:,c]</code> feels a bit odd</p>

username: ptrblck
cooked: <p>You could merge the indexing or use <code>view</code> instead:</p>
<pre><code class="lang-python">t=torch.tensor([[1,2],[3,4]])
r=torch.randperm(2)
c=torch.randperm(2)
t=t[r[:, None], c]

# With view
idx = torch.randperm(t.nelement())
t = t.view(-1)[idx].view(t.size())
</code></pre>

username: brookisme
cooked: <p>Oh smart – I like the <code>.view()</code> solution, especially since <code>nbelement</code> and <code>size</code> are fixed. The merged-indexing is nice but probably no less awkward than my first go.<br>
Thanks again!</p>

username: victor1
cooked: <p>Don’t do this, it is not a real random transformation!</p>
<p>indeed:<br>
The number of possible transformations for a N x N square matrix: (N*N)!<br>
Or, with two permutations of the lines and the columns as you do, there are (N!)*(N!) possible transformation<br>
And (N*N)! is far higher than (N!)*(N!) when N is high…<br>
with you code, the matrix</p>
<pre><code class="lang-auto">t=torch.tensor([[1,2],[3,4]])
</code></pre>
<p>will never be randomized into</p>
<pre><code class="lang-auto">t=torch.tensor([[1,4],[2,3]])
</code></pre>
<p>Use the code of <a class="mention" href="/u/ptrblck">@ptrblck</a> with the view, it is a good one <img src="https://discuss.pytorch.org/images/emoji/apple/wink.png?v=6" title=":wink:" class="emoji" alt=":wink:"></p>

username: tsap
cooked: <p>Hello,<br>
If we want  to shuffle the order of image database (format: [batch_size, channels, height, width]), I think this is a good method:</p>
<pre><code class="lang-auto">t = torch.rand(4, 2, 3, 3)
idx = torch.randperm(t.shape[0])
t = t[idx].view(t.size())
</code></pre>
<p><code> t[idx]</code> will retain the structure of channels, height, and width, while shuffling the order of the image.</p>

username: ncuxomun
cooked: <p>Exactly what I was looking for. Thanks, mate!</p>

username: InfT
cooked: <p>This code works, but the result changes at every run. How can I make it deterministic?</p>

username: ptrblck
cooked: <p>Seed the pseudorandom number generator via <code>torch.manual_seed(SEED)</code> before using the random operation.</p>

username: YannDubs1
cooked: <p>If it’s on CPU then the simplest way seems to be just converting the tensor to numpy array and use in place shuffling :</p>
<pre><code class="lang-auto">t = torch.arange(5)             
np.random.shuffle(t.numpy())
print(t) 
# tensor([0, 2, 3, 1, 4])
</code></pre>

username: HashRocketSyntax
cooked: <p>For numpy parity, it would be handy to have <code>torch.shuffle()</code></p>

username: HashRocketSyntax
cooked: <p>For batch-first shuffling:</p>
<pre><code class="lang-python">tzr = torch.tensor([
    [[1],[1],[1]],
    [[2],[2],[2]],
    [[3],[3],[3]],
    [[4],[4],[4]],
])

rand_indx = torch.randperm(len(tzr))

tzr[rand_indx]
</code></pre>
<p>returns</p>
<pre><code class="lang-auto">tensor([
    [[3], [3], [3]],
    [[4], [4], [4]],
    [[2], [2], [2]],
    [[1], [1], [1]]
])
</code></pre>