Smoothing one-hot encoded matrix rows

Viewed 348

Assuming that I have the following matrix consisting of one-hot encoded rows:

X = np.array([[0., 0., 0., 1., 0.], [1., 0., 0., 0., 0.], [0., 0., 1., 0., 0.]])

What I aim to do is smooth/expand the one-hot encoding in a way such that I will obtain the following output:

Y = np.array([[0., 0., 1., 1., 1.], [1., 1., 0., 0., 0.], [0., 1., 1., 1., 0.]])

assuming that I want to smooth/expand 1 element to the left or the right of the one-hot element. Thank you for the help!

3 Answers

We can use convolution -

In [22]: from scipy.signal import convolve2d

In [23]: convolve2d(X,np.ones((1,3)),'same')
Out[23]: 
array([[0., 0., 1., 1., 1.],
       [1., 1., 0., 0., 0.],
       [0., 1., 1., 1., 0.]])

With binary-dilation to be more memory-efficient -

In [43]: from scipy.ndimage.morphology import binary_dilation

In [46]: binary_dilation(X,np.ones((1,3), dtype=bool)).view('i1')
Out[46]: 
array([[0, 0, 1, 1, 1],
       [1, 1, 0, 0, 0],
       [0, 1, 1, 1, 0]], dtype=int8)

Or since we only 0s and 1s, uniform filter would also work and additionally we can use it along a generic axis (axis=1 in our case) and should be better on perf. -

In [47]: from scipy.ndimage import uniform_filter1d

In [50]: (uniform_filter1d(X,size=3,axis=1)>0).view('i1')
Out[50]: 
array([[0, 0, 1, 1, 1],
       [1, 1, 0, 0, 0],
       [0, 1, 1, 1, 0]], dtype=int8)

You could convolve X with an array of ones:

from scipy.signal import convolve2d

convolve2d(X, np.ones((1,3)), mode='same')

array([[0., 0., 1., 1., 1.],
       [1., 1., 0., 0., 0.],
       [0., 1., 1., 1., 0.]])

Solution based on standard np.convolve:

import numpy as np
np.array([np.convolve(x, np.array([1,1,1]), mode='same') for x in X])

Iterate rows using list comprehension to convolve, then convert back to np.array

Related