How to remove infinity values from a tensor in tensorflow? - python

Say I have a tensor as following :
var = tf.constant([0,0.05,0.2,0,0])
inverse_var = tf.math.reciprocal(var)
print(inverse_var)
Output : tf.Tensor([inf, 20. , 5. ,inf inf], shape=(5,), dtype=float32)
I want to make a new tensor from inverse_var tensor such that the infinity values are replaced with zero in the new tensor.
Final vector required - [ 0, 20, 5, 0, 0 ]

Here is a solution done using tf.tensor_scatter_nd_update method
import tensorflow as tf
var = tf.constant([0,0.05,0.2,0,0])
inverse_var = tf.math.reciprocal(var)
print(inverse_var)
mask = tf.math.is_inf(inverse_var)
indices = tf.where(mask) # found indices where infinite values are
print(indices)
updates=tf.zeros(len(indices)) # create 1D matrix of length of infinite values
inverse_var_inf = tf.tensor_scatter_nd_update(inverse_var,indices,updates) #updated using scatter_nd_update method
print(inverse_var_inf)
Thank you!
providing gist for reference

Related

Finding indices at multiple locations in a Tensor at runtime and replacing it with 0

I wish to assign 0 to multiple locations in a Tensor of size = (n,m) at runtime.
I computed the indices using the where clause in Tensorflow, and called the scatter_nd_update function in order to assign a tf.constant(0) at the newly found multiple locations.
oscvec = tf.where(tf.math.logical_and(sgn2 > 0, sgn1 < 0))
updates = tf.placeholder(tf.float64, [None, None])
oscvec_empty = tf.placeholder(tf.int64, [None])
tf.cond(tf.not_equal(tf.size(oscvec), 0), tf.scatter_nd_update(save_parms, oscvec, tf.constant(0, dtype=tf.float64)),
tf.scatter_nd_update(save_parms, oscvec_empty, updates))
I will expect tf.where returns an empty tensor when the condition if not satisfied, and a non-empty tensor of indices for save_parms at some point. I decided to create and empty oscvec_empty tensor to deal with cases where the result for tf.where returns an empty tensor. But this does not seem to work....as seen from the following error which is generated when the Tensorflow if-else condition - tf.cond - is used to update save_parms parameter tensor via the tf.scatter_nd_update function:
ValueError: Shape must be at least rank 1 but is rank 0 for 'ScatterNdUpdate' (op: 'ScatterNdUpdate') with input shapes: [55], [?,1], [].
Is there a way to replace values at multiple locations in the save_parms tensor when oscvec is non-empty and not do so, when oscvec is empty? The sgn tensor corresponds to the result of sign function applied on save_parms based on a given criterion.
You can use tf.where() instead of such a complex approach in question.
import tensorflow as tf
vec1 = tf.constant([[ 0.05734377, 0.80147606, -1.2730557 ], [ 0.42826906, 1.1943488 , -0.10129673]])
vec2 = tf.constant([[ 1.5461133 , -0.38455755, -0.79792875], [ 1.5374309 , -1.5657802 , 0.05546811]])
sgn1 = tf.sign(vec1)
sgn2 = tf.sign(vec2)
save_parms = tf.random_normal(shape=sgn1.shape)
oscvec = tf.where(tf.math.logical_and(sgn2 > 0, sgn1 < 0),tf.zeros_like(save_parms),save_parms)
with tf.Session() as sess:
save_parms_val, oscvec_val = sess.run([save_parms, oscvec])
print(save_parms_val)
print(oscvec_val)
[[ 0.75645643 -0.646291 -1.2194813 ]
[ 1.5204562 -1.0625905 2.9939709 ]]
[[ 0.75645643 -0.646291 -1.2194813 ]
[ 1.5204562 -1.0625905 0. ]]

Masking a 2D array and operating on second array based off masked indices

I have a function that reads in and outputs a 2D array. I want the output to be constant (pi in this case) for every index in the input that equals 0, otherwise I perform some maths on it. E.g:
import numpy as np
import numpy.ma as ma
def my_func(x):
mask = ma.where(x==0,x)
# make an array of pi's the same size and shape as the input
y = np.pi * np.ones(x)
# psuedo-code bit I can't figure out
y.not_masked = y**2
return y
my_array = [[0,1,2],[1,0,2],[1,2,0]]
result_array = my_func(my_array)
This should give me the following:
result_array = [[3.14, 1, 4],[1, 3.14, 4], [1, 4, 3.14]]
I.e. it has applied y**2 to each element in the 2D list that doesn't equal zero, and replaced all the zeros with pi.
I need this because my function will include division, and I don't know the indexes beforehand. I'm trying to convert a matlab tutorial from a textbook into Python and this function is stumping me!
Thanks
Just use np.where() directly:
y = np.where(x, x**2, np.pi)
Example:
>>> x = np.asarray([[0,1,2],[1,0,2],[1,2,0]])
>>> y = np.where(x, x**2, np.pi)
>>> print(y)
[[ 3.14159265 1. 4. ]
[ 1. 3.14159265 4. ]
[ 1. 4. 3.14159265]]
Try this:
my_array = np.array([[0,1,2],[1,0,2],[1,2,0]]).astype(float)
def my_func(x):
mask = x == 0
x[mask] = np.pi
x[~mask] = x[~mask]**2 # or some other operation on x...
return x
I would suggest rather than using masks you can use a boolean array to achieve what you want.
def my_func(x):
#create a boolean matrix, a, that has True where x==0 and
#False where x!=0
a=x==0
x[a]=np.pi
#Use np.invert to flip where a is True and False so we can
#operate on the non-zero values of the array
x[~a]=x[~a]**2
return x #return the transformed array
my_array = np.array([[0.,1.,2.],[1.,0.,2.],[1.,2.,0.]])
result_array = my_func(my_array)
this gives the output:
array([[ 3.14159265, 1. , 4. ],
[ 1. , 3.14159265, 4. ],
[ 1. , 4. , 3.14159265]])
Notice that I passed to the function an numpy array specifically, originally you passed a list and that will give problems when you attempt to do mathematical operations. Also notice I defined the array with 1. rather than just 1, in order to make sure it was an array of floats rather than integers, because if it is an array of integers when you set values equal to pi it will truncate to 3.
Perhaps it would be good to add a piece to the function to check the dtype of the input argument and see if it is a numpy array rather than a list or other object, and also to make sure it contains floats, and if not you can adjust accordingly.
EDIT:
Change to using ~a rather than invert(a) as per Scotty1's suggestion.

python, tensorflow, how to get a tensor shape with half the features

I need the shape of a tensor, except instead of feature_size as the -1 dimension I need feature_size//2
The code I'm currently using is
_, half_output = tf.split(output,2,axis=-1)
half_shape = tf.shape(half_output)
This works but it's incredibly inelegant. I don't need an extra copy of half the tensor, I just need that shape. I've tried to do this other ways but nothing besides this bosh solution has worked yet.
Anyone know a simple way to do this?
A simple way to get the shape with the last value halved:
half_shape = tf.shape(output[..., 1::2])
What it does is simply iterate output in its last dimension with step 2, starting from the second element (index 1).
The ... doesn't touch other dimensions. As a result, you will have output[..., 1::2] with the same dimensions as output, except for the last one, which will be sampled like the following example, resulting in half the original value.
>>> a = np.random.rand(5,5)
>>> a
array([[ 0.21553665, 0.62008421, 0.67069869, 0.74136913, 0.97809012],
[ 0.70765302, 0.14858418, 0.47908281, 0.75706245, 0.70175868],
[ 0.13786186, 0.23760233, 0.31895335, 0.69977537, 0.40196103],
[ 0.7601455 , 0.09566717, 0.02146819, 0.80189659, 0.41992885],
[ 0.88053697, 0.33472285, 0.84303012, 0.10148065, 0.46584882]])
>>> a[..., 1::2]
array([[ 0.62008421, 0.74136913],
[ 0.14858418, 0.75706245],
[ 0.23760233, 0.69977537],
[ 0.09566717, 0.80189659],
[ 0.33472285, 0.10148065]])
This half_shape prints the following Tensor:
Tensor("Shape:0", shape=(3,), dtype=int32)
Alternatively you could get the shape of output and create the shape you want manually:
s = output.get_shape().as_list()
half_shape = tf.TensorShape(s[:-1] + [s[-1] // 2])
This half_shape prints a TensorShape showing the shape halved in the last dimension.

numpy.diff returning an empty array?

#python 3.6.3
import numpy as np
time_C0002A/1000
array([[-0.99925 ],
[-0.99925 ],
[-0.99925 ],
...,
[ 0.0181095],
[ 0.0195675],
[ 0.0205931]])
Fs_log = 1 / np.diff(time_C0002A/1000)
When I enter it in to see what it returns, it is given as an empty array
Fs_log
array([], shape=(9063,0), dtype = float64)
I am expecting an array to be returned and have confirmed with a different example, any idea what could be occurring and how I should remedy this? i believe it is an issue with the axis along which diff is taken but I am not sure what it should be defined as, example:
np.diff(time_C0002A/1000, axis = 0)
But I am not sure? Input appreciated!
Your time_C0002A array has a shape of (n,1). np.diff take the difference over the last axis by default, in your case of length 1. You can specify the axis as an argument.
np.diff(time_C0002A/1000, axis=0)

Error with Padlen in signal.filtfilt in Python

I am working with library "scipy.signal" in Python and I have the next code:
from scipy import signal
b = [ 0.001016 0.00507999 0.01015998 0.01015998 0.00507999 0.001016 ]
a = [ 1. -3.0820186 4.04351697 -2.76126457 0.97291013 -0.14063199]
data = [[ 1.]
[ 1.]
[ 1.]
...]
# length = 264
y = signal.filtfilt(b, a, data)
But when I execute the code I get the next error message:
The length of the input vector x must be at least padlen, which is 18.
What could I do?
It appears that data is a two-dimensional array with shape (264, 1). By default, filtfilt filters along the last axis of the input array, so in your case it is trying to filter along an axis where the length of the data is 1, which is not long enough for the default padding method.
I assume you meant to interpret data as a one-dimensional array. You can add the argument axis=0
y = signal.filtfilt(b, a, data, axis=0)
to filter along the first dimension (i.e. down the column), in which case the output y will also have shape (264, 1). Alternatively, you can convert the input to a one-dimensional array by flattening it with np.ravel(data) or by using indexing to select the first (and only) column, data[:, 0]. (The latter will only work if data is, in fact, a numpy array and not a list of lists.) E.g.
y = signal.filtfilt(b, a, np.ravel(data))
In that case, the output y will also be a one-dimensional array, with shape (264,).
Assuming you have a two-dimensional array with shape (264, 2), you can also use np.hsplit() to split data into two separate arrays like so:
import numpy as np
arr1, arr2 = np.hsplit(data,2)
You can view the shape of each individual array, for example:
print(arr1.shape)
Your code will then look something like this:
y1 = signal.filtfilt(b, a, arr1)
y2 = signal.filtfilt(b, a, arr2)

Categories