1

Consider three numpy arrays. Each numpy array is three dimensional. We have array X, array Y, and array Z. All these arrays are the same shape. Combining the three matching elements of X, Y, and Z at the same places gives a coordinate. I have a function (not python function, mathematical) which has to run on one of these position vectors and place an output into another three dimensional array called s. So if the arrays were defined as shown below:

X = [[[1,2],[3,4]]        Y = [[[1,2],[3,4]]      Z = [[[1,2],[3,4]]
     [[5,6],[7,8]]]            [[5,6],[7,8]]]          [[5,6],[7,8]]]

Then the points to be tested would be:

(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7),(8,8,8)

If the function s was simply a+b+c then the results matrix would be:

s=[[[ 3, 6],[ 9,12]]
   [[15,18],[21,24]]]

But this is not the case instead we have a two dimensional numpy array called sv. In the actual problem, sv is a list of vectors of dimension three, like our position vectors. Each position vector must be subtracted from each support vector and the magnitude found of the resulting vector to give the classification of each vector. What numpy operations can be used to do this?

3
  • 1
    Can you provide a numerical example? Commented Sep 5, 2015 at 5:31
  • 1
    It would help to be specific about sizes, and maybe give names to the different arrays. The first one, X, is nx3? Then you have 3 arrays, Y1, Y2, and Y3, each of which is what size? (looks like mx2x3 ?) Finally, Z, the collection of Yi, is 3xmx2x3 ? Commented Sep 5, 2015 at 5:31
  • I will name the dimensions by their sizes to help discussion. Let's say x, y, z each have shape (n, m, l), then the positions array p has shape (d, n, m, l) where d=3 is the physical dimension of the vectors. Then p[0] is x, etc. Finally sv has shape (N, d), where N is the number of 3d vectors in sv. Your output would be of shape (N, n, m, l)? Since d has collapsed away as the magnitude gives scalars. Or does N somehow map to one of n, m, or l? Commented Sep 6, 2015 at 2:09

1 Answer 1

1

We start with the 3 arrays of components x, y, and z. I will change the values from your example so that they have unique values:

x = np.array([[[1,2],[3,4]],
              [[5,6],[7,8]]])
y = x + 10
z = y + 10

Each of the above have shape (2,2,2), but they could be any (n, m, l). This shape will have little impact on our process.

We next combine the three component arrays into a new array p, the "position vector", creating a new dimension i will iterate over the three physical dimensions x, y, z,

p = np.array([x, y, z])

so p[0] is x and so on, and p has shape (d, n, m, l) (where d=3 is the physical dimensionality of the vectors).

Now we look at your list of vectors sv which presumably has shape (N, d). Let us use a small number for N:

N = 4
d = 3
sv = np.arange(d*N).reshape(N,d) # a list of N vectors in 3d

OK the above was a little repetive but I want to be clear (and please correct any misunderstandings I may have had from your question).

You want to make some difference, diff in which you take each of the n*m*l vectors buried in p and subtract from it each of the N vectors in sv. This will give you N*n*m*l vectors, which each have d components. We need to align each of these dimensions before we do subtractions.

Basically we want to take p - sv but we must make sure that their shapes match so that the d axis is aligned, and the n, m, l and N axes basically just add up. The way numpy broadcasts is to take the shapes of the array, and aligns them from the end, so the last axis of each is aligned, and so on. To broadcast, each size must match exactly, or must be empty (on the left) or 1. That is, if your shapes were (a, b, c) and (b, c), you would be fine, and the second array would be repeated ("broadcasted") a times to match the a different subarrays of shape (b, c) in the first array. You can use dimensions length 1 which will force the position, so normally two arrays of shape (a, b, c) and (a, b) will not align because the last axis does not match, but you can add a new placeholder axis at the end of the second to give it shape (a, b, 1) which will match to (a, b, c) no matter what the value of c is.

We give shape (N, d, 1, 1, 1) to sv which matches the shape (d, n, m, l) of p. This can be done several ways:

sv = sv.reshape(sv.shape + (1,1,1)])
#or
sv.shape += (1, 1, 1)
#or
sv = sv[..., None, None, None]

Then, we can do the difference:

diff = p - sv[..., None, None, None]

where we have that diff.shape is (N, d, n, m, l). Now we can square it and sum over the second (d) dimension to get the norm/magnitude of each vector:

m = (diff*diff).sum(1)

which of course will have shape (N, n, m, l), or in the example case (4, 2, 2, 2)

So, all together:

import numpy as np

x = np.array([[[1,2],[3,4]],
              [[5,6],[7,8]]])
y = x + 10
z = y + 10
p = np.array([x, y, z])
print p.shape
N = 4
d = 3
sv = np.arange(d*N).reshape(N,d) # a list of N vectors in 3d
print sv.shape
diff = p - sv[..., None, None, None]
print diff.shape
m = (diff*diff).sum(1)
print m.shape
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the answer! Need sometime to go through it but looks to be perfect! The solution I had found involved copying a lot of the data which resulted in excess memory usage so this is ideal!
You're welcome, let me know if I can explain anything better.
Is there anywhere I can find a comprehensive overview on Numpy broadcasting rules?
Yeah these two are decent: numpy basics: broadcasting, and Eric's broadcasting doc. Mainly I've learned from practice and reading questions (and trying to answer them) on Stack Overflow.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.