5

I have just started using numpy and I am getting confused about how to use arrays. I have seen several Stack Overflow answers on numpy arrays but they all deal with how to get the desired result (I know how to do this, I just don't know why I need to do it this way). The consensus that I've seen is that arrays are better than matrices because they are a more basic class and less restrictive. I understand you can transpose an array which to me means there is a distinction between a row and a column, but the multiplication rules all produce the wrong outputs (compared to what I am expecting).

Here is the test code I have written along with the outputs:

a = numpy.array([1,2,3,4])
print(a)
>>> [1 2 3 4]

print(a.T)          # Transpose
>>> [1 2 3 4]       # No apparent affect

b = numpy.array( [ [1], [2], [3], [4] ] )
print(b)
>>> [[1]
     [2]
     [3]
     [4]]           # Column (Expected)

print(b.T)
>>> [[1 2 3 4]]     # Row (Expected, transpose seems to work here)

print((b.T).T)
>>> [[1]
     [2]
     [3]
     [4]]           # Column (All of these are as expected, 
                    #          unlike for declaring the array as a row vector)

# The following are element wise multiplications of a
print(a*a)
>>> [ 1  4  9 16]

print(a * a.T)      # Row*Column
>>> [ 1  4  9 16]   # Inner product scalar result expected

print(a.T * a)      # Column*Row
>>> [ 1  4  9 16]   # Outer product matrix result expected

print(b*b)
>>> [[1]
     [4]
     [9]
     [16]]          # Expected result, element wise multiplication in a column

print(b * b.T)      # Column * Row (Outer product)
>>> [[ 1  2  3  4]
     [ 2  4  6  8]
     [ 3  6  9 12]
     [ 4  8 12 16]] # Expected matrix result

print(b.T * (b.T))  # Column * Column (Doesn't make much sense so I expected elementwise multiplication
>>> [[ 1  4  9 16]]

print(b.T * (b.T).T) # Row * Column, inner product expected
>>> [[ 1  2  3  4]
    [ 2  4  6  8]
    [ 3  6  9 12]
    [ 4  8 12 16]]  # Outer product result

I know that I can use numpy.inner() and numpy.outer() to achieve the affect (that is not a problem), I just want to know if I need to keep track of whether my vectors are rows or columns.

I also know that I can create a 1D matrix to represent my vectors and the multiplication works as expected. I'm trying to work out the best way to store my data so that when I look at my code it is clear what is going to happen - right now the maths just looks confusing and wrong.

I only need to use 1D and 2D tensors for my application.

3 Answers 3

6

I'll try annotating your code

a = numpy.array([1,2,3,4])
print(a)
>>> [1 2 3 4]

print(a.T)          # Transpose
>>> [1 2 3 4]       # No apparent affect

a.shape will show (4,). a.T.shape is the same. It kept the same number of dimensions, and performed the only meaningful transpose - no change. Making it (4,1) would have added a dimension, and destroyed the A.T.T roundtrip.

b = numpy.array( [ [1], [2], [3], [4] ] )
print(b)
>>> [[1]
     [2]
     [3]
     [4]]           # Column (Expected)

print(b.T)
>>> [[1 2 3 4]]     # Row (Expected, transpose seems to work here)

b.shape is (4,1), b.T.shape is (1,4). Note the extra set of []. If you'd created a as a = numpy.array([[1,2,3,4]]) its shape too would have been (1,4).

The easy way to make b would be b=np.array([[1,2,3,4]]).T (or b=np.array([1,2,3,4])[:,None] or b=np.array([1,2,3,4]).reshape(-1,1))

Compare this to MATLAB

octave:3> a=[1,2,3,4]
a =
   1   2   3   4
octave:4> size(a)
ans =
   1   4
octave:5> size(a.')
ans =
   4   1

Even without the extra [] it has initialed the matrix as 2d.

numpy has a matrix class that imitates MATLAB - back in the time when MATLAB allowed only 2d.

In [75]: m=np.matrix('1 2 3 4')

In [76]: m Out[76]: matrix([[1, 2, 3, 4]])

In [77]: m.shape
Out[77]: (1, 4)

In [78]: m=np.matrix('1 2; 3 4')

In [79]: m
Out[79]: 
matrix([[1, 2],
        [3, 4]])

I don't recommend using np.matrix unless it really adds something useful to your code.

Note the MATLAB talks of vectors, but they are really just their matrix with only one non-unitary dimension.

# The following are element wise multiplications of a
print(a*a)
>>> [ 1  4  9 16]

print(a * a.T)      # Row*Column
>>> [ 1  4  9 16]   # Inner product scalar result expected

This behavior follows from a.T == A. As you noted, * produces element by element multiplication. This is equivalent to the MATLAB .*. np.dot(a,a) gives the dot or matrix product of 2 arrays.

print(a.T * a)      # Column*Row
>>> [ 1  4  9 16]   # Outer product matrix result expected

No, it is still doing elementwise multiplication.

I'd use broadcasting, a[:,None]*a[None,:] to get the outer product. Octave added this in imitation of numpy; I don't know if MATLAB has it yet.

In the following * is always element by element multiplication. It's broadcasting that produces matrix/outer product results.

print(b*b)
>>> [[1]
     [4]
     [9]
     [16]]          # Expected result, element wise multiplication in a column

A (4,1) * (4,1)=>(4,1). Same shapes all around.

print(b * b.T)      # Column * Row (Outer product)
>>> [[ 1  2  3  4]
     [ 2  4  6  8]
     [ 3  6  9 12]
     [ 4  8 12 16]] # Expected matrix result

Here (4,1)*(1,4)=>(4,4) product. The 2 size 1 dimensions have been replicated so it becomes, effectively a (4,4)*(4,4). How would you do replicate this in MATLAB - with .*?

print(b.T * (b.T))  # Column * Column (Doesn't make much sense so I expected elementwise multiplication
>>> [[ 1  4  9 16]]

* is elementwise regardless of expectations. Think b' .* b' in MATLAB.

print(b.T * (b.T).T) # Row * Column, inner product expected
>>> [[ 1  2  3  4]
    [ 2  4  6  8]
    [ 3  6  9 12]
    [ 4  8 12 16]]  # Outer product result

Again * is elementwise; inner requires a summation in addition to multiplication. Here broadcasting again applies (1,4)*(4,1)=>(4,4).

np.dot(b,b) or np.trace(b.T*b) or np.sum(b*b) give 30.

When I worked in MATLAB I frequently checked the size, and created test matrices that would catch dimension mismatches (e.g. a 2x3 instead of a 2x2 matrix). I continue to do that in numpy.

The key things are:

  • numpy arrays may be 1d (or even 0d)

  • A (4,) array is not exactly the same as a (4,1) or (1,4)`.

  • * is elementwise - always.

  • broadcasting usually accounts for outer like behavior

Sign up to request clarification or add additional context in comments.

Comments

3

"Transposing" is, from a numpy perspective, really only a meaningful concept for two-dimensional structures:

>>> import numpy
>>> arr = numpy.array([1,2,3,4])
>>> arr.shape
(4,)
>>> arr.transpose().shape
(4,)

So, if you want to transpose something, you'll have to make it two-dimensional:

>>> arr_2d = arr.reshape((4,1)) ## four rows, one column -> two-dimensional
>>> arr_2d.shape
(4, 1)
>>> arr_2d.transpose().shape
(1, 4)

Also, numpy.array(iterable, **kwargs) has a key word argument ndmin, which will, set to ndmin=2 prepend your desired shape with as many 1 as necessary:

>>> arr_ndmin = numpy.array([1,2,3,4],ndmin=2)
>>> arr_ndmin.shape
(1, 4)

Comments

2

Yes, they do.

Your question is already answered. Though I assume you are a Matlab user? If so, you may find this guide useful: Moving from MATLAB matrices to NumPy arrays

5 Comments

This is a helpful resource, yes I do use Matlab. The main difference I can see is that for a vector a, a*a is an error in Matlab but preforms element wise multiplication in numpy, and a*a' is a valid inner/outer product (depending on if a is a row or column vector) in Matlab but a*a.T in numpy still outputs an element wise multiplication.
@Francis Have you tried doing it like this: numpy.dot(a,a.T) or a.dot(a.T). Although, for optimisation reasons, I suggest you store a.T in another variable.
Yes, I am aware of numpy.dot(), numpy.outer() etc. I know how to perform the operations I want, I'd just like to know how the * operator works on 1D numpy arrays because the results from my test are unintuitive.
aaah, I see. So the question is not how it is done, but how do they differ. You are right, these are substantially different. The concept of vectorisation and matrices in Matlab are different to those in Python. In Python, Matrices are essentially list of lists, and are not really restricted in operations and elements (unless you explicitly use the matrix function in NumPy, or implement tuple which is immutable). You might find this helpful: scipy-lectures.org/intro/numpy/operations.html
To be picky, Python does not have matrices, though numpy has a subclass called matrix. In MATLAB (esp. the old versions) everything is a matrix - a 2d structure. numpy arrays can be converted to/from lists of lists, but should not (generally) be thought of as such. MATLAB added cells to get the type flexibility of Python lists. And structures to imitate objects/classes.

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.