Adding numpy arrays - python

How can I add a small numpy array to a part of big numpy array?
My code is like:
import numpy as np
x = np.ones((10, 15))
I want to add a 3 by 3 np array to the middle or some location that I can designate.

If by adding you mean assigning values from 3x3 matrix into your x matrix, then you can assign it to the slice of your x matrix. Example -
x[row:row+3,col:col+3] = np.array([[1,2,3],[4,5,6],[7,8,9]]) #Your 3x3 array on right side.
Demo -
In [98]: x = np.ones((10,15))
In [99]: x[3:6,3:6] = np.array([[1,2,3],[4,5,6],[7,8,9]])
In [100]: x
Out[100]:
array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 2., 3., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 4., 5., 6., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 7., 8., 9., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1.]])
If by add, you meant to add the values up at the corresponding indexes, you can use += in the above slicing assignment. Example -
x[row:row+3,col:col+3] += np.array([[1,2,3],[4,5,6],[7,8,9]]) #Your 3x3 array on right side.

Related

For a binary array sum(array) and numpy.count_nonzero(array) give different answers for big arrays, when array is uint8. Why?

I have 3D arrays filled with ones and zeros (created through pyellipsoid). The array is uint8. I wanted to know the number of 1s. I used sum(sum(sum(array))) to do this and it worked fine for small arrays (up to approx.5000 entries).
I compared sum(sum(sum(array))) to numpy.count_nonzero(array) for a known number of nonzero entries. For bigger arrays the answers from "sum" are always wrong and lower than they should be.
If I use float64 arrays it works fine with big arrays. If I change the data type to uint8 it does not work.
Why is that? I am sure there is a very simple reason, but I can't find an answer.
Small array example:
test = numpy.zeros((2,2,2))
test[0,0,0] = 1
test[1,0,0] = 1
In: test
Out:
array([[[1., 0.],
[0., 0.]],
In: sum(sum(sum(test)))
Out: 2.0
Big example (8000 entries, only one zero, 7999 ones):
test_big=np.ones((20,20,20))
test_big[0,0,0] = 0
test_big
Out[77]:
array([[[0., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
...,
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.]],
[[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
...,
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.]],
[[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
...,
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.]],
...,
[[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
...,
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.]],
[[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
...,
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.]],
[[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
...,
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.]]])
In: sum(sum(sum(test_big)))
Out: 7999.0
So far so good. Here, the data type of the sum output is float64. But if I now change the data type of the array to the type that is used with pyellipsoid (uint8)...
In: test_big = test_big.astype('uint8')
In: sum(sum(sum(test_big)))
Out: 2879
So obviously 2879 is not 7999. Here, the data type of the sum output is int32 (-2147483648 to 2147483647) so this should be big enough for 7999, right? I guess it has something to do with the data type, but how? Why?
(I am using Spyder in Anaconda on Windows).
The issue is as you guessed - there is an integer overflow. If you take a look at sum(sum(test_big)), you will notice that the values are wrong there.
The part that is wrong is that integer overflow can occur in your sum() functions which are taking the partial sums.
What I would suggest is making a sum of this array using np.sum() as it does give an appropriate sum despite of data type.

Keras how to force zero gamma initialization for BatchNormalization for downloaded models

I'd like to change default gamma initialization for BatchNormalization layers for downloaded models.
For example:
I have a downloaded EfficientNetB0 model:
from tensorflow.python.keras.applications.efficientnet import EfficientNetB0
model = EfficientNetB0(include_top=False, weights=None, input_shape=(200,200,3))
and after after downloading it is already initialized with gamma = 1:
for layer in model.layers:
if isinstance(layer, BatchNormalization):
pprint(layer.gamma.numpy())
break
# prints:
# array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
# 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
# dtype=float32)
so code like below won't work:
from tensorflow.keras.layers import BatchNormalization
for layer in model.layers:
if isinstance(layer, BatchNormalization):
layer.gamma_initializer = 'zeros'
# layer.gamma.numpy() is still:
# array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
# 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
# dtype=float32)
Is there any way to force zero gamma initialization?

I don't know the meaning of the code "[:, row:row]"

I have the code:
g, g_err = data[:, 4:6].T
I don't know the meaning of [:, 4:6]
especially the first :
and does .T mean transpose?
You have a 2D matrix called data, your code takes all elements from the first dimension, marked as :, then takes only elements 4 and 5 in the second dimension, something like this:
>>> np.ones( (7,7 ))
array([[ 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1.]])
>>> np.ones( (7,7 ))[:,4:6]
array([[ 1., 1.],
[ 1., 1.],
[ 1., 1.],
[ 1., 1.],
[ 1., 1.],
[ 1., 1.],
[ 1., 1.]])
>>>
And yeah, .T means transpose.

In numpy, why multi dimension array d[0][0:2][0][0] returning not two elements

In [136]: d = np.ones((1,2,3,4))
In [167]: d[0][0][0:2][0]
Out[167]: array([ 1., 1., 1., 1.])
as shown above, why it's not returning exactly 2 elements
Look at the array itself. It should be self explanatory
>>> d
array([[[[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]],
[[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]]]])
# first you grab the first and only element
>>> d[0]
array([[[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]],
[[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]]])
# then you get the first element out of the two groups
>>> d[0][0]
array([[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]])
# thirdly, you get the two first elements as a list
>>> d[0][0][0:2]
array([[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]])
# finally, you get the first element of the list
>>> d[0][0][0:2][0]
array([ 1., 1., 1., 1.])

How to generate and apply a square mask in numpy

I really just can't grok how masks work in Numpy.
I create a mask like
import numpy
def make_mask(center_x,center_y,len_x,len_y):
x,y = numpy.ogrid[:len_x, :len_y]
mask = (center_x-x)**2 + (center_y-y)**2
return mask
Then I attempt to use it
>>>a = numpy.ones((10,10))
>>>mask = make_mask(2,2,2,2,2)
>>>a[mask] = 0
>>>a
array([[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[0,0,0,0,0,0,0,0],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[0,0,0,0,0,0,0,0],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[0,0,0,0,0,0,0,0]])
What I was expecting was something like
>>>a
array([[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[1,1,0,0,1,1,1,1],
[1,1,0,0,1,1,1,1],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1]])
I've try a few different versions of the function. I just can't get the desired behavior. What am I doing wrong. I really don't understand how a 2D matrix indexes a 2D matrix.
Your mask is setting the 2nd, 5th and 8th rows to 0; the array is being flattened since it does not have the same shape as the array it is masking. It is being applied as:
a[2] = 0
a[5] = 0
a[8] = 0
I think you were expecting something more like:
mask = numpy.ones_like(a)
mask[center_y:center_y + len_y, center_x:center_x + len_x] = 0
which has the same size as the array you are tring to mask and gives the expected result.
If you take a look at what your make_mask function does, when written like this:
def make_mask(index_x,index_y,len_x,len_y):
x,y = numpy.ogrid[:len_x, :len_y]
mask = (index_x-x)**2 + (index_y-y)**2
return mask
you will see that you get
array([[8, 5],
[5, 2]])
and when you index a 10x10 matrix with that 2x2 matrix, I believe it treats all the values in that matrix as indexing the larger matrix by row. Which is why you see the 2nd row with all zeros, the 5th row with all zeros and the 8th row with all zeros.
To get the effect you desire, you can just use the indices you have, you don't even need a function:
a[startx:startx+lenx, starty:starty+leny] = 0
which gives:
array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 0., 0., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 0., 0., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])

Categories

Resources