Compare two dimensions of the same tesnor

M2M: <p>Hi All,</p>
<p>PyTorch newbie here. I have a tensor “AAA” with 5 dimensions and the length of each dimension is 1, 2, Z, Y, X.</p>
<p>To make the question easy, let’s say we divide AAA into two tensors by the second dimension so the sizes of resulting tensors A, B would look like A = [Z, Y, X] and B = [Z, Y, X]</p>
<p>I want to check if each element is in B &gt; A (elementwise) and if each element is in B &gt; a_threashold (a scalar value).</p>
<p>If both of those conditions are true, I want this value from B and its index. Now, if we can do this in the original tensor AAA without creating two-child tensors A and B is probably more efficient I guess.</p>
<p>I can easily do this by running three nested for loops and comparing each element like</p>
<pre><code class="lang-auto">for z in range(AAA.size(dim=2)):
 for y in range(AAA.size(dim=3)):
  for x in range(AAA.size(dim=4)):
   if AAA[0, 0, z, y, x] &lt; AAA[0, 1, z, y, x] and AAA[0, 1, z, y, x]  &gt; a_threashold:
     print(str(AAA[0, 1, z, y, x]) + "index" + str(z) + "\t" + str(y) + "\t" + str(z))
</code></pre>
<p>but this is unbelievably slow (I have like 500 million floating-point numbers in AAA).</p>
<p>I was thinking of using python multiprocessing but there might be a better PyTorch way?<br>
Thank you so much!!!</p>

my3bikaht: <pre><code class="lang-auto">&gt;&gt;&gt; a = torch.ones(3,3)
&gt;&gt;&gt; a[1,1] = 0
&gt;&gt;&gt; a
tensor([[1., 1., 1.],
        [1., 0., 1.],
        [1., 1., 1.]])
&gt;&gt;&gt; b = torch.zeros(3,3)
&gt;&gt;&gt; b
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])
&gt;&gt;&gt; (a&gt;b).any()
tensor(True)
&gt;&gt;&gt; (a&gt;b).all()
tensor(False)

</code></pre>

M2M: <p>Thank you for your answer, maybe I was not clear. Let me try again</p>
<ol>
<li>Both A and B are in the same tensor</li>
<li>When I compare, I want the actual values and their indices as well. Please be kind enough to check my 5 lines of code above. Thank you <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=10" title=":slight_smile:" class="emoji" alt=":slight_smile:">
</li>
</ol>

my3bikaht: <p>What I meant is that you don’t need loops to iterate over each dimension. This is very slow indeed and numpy and pytorch have bunch of tricks to evade loops completely, like broadcasting and vectorized operations.</p>
<pre><code class="lang-auto">&gt;&gt;&gt; a = torch.ones(3,3)
&gt;&gt;&gt; a[1,1] = 0
&gt;&gt;&gt; a
tensor([[1., 1., 1.],
        [1., 0., 1.],
        [1., 1., 1.]])
&gt;&gt;&gt; b = torch.zeros(3,3)
&gt;&gt;&gt; b
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])
</code></pre>
<p>now let’s compare a and b directly:</p>
<pre><code class="lang-auto">&gt;&gt;&gt; a&gt;b
tensor([[ True,  True,  True],
        [ True, False,  True],
        [ True,  True,  True]])
</code></pre>
<p>or</p>
<pre><code class="lang-auto">&gt;&gt;&gt; torch.where(a&gt;b, a, b)
tensor([[1., 1., 1.],
        [1., 0., 1.],
        [1., 1., 1.]])
</code></pre>
<p>to get indices of where condition is True, we can use nonzero()</p>
<pre><code class="lang-auto">&gt;&gt;&gt; (a&gt;b).nonzero()
tensor([[0, 0],
        [0, 1],
        [0, 2],
        [1, 0],
        [1, 2],
        [2, 0],
        [2, 1],
        [2, 2]])
</code></pre>

M2M: <p>Thank you so much. You are right, looping took me 55 minutes (maybe because the tensor was in the GPU) when I used your method, it took me 9 seconds. I am blown away. Sorry for maybe a silly question :). Your answer is very helpful. I have last two little questions that I am missing.</p>
<ol>
<li>I want to compare b&gt;a and also b &gt; threshold (a floating-point number). As I said earlier, a and b are both in the same tensor in different channels in the second dimension.</li>
</ol>
<p>So I tried the following and It throws an error. I am stuck here.</p>
<pre><code class="lang-auto">x = AAA[0,0,:,:,:] &lt; AAA[0,1,:,:,:] and AAA[0,1,:,:,:].ge(threshold)

print(x.nonzero())
			
</code></pre>
<ol start="2">
<li>I am wondering whether the following line from the code above is safe</li>
</ol>
<pre><code class="lang-auto">x = AAA[0,0,:,:,:] &lt; AAA[0,1,:,:,:]
</code></pre>
<p>Or I should just slice the tensor first before comparison like</p>
<pre><code class="lang-auto">a = AAA[0,0,:,:,:] 

b = AAA[0,1,:,:,:]

x = a &lt; b
</code></pre>
<p>Thank you so much for the whole wonderful PyTorch community <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=10" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

my3bikaht: <aside class="quote no-group" data-username="M2M" data-post="5" data-topic="137982">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/m2m/48/33611_2.png" class="avatar"> M2M:</div>
<blockquote>
<p><code>AAA[0,0,:,:,:] &lt; AAA[0,1,:,:,:] and AAA[0,1,:,:,:].ge(threshold)</code></p>
</blockquote>
</aside>
<p>Reason for the 1st issue is that you are trying to ‘and’ two multidimensional tensors, but this operation only supported with single boolean values. You can try to use something like torch.logical_and</p>
<p>Slices are just views of original tensor, so I don’t see any harm done</p>

zilong: <p>This should work:</p>
<pre><code class="lang-auto">idxs1 = AAA[0, 1] &gt; AAA[0, 0] 
</code></pre>
<p><code>idxs</code> will be an index mask containg True and False, where True means that the condition for <code>AAA[0, 1] &gt; AAA[0, 0]</code> holds. So you would access those values by <code>AAA[idxs]</code></p>
<p>the same should work for the other condition:</p>
<pre><code class="lang-auto">idxs2 = AAA[0, 1] &gt; threshold 
</code></pre>
<p>To get the indexes where it holds for both you would do</p>
<pre><code class="lang-auto">idxs3 = idxs1 &amp; idxs2
</code></pre>
<p>or</p>
<pre><code class="lang-auto">idxs3 = torch.logical_and(idxs1, idxs2)
</code></pre>

J_Johnson: <p>When using Logical Operators in Python, you must define the order of operations through parentheses when there is more than one operation involved. If you’re getting an error, it is probably because Python can’t figure out the order in which you want the operations performed. Additionally, depending on what you are trying to accomplish, you may need two logical operators in your statement.</p>
<p>For instance, try:</p>
<pre><code class="lang-auto">x=(A[0,0,:,:,:] &gt; A[0,1,:,:,:]) &amp; (A[0,0,:,:,:] &gt; A[0,1,:,:,:].ge(0.5))
</code></pre>