Python Multiplication different shape to numpy dot product - python

I am trying to understand the python multiplication operator. I was always under the assumption that it performed a dot product when doing the following
a * b
however, the example below shows that different shapes are produced.
a = np.random.random((3, 3))
b = np.array([1,0,1])
Multiplication operator:
(a*b).shape
(3, 3)
Numpy dot product:
np.dot(a,b).shape
(3,)
What maths operation is the multiplication operator doing?

import numpy as np
a = np.random.randint(3, size=(3, 3))
Out[1]:
(A) [[0 1 1]
[0 2 2]
[0 1 0]]
b = np.array([1,0,2])
Out[2]:
(B) [1 0 2]
So in operation a*b it does element-wise multiply. Because dimensions mismatch it make "broadcast", and apply extrapolated "b" instead real "b".
(A)[[0 1 1] (B)[[1 0 2] [[0 0 2] # [0x0, 1x0, 1x2] and so on
[0 2 2] * [1 0 2] = [0 0 4]
[0 1 0]] [1 0 2]] [0 0 0]]
On another hand, np.dot gives you matrix multiplying:
(A)[[0 1 1] (B)[[1] [[2] # [0x1 + 1x0 + 1x2 = 2] and so on
[0 2 2] X [0] = [4]
[0 1 0]] [2]] [0]]

One general answer is that the python multiplication operator has a different behaviour depending on the object it is applied to.
numpy objects are not python primitive types. numpy redefines the behaviour of the multiplication operator.
According to numpy documentation:
arithmetic operators on arrays apply elementwise
Reading the doc further you get your answer:
Unlike in many matrix languages, the product operator * operates elementwise in NumPy arrays. The matrix product can be performed using the # operator (in python >=3.5) or the dot function or method

Related

Generalized version of np.roll

I have a 2D array
a = np.array([[0,1,2,3],[4,5,6,7]])
that is a 2x4 array. I need to shift the elements of each of the two arrays in axis 0 in but with different steps, say 1 for the first and 2 for the second, so that the output will be
np.array([[1,2,3,0],[6,7,4,5]])
With np.roll it doesn't seem possible to do it, at least looking at the documentation, I don't see any useful hint. There exists another function doing this?
This is an attempt at a generalized version of numpy.roll.
import numpy as np
a = np.array([[0,1,2,3],[4,5,6,7]])
def roll(a, shifts, axis):
assert a.shape[axis] == len(shifts)
return np.stack([
np.roll(np.take(a, i, axis), shifts[i]) for i in range(len(shifts))
], axis)
print(a)
print(roll(a, [-1, -2], 0))
print(roll(a, [1, 2, 1, 0], 1))
prints
[[0 1 2 3]
[4 5 6 7]]
[[1 2 3 0]
[6 7 4 5]]
[[4 1 6 3]
[0 5 2 7]]
Here, the parameter a is a numpy.array, shifts is an Iterable containing the shift amounts per element and axis is the axis along which to shift. Note that was only tested on two-dimensional arrays however.

Is there any Python equivalent to sort([op ;op+1])

As title, I have Matlab
op = [1 3 5]
[op ;op+1]
opf = sort([op ;op+1])
opf = [1 2 3 4 5 6]
and reading the doc, I've discovered that ; could signify end of row. However I don't know if that's the case since it's in square brackets and in Matlab more often than not there are way too many ways of doing most of the things. Not that it's something bad to be honest, but it's at least a bit confusing for students like me.
To replicate in Python I did
opf = np.sort([op,op+1])
but opf shape is wrong. I get in fact [[0 2 4] [1 3 5]] which is (2,3). opf instead should be [1 2 3 4 5 6] and its shape accordingly (6,1)
This is possible in Python using regular lists:
import numpy as np
op = np.array([1, 3, 5])
opf = [[i, i+1] for i in op]
opf = [i for j in opf for i in j]
print(np.asarray(opf))
Returning:
[1 2 3 4 5 6]
If your op array is unordered, you could do:
import numpy as np
op = np.array([1, 5, 3])
opf = [[i, i+1] for i in sorted(op)]
opf = [i for j in opf for i in j]
print(np.sort(np.asarray(opf)))
Again returning:
[1 2 3 4 5 6]
When working with numpy arrays, you cannot concatenate like you did on matlab.
The way to do it, is via np.concatenate(). Also, np.concatenate() takes in a tuple as its argument, so you must use double parenthesis (one to indicate the function, and the other for the tuple of the arrays you want to concatenate).
Your complete example would look something like this
import numpy as np
a = [1, 3, 5]
op = np.array(a)
result = np.sort(np.concatenate((op, op + 1)))
print(result)
Try:
np.reshape(6,1)
If you are using numpy you can reshape it yourself

Python: use range() function or np.arrange() as parameter arr[range(m), y]

This is what I saw in a blog:
(Source: https://deepnotes.io/softmax-crossentropy#cross-entropy-loss)
def delta_cross_entropy(X,y):
"""
X is the output from fully connected layer (num_examples x num_classes)
y is labels (num_examples x 1)
Note that y is not one-hot encoded vector.
It can be computed as y.argmax(axis=1) from one-hot encoded vectors of labels if required.
"""
m = y.shape[0]
grad = softmax(X)
grad[range(m),y] -= 1
grad = grad/m
return grad
Also I try it myself by replacing y(matrix) using a integer number:
import numpy as np
arr = np.array([[1,2,3], [4,5,6], [7,8,9]])
print(arr)
arr[range(2), 1] = 0
print("after range: ", arr)
As result I got:
[[1 2 3]
[4 5 6]
[7 8 9]]
after range: [[1 0 3]
[4 0 6]
[7 8 9]]
Can someone pls explain what does this range() function do here? thank you!
range(2) is like passing [0, 1] as an argument in this case. You'll get the same result in this experiment:
arr1 = np.array([[1,2,3], [4,5,6], [7,8,9]])
arr1[range(2), 1] = 0
arr2 = np.array([[1,2,3], [4,5,6], [7,8,9]])
arr2[[0, 1], 1] = 0
np.all(arr1 == arr2)
Where np.all checks if the equality is true across the whole array and it will return True
In other words arr[range(2), 1] = 0 is equal to this as well:
arr[0, 1] = 0
arr[1, 1] = 0
And another way to look at it:
for i in range(2):
arr[i, 1] = 0
Range just creates a new range object from 0 to 1 less than the value given, so for example:
>>> range(2)
[0, 1]
Numpy arrays can accept iterables of indices to index so in this case you are saying "set the {0,1} row, 1st column equal to 0".

which numpy command could I use to subtract vectors with different dimensions many times?

i have to write this function:
in which x is a vector with dimensions [150,2] and c is [N,2] (lets suppose N=20). From each component xi (i=1,2) I have to subtract the components of c in this way ([x11-c11,x12-c12])...([x11-cN1, x12-cN2])for all the 150 sample.
I've trasformed them in a way I have the same dimensions and I can subtract them, but the result of the function should be a vector. Maybe How can I write this in numpy?
Thank you
Ok, lets suppose x=(5,2) and c=(3,2)
this is what I have obtained transforming dimensions of the two arrays. the problem is that, I have to do this but with a iteration "for loop" because the exp function should give me as a result a vector. so I have to obtain a sort of matrix divided in N blocks.
From what I understand of the issue, the problem seems to be in the way you are calculating the vector norm, not in the subtraction. Using your example, but calculating exp(-||x-c||), try:
x = np.linspace(8,17,10).reshape((5,2))
c = np.linspace(1,6,6).reshape((3,2))
sub = np.linalg.norm(x[:,None] - c, axis=-1)
np.exp(-sub)
array([[ 5.02000299e-05, 8.49325705e-04, 1.43695961e-02],
[ 2.96711024e-06, 5.02000299e-05, 8.49325705e-04],
[ 1.75373266e-07, 2.96711024e-06, 5.02000299e-05],
[ 1.03655678e-08, 1.75373266e-07, 2.96711024e-06],
[ 6.12664624e-10, 1.03655678e-08, 1.75373266e-07]])
np.exp(-sub).shape
(5, 3)
numpy.linalg.norm will try to return some kind of matrix norm across all the dimensions of its input unless you tell it explicitly which axis represents the vector components.
I I understand, try if this give the expected result, but there is still the problem that the result has the same shape of x:
import numpy as np
x = np.arange(10).reshape(5,2)
c = np.arange(6).reshape(3,2)
c_col_sum = np.sum(c, axis=0)
for (h,k), value in np.ndenumerate(x):
x[h,k] = c.shape[0] * x[h,k] - c_col_sum[k]
Initially x is:
[[0 1]
[2 3]
[4 5]
[6 7]
[8 9]]
And c is:
[[0 1]
[2 3]
[4 5]]
After the function x becomes:
[[-6 -6]
[ 0 0]
[ 6 6]
[12 12]
[18 18]]

Iterating through matrix in python using numpy

I want to generate a resultant matrix by iterating through 5 different matrices and firstly i want to take first value of all matrix and take the average of these values and append the result as the first value of resultant matrix. Can anyone tell how to do this in python using numpy library??
In general you want to avoid (potentially slow) python-based looping and let numpy do (faster) c-based looping (or no looping at all).
Most people would call the approach of removing explicit loops as (numpy-)vectorization which is usually very important if going for performance.
The following example creates 5 numpy-arrays with size (3,3) (the matrix-type, which also exists, is kind of deprecated, not used here and most numpy-users should use arrays as replacement for matrices) and calculate a new matrix containing all the averages with the same shape (elementwise-mean over matrix-cells; we are interpreting the 2d-arrays as a matrix).
Code:
import numpy as np
a, b, c, d, e = [np.random.randint(0, 5, size=(3,3)) for i in range(5)]
all = np.stack((a, b, c, d, e), axis=0)
print(all.shape)
x = np.mean(all, axis=0)
print(a)
print(b)
print(c)
print(d)
print(e)
print(x)
Out:
(5, 3, 3)
[[0 0 0]
[0 1 0]
[2 4 0]]
[[4 2 0]
[3 3 4]
[0 4 0]]
[[3 4 0]
[2 2 1]
[0 0 4]]
[[3 1 2]
[4 3 4]
[2 0 3]]
[[3 4 2]
[3 1 0]
[1 0 0]]
[[ 2.6 2.2 0.8]
[ 2.4 2. 1.8]
[ 1. 1.6 1.4]]
If you still want to loop, you can just use a nested loop like:
for row in range(array.shape[0]):
for col in range(array.shape[1]):
cell_value = array[row, col]
...
given an array of 2 dimensions.

Categories