I am new user to Python.
I want to add many exponential functions, and then take (and store in memory) the logarithm of the result. (Side note : I am doing this because the sum of the exponential functions is very large so storing the log value of this result is a workaround). Can anyone help me use this numpy function https://numpy.org/doc/stable/reference/generated/numpy.logaddexp.html
In the below code I have a 2 x 2 matrix M and a 2 dimensional vector v. I want to first add v the columns of M. So in the below code the result should be
[[11, 22], [13, 24]]
Then I want to take the exponential of each value and sum across the rows (ending up with a vector of length 2), and storing the logarithm of the result. However the below code outputs a matrix and I cant work out how to use the "out=None" imput for the logaddexp function.
import numpy as np
M = np.array([[1, 2], [3, 4]])
v = np.array([10, 20])
result = np.logaddexp(M, v[None, :])
CodePudding user response:
The function np.logaddexp()
performs an elementwise operation. In your case, you need the addition to be performed along a given axis. Using some basic functions, you can try the following.
import numpy as np
M = np.array([[1, 2], [3, 4]]) # '2 x 2' array
v = np.array([[10, 20]]) # '1 x 2' array
sum_Mv = M v # '2 x 2' array
result = np.log(np.sum(np.exp(sum_Mv), axis=1))
Change the 'axis' parameter if needed.
If you still want to use np.logaddexp()
, you can split the summed matrix into two halves and perform the operation as shown below.
result = np.logaddexp(sum_Mv[:, 0], sum_Mv[:, 1])
CodePudding user response:
TLDR:
import numpy as np
M = np.array([[1, 2], [3, 4]])
v = np.array([10, 20])
result = np.logaddexp.reduce(M v, axis=___)
Fill in ___ depending on what "sum across the rows" means
Consider the difference between np.add
and np.sum
.
np.add
, much like the operator, always takes in 2 arguments, x1 and x2, and adds them together.np.add
is a numpy ufunc. If x1 or x2 is an array_like, then the arguments are broadcast together.np.sum
always takes in 1 argument, typically an array_like of items, and performs a summation of all of the elements in the array_like. This is essentially equivalent to iteratively taking an element from the array_like and repeatedly callingnp.add
with that element on a running result variable. The running result variable is initialized with 0.
Similarly, what np.sum
is to np.add
, np.prod
is to np.multiply
(with running result initalized as 1).
Every np.ufunc
(such as np.add
and np.multiply
, but also np.logaddexp
), comes with a reduce
method and an accompanying identity
property that is used as initialization for the running result.
np.add.reduce
is exactly equivalent to np.sum
. np.multiply.reduce
is exactly equivalent to np.prod
.
What you're looking to do is a log-sum-exp
; but numpy only offers np.logaddexp
. As such, you can use np.logaddexp.reduce
to get the required functionality. Confusion arises from the fact that you're adding M
and v
as well as adding exponential terms together. You can simply perform the M v
operation first, and pass the resulting array (the intermediate result in your question), to np.logaddexp.reduce
. Note that M v
is equivalent to M v[None, :]
in this case due to numpy's broadcasting rules.