Equivalent function like `numpy.diff` in pytorch?

username: HappyPants
cooked: <p>Greetings, I am relatively new to pytorch (also not very familiar with manipulating tensors) and I am trying to implement a function with the same behavior as <code>numpy.diff</code> (<a href="https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.diff.html" rel="nofollow noopener">https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.diff.html</a>). I would like that this function works only with torch Tensors. After looking at the documentation, it doesn’t seems like pytorch as a function that have the same behavior… Is there an equivalent function that I missed ? if None exist, how would your implement such function ?</p>
<p>Ultimately, I am trying to implement a loss function weighted by Mean Directional Accuracy (MDA)(<a href="https://en.wikipedia.org/wiki/Mean_Directional_Accuracy" rel="nofollow noopener">https://en.wikipedia.org/wiki/Mean_Directional_Accuracy</a>).</p>
<p>For example, the numpy version of it is as follows:</p>
<pre><code class="lang-auto">def diff(a, n=1, axis=-1):
    if n == 0:
        return a
    if n &lt; 0:
        raise ValueError(
            "order must be non-negative but got " + repr(n))

    a = asanyarray(a)
    nd = a.ndim
    axis = normalize_axis_index(axis, nd)

    slice1 = [slice(None)] * nd
    slice2 = [slice(None)] * nd
    slice1[axis] = slice(1, None)
    slice2[axis] = slice(None, -1)
    slice1 = tuple(slice1)
    slice2 = tuple(slice2)

    op = not_equal if a.dtype == np.bool_ else subtract
    for _ in range(n):
        a = op(a[slice1], a[slice2])

    return a

&gt;&gt;&gt; x = np.array([1, 2, 4, 7, 0])
&gt;&gt;&gt; np.diff(x)
#array([ 1,  2,  3, -7])
</code></pre>

username: ptrblck
cooked: <p>I think indexing should just work:</p>
<pre><code class="lang-python">x = torch.tensor([1, 2, 4, 7, 0])
x_diff = x[1:] - x[:-1]
print(x_diff)
&gt; tensor([ 1,  2,  3, -7])
</code></pre>

username: JaydeepRade_JD
cooked: <p>How to get the same shape output?</p>

username: oli4100
cooked: <p>Below a solution to keep the same shape when computing first differences across the last dimension by padding zeros at the front.</p>
<pre><code class="lang-auto">import torch.nn.functional as F
t = torch.rand((10, 10, 10))
diff = t - F.pad(t, (1, 0))[:, :, :-1]
</code></pre>
<p>Note 1: you can also create a Conv layer with a 2 sized kernel with fixed weights [-1, 1], but that comes down to the same thing.<br>
Note 2: Don’t know if this is optimal in terms of speed, I know it’s faster than using a concatenation. Happy to learn when someone has a faster option <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

username: saba
cooked: <p>Hi Ptrblck</p>
<p>Sorry to take your time. I am using Matlab to find the coordinate so f specific value in 3 Diment by "<br>
[XX,YY,ZZ]=ind2sub(size(SWITHresholedOutPut),find(SWITHresholedOutPut==1));</p>
<p>I want to do same thing in pytorch, means find the coordinate of specific value in 3 dimension.</p>
<p>What is the best option?</p>

username: ptrblck
cooked: <p>Would this work for you?</p>
<pre><code class="lang-python">x = torch.arange(4*5*6).view(4, 5, 6)
idx = (x == 82).nonzero()
</code></pre>

username: Hemlata
cooked: <p>Hi Ptrblck</p>
<p>I want to compute instantaneous frequency (IF) from hilbert transform using pytorch.<br>
Currently, I am using Matlab for this task.</p>
<p>Matlab script:</p>
<pre><code class="lang-python">[x,fs]=audioread('waveform');

for i = 1:length(sinc_filter)
    C(i,:) = conv(x,sinc{i},'same');
    HT(i,:)=(hilbert(C(i,:)));
    instfreq (i,:)= abs(fs/(2*pi)*diff(unwrap(angle(HT(i,:)))));
end

</code></pre>
<p>I want to do the same thing in pytorch.</p>
<p>I didn’t find hilbert and unwrape function in pytorch.</p>
<p>I tried using numpy but that’s taking lot of time for computing instantaneous frequency for each mini-batch.</p>
<p>python script using numpy:</p>
<pre><code class="lang-auto">#no. of sinc filters=21
#filter_length=128
#mini-batch size=8
#self.filters size is [1,no. of sinc filters, filter_length]
# Filter is sinc filters with size [batch_size, no. of sinc filter, audio samples(64000 samples)]. 

Filter=F.conv1d(waveforms, self.filters, stride=self.stride,
                        padding=self.padding, dilation=self.dilation,
                         bias=None, groups=1) 

self.Filter=Filter

fs=16000

FILTER_1=self.Filter.cpu().detach().numpy()  

inst_freq=np.zeros((self.Filter.shape[0],self.Filter.shape[1],Filter.shape[2]-1))  # intialized inst_freq matrix

# 1st for loop to compute IF for each filter and 2nd for loop is for each audio wave in mini-batch.
# j range from 0 to 20.
# i range from 0 to 7.


for j in range(self.Filter.shape[1]):
    for i in range(self.Filter.shape[0]):
        z= hilbert(FILTER_1[i,j,:])
        inst_phase = np.unwrap(np.angle(z))
        inst_freq[i,j,:] = np.diff(inst_phase)/(2*np.pi)*fs 
                
  
Main_filt=torch.from_numpy(inst_freq).type(torch.float).to(self.device)

</code></pre>
<p>But its taking lot of time for IF computation.</p>
<p>Is there any way to do this things in pytorch.</p>
<p>Please let me know what is the best option to do this operations for IF computation in pytorch.<br>
your suggestions would be really useful for me.</p>
<p>Thanks in advance.</p>

username: ptrblck
cooked: <p>Based on the code it seems you would need to port the <code>hilbert</code> transformation and <code>unwrap</code> to PyTorch to avoid using <code>scipy</code> and <code>numpy</code> on the CPU.<br>
I had a quick look at the source code for <a href="https://github.com/scipy/scipy/blob/v1.5.2/scipy/signal/signaltools.py#L2036-L2144"><code>hilbert</code></a> and <a href="https://github.com/numpy/numpy/blob/v1.19.0/numpy/lib/function_base.py#L1487-L1541"><code>unwrap</code></a> and I think all needed operations are implemented in PyTorch, so that you could try to port these methods directly.</p>