12

This is the code I have in Octave:

sum(bsxfun(@times, X*Y, X), 2)

The bsxfun part of the code produces element-wise multiplication so I thought that numpy.multiply(X*Y, X) would do the trick but I got an exception. When I did a bit of research I found that element-wise multiplication won't work on Python arrays (specifically if X and Y are of type "numpy.ndarray"). So I was wondering if anyone can explain this a bit more -- i.e. would type casting to a different type of object work? The Octave code works so I know I don't have a linear algebra mistake. I'm assuming that bsxfun and numpy.multiply are not actually equivalent but I'm not sure why so any explanations would be great.

I was able to find a website! that gives Octave to Matlab function conversions but it didn't seem to be help in my case.

alisianoi
  • 2,003
  • 3
  • 31
  • 46
eTothEipiPlus1
  • 577
  • 2
  • 9
  • 28
  • This question appears to be off-topic because it is a request for code translation – jonrsharpe May 08 '14 at 14:39
  • when you apply `sum()` in NumPy are you selecting the right `axis`? – Saullo G. P. Castro May 08 '14 at 14:40
  • "I'm having a lot of trouble" is not very informative. Please describe the behavior you see, a reproducible example is the best way to do that. – Lev Levitsky May 08 '14 at 14:42
  • Is `bsxfun(@times, X*Y, X)` the same as `(X*Y).*X`? – Eric May 08 '14 at 14:47
  • 1
    @Eric no it's the same (in Matlab) as `(X*Y)*repmat(X, size(X,2), 1)` (assuming here the `X` is a row vector). `(X*Y).*X` will be a syntax error unless the dimensions of `(X*Y)` and of `X` are identical. Matlab does not braodcast, or expand along a singelton dimension, automatically like octave or numpy do. That's what `bsxfun` is for. I know that in some instances Octave will perform the expansion automatically in which case the answer to your question is yes – Dan May 08 '14 at 14:52
  • 1
    The question would be a lot clearer if we had the dimensions of `X` and `Y`, and the exact nature of the exception. – hpaulj May 08 '14 at 15:31
  • did you manage to get the equivalent code in python/numpy? – Charlie Parker Jun 19 '16 at 06:15

3 Answers3

14

bsxfun in Matlab stand for binary singleton expansion, in numpy it's called broadcasting and should happen automatically. The solution will depend on the dimensions of your X, i.e. is it a row or column vector but this answer shows one way to do it:

How to multiply numpy 2D array with numpy 1D array?

I think that the issue here is that broadcasting requires one of the dimensions to be 1 and, unlike Matlab, numpy seems to differentiate between a 1 dimensional 2 element vector and a 2 dimensional 2 element, i.e. the difference between a matrix of shape (2,) and of shape (2,1), you need the latter for broadcasting to happen.

Community
  • 1
  • 1
Dan
  • 45,079
  • 17
  • 88
  • 157
  • Is there no bxnfun in numpy? What if I wanted to do a element wise sum for example. – Charlie Parker Jun 19 '16 at 06:14
  • You just do the sum, numpy will automatically broadcast it along a dimension. So just `+` in numpy is the same as `bsxfun(@plus,,)` in Matlab *provided* your numpy dimensions are right – Dan Jun 19 '16 at 11:19
  • so is the python code just literally just `A + B` or `A * B` (assuming A has say Dx1 and B has 1 x K). – Charlie Parker Jun 19 '16 at 15:52
  • @Pinocchio yes exactly, but make sure that in numpy you have a 2D array and not a 1D array, i.e. a `D`-by-`1` 2D array as opposed to a `D` element 1D array. Note that in MATLAB no such distinction exists. Also from MATLAB 2016b, `A + B` will work as well, i.e. automatic broadcasting is finally coming to MATLAB too – Dan Jun 19 '16 at 23:02
3

For those who don't know Numpy, I think it's worth pointing out that the equivalent of Octave's (and Matlab's) * operator (matrix multiplication) is numpy.dot (and, debatably, numpy.outer). Numpy's * operator is similar to bsxfun(@times,...) in Octave, which is itself a generalization of .*.

In Octave, when applying bsxfun, there are implicit singleton dimensions to the right of the "true" size of the operands; that is, an n1 x n2 x n3 array can be considered as n1 x n2 x n3 x 1 x 1 x 1 x.... In Numpy, the implicit singleton dimensions are to the left; so an m1 x m2 x m3 can be considered as ... x 1 x 1 x m1 x m2 x m3. This matters when considering operand sizes: in Octave, bsxfun(@times,a,b) will work if a is 2 x 3 x 4 and b is 2 x 3. In Numpy one could not multiply two such arrays, but one could multiply a 2 x 3 x 4 and a 3 x 4 array.

Finally, bsxfun(@times, X*Y, X) in Octave will probably look something like numpy.dot(X,Y) * X. There are still some gotchas: for instance, if you're expecting an outer product (that is, in Octave X is a column vector, Y a row vector), you could look at using numpy.outer instead, or be careful about the shape of X and Y.

Rory Yorke
  • 2,166
  • 13
  • 13
0

Little late, but I would like to provide an example of having equivalent bsxfun and repmat in python. This is a little bit of code I was just converting from Matlab to Python numpy:

Matlab:

x =

    -2
    -1
     0
     1
     2

n =

 2

M = repmat(x,1,n+1)

M =

    -2    -2    -2
    -1    -1    -1
     0     0     0
     1     1     1
     2     2     2


M = bsxfun(@power,M,0:n)

M =

     1    -2     4
     1    -1     1
     1     0     0
     1     1     1
     1     2     4

Equivalent in Python:

In [8]: x
Out[8]: 
array([[-2],
       [-1],
       [ 0],
       [ 1],
       [ 2]])

In [9]: n=2

In [11]: M = np.tile(x, (1, n + 1))

In [12]: M
Out[12]: 
array([[-2, -2, -2],
       [-1, -1, -1],
       [ 0,  0,  0],
       [ 1,  1,  1],
       [ 2,  2,  2]])



In [13]:  M = np.apply_along_axis(pow, 1, M, range(n + 1))

In [14]: M
Out[14]: 
array([[ 1, -2,  4],
       [ 1, -1,  1],
       [ 1,  0,  0],
       [ 1,  1,  1],
       [ 1,  2,  4]])
Marcin
  • 215,873
  • 14
  • 235
  • 294