Reshape 1D vector into multiple matrices properly (numpy) - python

Given a 1 dimensional vector, I have to split it and reshape it
in order to fit with a list of matrices. The order matters. Here I have a working example:
import numpy as np
def setWeights(odlW: list, newW: np.ndarray) -> list:
assert newW.shape[0] == sum(map(np.size, odlW)) # total nb weights
for i, w in enumerate(odlW):
if i == 0:
odlW[i] = newW[:w.size].reshape(odlW[i].shape)
else:
odlW[i] = newW[odlW[i - 1].size : odlW[i - 1].size + odlW[i].size].reshape(w.shape)
return odlW
shape = [2, 3, 4, 1]
weights = [np.ones((y, x)) for x, y in zip(shape[:-1], shape[1:])]
for w in weights:
print("w {}".format(w.shape))
print(w)
which gives :
w (3, 2)
[[1. 1.]
[1. 1.]
[1. 1.]]
w (4, 3)
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
w (1, 4)
[[1. 1. 1. 1.]]
and after calling the function, everything works well:
# there are 22 weights
newVec = np.zeros((22, 1))
weights = setWeights(weights,newVec)
for w in weights:
print("w {}".format(w.shape))
print(w)
which gives:
w (3, 2)
[[0. 0.]
[0. 0.]
[0. 0.]]
w (4, 3)
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
w (1, 4)
[[0. 0. 0. 0.]]
However, I really dislike the shape of the function, I cannot change the data structure but if someone knows how to solve this properly (maybe with builtin numpy functions) it would be really helpful.
Thanks for your time.

Related

Slicing 2D NumPy Array, removing first and last row and column

I have a 2D Numpy array of tile objects that serves as a map. The outer ring is all "wall" values to make a closed border. I want to make a copy of the inner values to iterate over without touching the outer rows and columns. I'm trying:
inner_values = map.tiles[1:-1][1:-1]
to cut off the top and bottom rows and left and right columns. My map is 100*70, and this keeps giving me an array of shape (96, 70) when I want (98, 68). How can I use slices correctly to get my inner values? Thanks!
You are just about there...you can put all the indices inside the brackets to get what you want:
import numpy as np
a = np.ones([5, 5])
print(a)
# [[1. 1. 1. 1. 1.]
# [1. 1. 1. 1. 1.]
# [1. 1. 1. 1. 1.]
# [1. 1. 1. 1. 1.]
# [1. 1. 1. 1. 1.]]
a[1:-1, 1:-1] = 0
print(a)
# [[1. 1. 1. 1. 1.]
# [1. 0. 0. 0. 1.]
# [1. 0. 0. 0. 1.]
# [1. 0. 0. 0. 1.]
# [1. 1. 1. 1. 1.]]
Or given your dimensions:
a = np.ones([100,70])
a[1:-1, 1:-1].shape
# (98, 68)

Is there a way to insert multiple elements to different locations in a ndarray all at once?

I'm using numpy's ndarray, and I'm wondering is there a way that allows me to insert multiple elements to different locations all at once?
For example, I have an image, and I want to pad the image with 0s. This is what I currently have:
def zero_padding(self):
padded = self.copy()
padded.img = np.insert(self.img, 0, 0, axis = 0)
padded.img = np.insert(padded.img, padded.img.shape[0], 0, axis = 0)
padded.img = np.insert(padded.img, 0, 0, axis = 1)
padded.img = np.insert(padded.img, padded.img.shape[1], 0, axis = 1)
return padded
where padded is an instance of the image.
Sure, you can use the fancy indexing techinque of NumPy as follows:
import numpy as np
if __name__=='__main__':
A = np.zeros((5, 5))
A[[1, 2], [0, 3]] = 1
print(A)
Output:
[[0. 0. 0. 0. 0.]
[1. 0. 0. 0. 0.]
[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
Cheers

Vectorizing the element-wise product of two 3 D tensors

Is there a way to vectorize the following code so that I can remove the loop entirely?
x = tf.constant([[[1,2,3],[2,3,4]],[[1,2,3],[2,3,5]]])
t=tf.eye(x.shape[1])[:,:,None]
for i in range(x.shape[0]):
out = tf.multiply(t,x[i].numpy())
out=tf.reshape(out, shape=(out.shape[0], out.shape[-1]*out.shape[-2]))
print(out)
In short: how to multiply a 3 D tensor to each element of a 3 D tensor?
In my case: 3 D tensors are:
tf.Tensor(
[[[1.]
[0.]]
[[0.]
[1.]]], shape=(2, 2, 1), dtype=float32)
and
tf.Tensor(
[[[1 2 3]
[2 3 4]]
[[1 2 3]
[2 3 5]]], shape=(2, 2, 3), dtype=int32)
expected output: following 2 tensors merged together with shape 2*2*6.
tf.Tensor(
[[1. 2. 3. 0. 0. 0.]
[0. 0. 0. 2. 3. 4.]], shape=(2, 6), dtype=float32)
tf.Tensor(
[[1. 2. 3. 0. 0. 0.]
[0. 0. 0. 2. 3. 5.]], shape=(2, 6), dtype=float32)
Here is how you can get that result:
import tensorflow as tf
x = tf.constant([[[1, 2, 3], [2, 3, 4]],
[[1, 2, 3], [2, 3, 5]]], dtype=tf.float32)
t = tf.eye(tf.shape(x)[1], dtype=x.dtype)
# Add one dimension to x and one dimension to t
xt = tf.expand_dims(x, 1) * tf.expand_dims(t, 2)
# Reshape
result = tf.reshape(xt, (tf.shape(x)[0], tf.shape(x)[1], -1))
print(result.numpy())
# [[[1. 2. 3. 0. 0. 0.]
# [0. 0. 0. 2. 3. 4.]]
#
# [[1. 2. 3. 0. 0. 0.]
# [0. 0. 0. 2. 3. 5.]]]

hog features output array returns a very few values

fd, hog_image = feature.hog(grayscale, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(2, 2), visualise=True)
print(hog_image.size)
This outputs a value 8192 but when I print(hog_image). It gives me an array of very few values. I dont understand these values. What does this array tell? Why are the values empty.
img = imread(contours.jpg)
imshow(img)
print(img.shape)
resized_img = resize(img, (128,64))
imshow(resized_img)
print(resized_img.shape)
grayscale = rgb2gray(resized_img)
imshow(grayscale)
fd, hog_image = feature.hog(grayscale, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(2, 2), visualise=True)
#print(hog_image)
print(hog_image.size)
[[0. 0. 0. ... 0. 0. 0. ]
[0. 0. 0.04045185 ... 0.02035863 0. 0. ]
[0. 0.01418138 0. ... 0. 0.00873405 0. ]
...
[0. 0.00782422 0. ... 0. 0.00160013 0. ]
[0. 0. 0.00335884 ... 0.01116131 0. 0. ]
[0. 0. 0. ... 0. 0. 0. ]]
This is the array which I am getting. Please tell me the meaning of this array

Modifying (keras/tensorflow) Tensors using numpy methods

I want to perform a specific operation. Namely, from a matrix:
A = np.array([[1,2],
[3,4]])
To the following
B = np.array([[1, 0, 0, 2, 0, 0],
[0, 1, 0, 0, 2, 0],
[0, 0, 1, 0, 0, 2],
[3, 0, 0, 4, 0, 0],
[0, 3, 0, 0, 4, 0],
[0, 0, 3, 0, 0, 4]])
Or in words: multiply every entry by the identity matrix and keep the same order.
Now I have accomplished this by using numpy, using the following code. Here N and M are the dimensions of the starting matrix, and the dimension of the identity matrix.
l_slice = 3
n_slice = 2
A = np.reshape(np.arange(1, 1+N ** 2), (N, N))
B = np.array([i * np.eye(M) for i in A.flatten()])
C = B.reshape(N, N, M, M).reshape(N, N * M, M).transpose([0, 2, 1]).reshape((N * M, N * M))
where C has my desired properties.
But now I want do this modification in Keras/Tensorflow, where the matrix A is the outcome of one of my layers.
However, I am not sure yet if I will be able to properly create matrix B. Especially when batches are involved, I think I will somehow mess up the dimensions of my problem.
Can anyone with more Keras/Tensorflow experience comment on this 'reshape' and how he/she sees this happening within Keras/Tensorflow?
Here is a way to do that with TensorFlow:
import tensorflow as tf
data = tf.placeholder(tf.float32, [None, None])
n = tf.placeholder(tf.int32, [])
eye = tf.eye(n)
mult = data[:, tf.newaxis, :, tf.newaxis] * eye[tf.newaxis, :, tf.newaxis, :]
result = tf.reshape(mult, n * tf.shape(data))
with tf.Session() as sess:
a = sess.run(result, feed_dict={data: [[1, 2], [3, 4]], n: 3})
print(a)
Output:
[[1. 0. 0. 2. 0. 0.]
[0. 1. 0. 0. 2. 0.]
[0. 0. 1. 0. 0. 2.]
[3. 0. 0. 4. 0. 0.]
[0. 3. 0. 0. 4. 0.]
[0. 0. 3. 0. 0. 4.]]
By the way, you can do basically the same in NumPy, which should be faster than your current solution:
import numpy as np
data = np.array([[1, 2], [3, 4]])
n = 3
eye = np.eye(n)
mult = data[:, np.newaxis, :, np.newaxis] * eye[np.newaxis, :, np.newaxis, :]
result = np.reshape(mult, (n * data.shape[0], n * data.shape[1]))
print(result)
# The output is the same as above
EDIT:
I'll try to give some intuition about why/how this works, sorry if it's too long. It is not that hard but I think it's sort of tricky to explain. Maybe it is easier to see how the following multiplication works
import numpy as np
data = np.array([[1, 2], [3, 4]])
n = 3
eye = np.eye(n)
mult1 = data[:, :, np.newaxis, np.newaxis] * eye[np.newaxis, np.newaxis, :, :]
Now, mult1 is a sort of "matrix of matrices". If I give two indices, I will get the diagonal matrix for the corresponding element in the original one:
print(mult1[0, 0])
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
So you could say this matrix could be visualize like this:
| 1 0 0 | | 2 0 0 |
| 0 1 0 | | 0 2 0 |
| 0 0 1 | | 0 0 2 |
| 3 0 0 | | 4 0 0 |
| 0 3 0 | | 0 4 0 |
| 0 0 3 | | 0 0 4 |
However this is deceiving, because if you try to reshape this to the final shape the result is not the right one:
print(np.reshape(mult1, (n * data.shape[0], n * data.shape[1])))
# [[1. 0. 0. 0. 1. 0.]
# [0. 0. 1. 2. 0. 0.]
# [0. 2. 0. 0. 0. 2.]
# [3. 0. 0. 0. 3. 0.]
# [0. 0. 3. 4. 0. 0.]
# [0. 4. 0. 0. 0. 4.]]
The reason is that reshaping (conceptually) "flattens" the array first and then gives the new shape. But the flattened array in this case is not what you need:
print(mult1.ravel())
# [1. 0. 0. 0. 1. 0. 0. 0. 1. 2. 0. 0. 0. 2. 0. ...
You see, it first traverses the first submatrix, then the second, etc. What you want though is for it to traverse first the first row of the first submatrix, then the first row of the second submatrix, then second row of first submatrix, etc. So basically you want something like:
Take the first two submatrices (the ones with 1 and 2)
Take all the first rows ([1, 0, 0] and [2, 0, 0]).
Take the first of these ([1, 0, 0])
Take each of its elements (1, 0 and 0).
And then continue for the rest. So if you think about it, we traversing first the axis 0 (row of "matrix of matrices"), then 2 (rows of each submatrix), then 1 (column of "matrix of matrices") and finally 3 (columns of submatrices). So we can just reorder the axis to do that:
mult2 = mult1.transpose((0, 2, 1, 3))
print(np.reshape(mult2, (n * data.shape[0], n * data.shape[1])))
# [[1. 0. 0. 2. 0. 0.]
# [0. 1. 0. 0. 2. 0.]
# [0. 0. 1. 0. 0. 2.]
# [3. 0. 0. 4. 0. 0.]
# [0. 3. 0. 0. 4. 0.]
# [0. 0. 3. 0. 0. 4.]]
And it works! So in the solution I posted, to avoid the tranposing, I just make the multiplication so the order of the axes is exactly that:
mult = data[
:, # Matrix-of-matrices rows
np.newaxis, # Submatrix rows
:, # Matrix-of-matrices columns
np.newaxis # Submatrix columns
] * eye[
np.newaxis, # Matrix-of-matrices rows
:, # Submatrix rows
np.newaxis, # Matrix-of-matrices columns
: # Submatrix columns
]
I hope that makes it slightly clearer. To be honest, in this case in particular I could came up with the solution quickly because I had to solve a similar problem not too long ago, and I guess you end up building an intuition of these things.
Another way to achieve the same effect in numpy is to use the following:
A = np.array([[1,2],
[3,4]])
B = np.repeat(np.repeat(A, 3, axis=0), 3, axis=1) * np.tile(np.eye(3), (2,2))
Then, to replicate it in tensorflow, we can use tf.tile, but there is no tf.repeat, however someone has provided this function on tensorflow tracker.
def tf_repeat(tensor, repeats):
"""
Args:
input: A Tensor. 1-D or higher.
repeats: A list. Number of repeat for each dimension, length must be the same as the number of dimensions in input
Returns:
A Tensor. Has the same type as input. Has the shape of tensor.shape * repeats
"""
with tf.variable_scope("repeat"):
expanded_tensor = tf.expand_dims(tensor, -1)
multiples = [1] + list(repeats)
tiled_tensor = tf.tile(expanded_tensor, multiples=multiples)
repeated_tesnor = tf.reshape(tiled_tensor, tf.shape(tensor) * repeats)
return repeated_tesnor
and thus the tensorflow implementation will look like the following. Here I also consider that the first dimension represents batches, and thus we do not operate on it.
N = 2
M = 3
nbatch = 2
Ain = np.reshape(np.arange(1, 1 + N*N*nbatch), (nbatch, N, N))
A = tf.placeholder(tf.float32, shape=(nbatch, N, N))
B = tf.tile(tf.eye(M), [N, N]) * tf_repeat(A, [1, M, M])
with tf.Session() as sess:
print(sess.run(C, feed_dict={A: Ain}))
and the result:
[[[1. 0. 0. 2. 0. 0.]
[0. 1. 0. 0. 2. 0.]
[0. 0. 1. 0. 0. 2.]
[3. 0. 0. 4. 0. 0.]
[0. 3. 0. 0. 4. 0.]
[0. 0. 3. 0. 0. 4.]]
[[5. 0. 0. 6. 0. 0.]
[0. 5. 0. 0. 6. 0.]
[0. 0. 5. 0. 0. 6.]
[7. 0. 0. 8. 0. 0.]
[0. 7. 0. 0. 8. 0.]
[0. 0. 7. 0. 0. 8.]]]

Categories

Resources