How to broadcast across 3d tensor in theano? - python

If I have a 3d tensor block B and I would like to set some of its "faces" to 0 with probability 0.5. Here axis 1 are rows, axis 2 are columns, and axis 3 are the "faces". I have tried
size = (B.shape[1], 1, 1)
noise = self.theano_rng.binomial(size=size, n=1, p=0.5)
return noise * B
But this isn't working, the shapes aren't lining up and I get an error.
For example, I would like
2 2 2 2 2 2
3 3 3 3 3 3
4 4 4 4 4 4
* [1 0] ->
6 6 6 0 0 0
7 7 7 0 0 0
8 8 8 0 0 0

You can use dimshuffle to add the dimensions necessary to enable broadcasting.
Here's a working example:
import numpy
import theano
import theano.tensor as tt
x = tt.tensor3()
y = tt.bvector()
z = x * y.dimshuffle(0, 'x', 'x')
f = theano.function([x, y], z)
x_value = numpy.array([[[2, 2, 2], [3, 3, 3], [4, 4, 4]],
[[6, 6, 6], [7, 7, 7], [8, 8, 8]]], dtype=theano.config.floatX)
y_value = numpy.array([1, 0], dtype=numpy.int8)
print f(x_value, y_value)
which prints
[[[ 2. 2. 2.]
[ 3. 3. 3.]
[ 4. 4. 4.]]
[[ 0. 0. 0.]
[ 0. 0. 0.]
[ 0. 0. 0.]]]

Related

Python - Divide each row by a vector

I have a 10x10 matrix and I want to divide each row of the matrix with the elements of a vector.
For eg:
Suppose I have a 3x3 matrix
1 1 1
2 2 2
3 3 3
and a vector [1, 2, 3]
Then this is the operation I wish to do:
1/1 1/2 1/3
2/1 2/1 2/3
3/1 3/2 3/3
i.e, divide the elements of a row by the elements of a vector(A python list)
I can do this using for loops. But, is there a better way to do this operation in python?
You should look into broadcasting in numpy. For your example this is the solution:
a = np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3]])
b = np.array([1, 2, 3]).reshape(1, 3)
c = a / b
print(c)
>>> [[1. 0.5 0.33333333]
[2. 1. 0.66666667]
[3. 1.5 1. ]]
The first source array should be created as a Numpy array:
a = np.array([
[ 1, 1, 1 ],
[ 2, 2, 2 ],
[ 3, 3, 3 ]])
You don't need to reshape the divisor array (it can be a 1-D array,
as in your source data sample):
v = np.array([1, 2, 3])
Just divide them:
result = a / v
and the result is:
array([[1. , 0.5 , 0.33333333],
[2. , 1. , 0.66666667],
[3. , 1.5 , 1. ]])

numpy first non zero value of vectors in a multi dimentional array

I have a 3dimensional numpy ndarray shaped (i,j,k) where each row is an array of multiple similarly sized vectors.
I would like to extract an (i,k) shaped array such that each element of the rows contains the first non-zero element of its group of "j" vectors
So basically, given an array such as:
[
[
[0 , 10 , 12 , 0 , 4],
[0 , 0 , 13 , 1 , 2],
[12, 14 , 1 , 12 , 8]
],
[
[5 , 17 , 12 , 9 , 0],
[0 , 0 , 13 , 1 , 0],
[12, 14 , 1 , 12 , 8]
],
[
[0 , 0 , 19 , 0 , 9],
[2 , 6 , 13 , 0 , 2],
[12, 14 , 1 , 12 , 8]
]
]
Im looking to find something like:
[
[12, 10, 12, 1, 4],
[5 , 17, 12, 9, 8],
[2 , 6, 19, 12, 9]
]
how to find the results efficiently?
import numpy as np
i,j,k = 3, 5, 10 #in real problem, these are pretty large
arr = np.random.randint(0, 10000, (i,j,k))
#????????
Using a simple transpose https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html and advanced indexing https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#advanced-indexing, the solution looks like this:
import numpy as np
a = np.array([
[
[0 , 10 , 12 , 0 , 4],
[0 , 0 , 13 , 1 , 2],
[12, 14 , 1 , 12 , 8]
],
[
[5 , 17 , 12 , 9 , 0],
[0 , 0 , 13 , 1 , 0],
[12, 14 , 1 , 12 , 8]
],
[
[0 , 0 , 19 , 0 , 9],
[2 , 6 , 13 , 0 , 2],
[12, 14 , 1 , 12 , 8]
]
])
# swapping the 0 and 1 axes, to make the rest of the code easier
a = a.transpose((1, 0, 2))
# initialising result to zeroes, same shape as a single layer of the transposed a
result = np.zeros(a[0].shape, np.int32)
# one layer at a time
for layer in a:
# as soon as result contains no more zeroes, done
if len(result[result == 0]) == 0:
break
else:
# replace all values of result that are zero
# with values from the same location in layer
result[result == 0] = layer[result == 0]
print(result)
Prints:
[[12 10 12 1 4]
[ 5 17 12 9 8]
[ 2 6 19 12 9]]
This is not the most elegant way to do it, as I wrote it rather quickly on the fly. However, hopefully this is sufficient enough to get you started.
def find_non_zero(lst):
for num in lst:
if num != 0:
return num
First, we define a very simple helper function, find_non_zero, which receives a one-dimensional list as input and returns the first non-zero entry. This function is then used when we loop over each columns of the two-dimensional array in arrays, the three-dimensional input array provided.
import numpy as np
arrays = [
[
[0 , 10 , 12 , 0 , 4],
[0 , 0 , 13 , 1 , 2],
[12, 14 , 1 , 12 , 8]
],
[
[5 , 17 , 12 , 9 , 0],
[0 , 0 , 13 , 1 , 0],
[12, 14 , 1 , 12 , 8]
],
[
[0 , 0 , 19 , 0 , 9],
[2 , 6 , 13 , 0 , 2],
[12, 14 , 1 , 12 , 8]
]
]
final_result = []
for array in arrays:
array = np.array(array).T
final_result.append([find_non_zero(col) for col in array])
print(final_result)
This yields the following output.
[[12, 10, 12, 1, 4], [5, 17, 12, 9, 8], [2, 6, 19, 12, 9]]
Numpy's .T tranpose operator comes in handy because it allows us to loop through two-dimensional arrays by columns, instead of the default row. For more information on the transpose operator, read the official documentation.
I'd be happy to answer any additional questions you might have.
Use apply along axis and then apply the function nonzero and get first element in desired axis
np.apply_along_axis(lambda e: e[np.nonzero(e)][0], 1, x)
OR
np.apply_along_axis(lambda e: e[(e!=0).argmax()], 1, x)
Output
array([[12, 10, 12, 1, 4],
[ 5, 17, 12, 9, 8],
[ 2, 6, 19, 12, 9]])

How do I get the minimum of certain elements of an array with Python?

I need to know the minimum element of a data for certain elements in an iterating array.
I have three array dist, Q and vertex:
dist = [ 0. inf inf inf inf]
vertex = [2 4 5 7 8]
Q = [2 4 5 7 8]
The dist array are the vertex values. Each iteration Q decreases and dist has different values. For example:
First iteration:
dist = [ 0. inf inf inf inf]
vertex = [2 4 5 7 8]
Q = [2 4 5 7 8]
Second iteration:
dist = [ 0. 4. 2. 2. 1.]
vertex = [2 4 5 7 8]
Q = [4 5 7 8]
Third iteration
dist = [ 0. 4. 2. 2. 1.]
vertex = [2 4 5 7 8]
Q = [4 5 7]
The idea is to find the minimum of dist but only of the available values of Q in vertex. In the first iteration the minimum is 0 because they are all in Q. In the second iteration the minimum 1, that is to say the 8 in vertex, because in Q there is not the 4 that has value 0 in dist.
This is a part of the Dijkstra algorithm in which it finds the minimum of the values of Q. In pseudocode it would be:
u ← vertex in Q with min dist[u] // Node with the least distance
I'm just using the Numpy library.
My solution so far:
min = np.inf
u = 0
for q in Q:
if dist[self.vertex == q] <= min:
min = dist[self.vertex == q]
u = q
Little trick: add ∞ if the vertex is not in Q:
>>> dist = [ 0., 4., 2., 2., 1.]
>>> vertex = [2, 4, 5, 7, 8]
>>> Q = [4, 5, 7]
>>> vertex_mask = np.array([0 if x in Q else float('inf') for x in vertex])
>>> np.min(vertex_mask+dist)
2.0

Division with numpy matrices that might result in nan

How can I divide two numpy matrices A and B in python when sometimes the two matrices will have 0 on the same cell?
Basically A[i,j]>=B[i,j] for all i, j. I need to calculate C=A/B. But sometimes A[i,j]==B[i,j]==0. And when this happens I need A[i,j]/B[i,j] to be defined as 0.
Is there a simple pythonic way other than going through all the indexes?
You can use the where argument for ufuncs like np.true_divide:
np.true_divide(A, B, where=(A!=0) | (B!=0))
In case you have no negative values (as stated in the comments) and A >= B for each element (as stated in the question) you can simplify this to:
np.true_divide(A, B, where=(A!=0))
because A[i, j] == 0 implies B[i, j] == 0.
For example:
import numpy as np
A = np.random.randint(0, 3, (4, 4))
B = np.random.randint(0, 3, (4, 4))
print(A)
print(B)
print(np.true_divide(A, B, where=(A!=0) | (B!=0)))
[[1 0 2 1]
[1 0 0 0]
[2 1 0 0]
[2 2 0 2]]
[[1 0 1 1]
[2 2 1 2]
[2 1 0 1]
[2 0 1 2]]
[[ 1. 0. 2. 1. ]
[ 0.5 0. 0. 0. ]
[ 1. 1. 0. 0. ]
[ 1. inf 0. 1. ]]
As alternative: Just replace nans after the division:
C = A / B # may print warnings, suppress them with np.seterrstate if you want
C[np.isnan(C)] = 0
You could use a mask with np.where to choose between such a case of A and B being both zeros and otherwise and put out 0 or an elementwise division respectively -
from __future__ import division # For Python 2.x
mask = (A == B) & (A==0)
C = np.where(mask, 0, A/B)
About the mask creation : (A==B) would be the mask of all elements that are equal between A and B and with (A==0) we have a mask of all elements that are zero in A. Thus, with a combined mask of (A == B) & (A==0), we have mask of places where both A and B are zeros. A more simpler version to do the same task and maybe easier to understand would be to check for zeros in both A and B and it would be :
mask = (A==0) & (B==0)
About the use of np.where, its syntax is :
C = np.where(mask, array1, array2)
i.e. we would select elements for assinging into C based on the mask. If the corresponding mask element is True, we pick the corresponding element from array1, else from array2. This is done on elementwise level and thus, we have the output C.
Sample run -
In [48]: A
Out[48]:
array([[4, 1, 4, 0, 3],
[0, 4, 1, 4, 3],
[1, 0, 0, 4, 0]])
In [49]: B
Out[49]:
array([[4, 2, 2, 1, 4],
[2, 1, 2, 4, 2],
[4, 0, 2, 0, 3]])
In [50]: mask = (A == B) & (A==0)
In [51]: np.where(mask, 0, A/B)
Out[51]:
array([[ 1. , 0.5 , 2. , 0. , 0.75],
[ 0. , 4. , 0.5 , 1. , 1.5 ],
[ 0.25, 0. , 0. , inf, 0. ]])

convert 1d array to 2d array with nan values

suppose I have a series like this
S1 = Series([[1 , 2 , 3] , [4 , 5 , 6] , np.nan , [0] , [8 ,9 ]])
0 [1, 2, 3]
1 [4, 5, 6]
2 NaN
3 [0]
4 [8, 9]
then I will create a numpy array from this series
arr1d = S1.values # [[1, 2, 3] [4, 5, 6] nan [0] [8, 9]]
print(arr1d.shape) #(5L,)
print(arr1d.ndim) # 1
is it possible to create a 2d array from arr1d that looks like the following
arr2d = np.array([[1 , 2 , 3 ] , [4 , 5 , 6] ,
[np.nan , np.nan , np.nan] , [0 , np.nan , np.nan] , [8 , 9 , np.nan]])
this is how the 2d array looks like
[[ 1. 2. 3.]
[ 4. 5. 6.]
[ nan nan nan]
[ 0. nan nan]
[ 8. 9. nan]]
print(arr2d.ndim) # 2
print(arr2d.shape) # (5L, 3L)
the solution should work dynamically with any number of elements in arr1d this is just an example of how the data may look like
Not claiming efficiency but this should work:
from itertools import zip_longest
arr2d = np.array(list(zip_longest(*np.atleast_1d(*S1), fillvalue=np.nan))).T
print(arr2d)
print(arr2d.shape)
Output:
[[ 1. 2. 3.]
[ 4. 5. 6.]
[ nan nan nan]
[ 0. nan nan]
[ 8. 9. nan]]
(5, 3)

Categories