Reputation: 3
I want to generate a 3-D array by assigning an array to an array.
Following are codes written by me.
import numpy as np
def func01(a):
b = np.array([[a, 3],
[4, 5]])
return b
a = np.array([1, 2])
b = func01(a)
print(b)
Originally, I wrote this code expecting the following output.
[[[1 3]
[4 5]]
[[2 3]
[4 5]]]
However, the following output is obtained.
[[array([1, 2]) 3]
[4 5]]
Could someone give me a solution?
My goal is to curve fit a function involving matrix calculation by SciPy.
I want to perform the curve fit for following function.
import numpy as np
import scipy.optimize
def func01(A, k):
b1 = np.array([[A[0], 3],
[4, 5]])
b2 = np.array([[A[1], 3],
[4, 5]])
B = np.dot(b1, b2)
w, v = np.linalg.eig(B)
C = w[np.argmax(w)] * k
return C
x = np.array([173, 273, 373])
y = np.array([0.1, 0.2, 0.3])
xy = np.append([x],[y],axis=0)
z = np.array([0.023, 0.027, 0.031])
k =0.00005 # initial value
para_opt, cov = scipy.optimize.curve_fit(func01, xy, z, k)
print(para_opt[0])
I can get the value with a simple variable assignment in this function.
k = 0.0005
A = np.array([1,2])
C = func01(A, k)
print(C)
However, I cannot perform the curve fit with SciPy. When I used the SciPy, the following values were assigned to b1 above.
[[array([173., 273., 373.]) 3]
[4 5]]
Therefore, I wanted to know how to get the following matrix.
[[[173 3]
[4 5]]
[[173 3]
[4 5]]]
[[173 3]
[4 5]]]
Upvotes: 0
Views: 62
Reputation: 31011
Try the following function:
def func01(a):
n = len(a)
b = np.tile(np.array([[0, 3], [4, 5]]), (n,1)).reshape(-1,2,2)
b[:,0,0] = a
return b
It gives proper results regardless of the length of a. Furthermore, a can be either a list or a 1-D Numpy array.
To test this function, run:
a = np.array([11, 12, 13])
func01(a)
getting:
array([[[11, 3],
[ 4, 5]],
[[12, 3],
[ 4, 5]],
[[13, 3],
[ 4, 5]]])
Upvotes: 0
Reputation: 231738
In [210]: res = np.zeros((2,2,2),int)
In [211]: res[:] = np.array([[0,3],[4,5]])
In [212]: res
Out[212]:
array([[[0, 3],
[4, 5]],
[[0, 3],
[4, 5]]])
In [213]: res[:,0,0]=[1,2]
In [214]: res
Out[214]:
array([[[1, 3],
[4, 5]],
[[2, 3],
[4, 5]]])
Tell us about curve_fit
. What does it expect with regards to the arguments - type and shape? Do your arguments fit? As written your function expects A
to have shape (2,). Is that what you are getting? Why, or why not?
(I could look up curve_fit
docs, but I'd rather you did some that leg work. You need the debugging practice :)
So your arrays are:
In [216]: xy
Out[216]:
array([[1.73e+02, 2.73e+02, 3.73e+02],
[1.00e-01, 2.00e-01, 3.00e-01]])
In [217]: z
Out[217]: array([0.023, 0.027, 0.031])
And apparently you want to call func01
with one column of xy
:
In [219]: func01(xy[:,0],.00005)
Out[219]: 0.00687966968797453
to work with all columns we can start with an straight forward iteration:
In [220]: def foo(A,k):
...: return np.array([func01(A[:,i],k) for i in range(A.shape[1])])
In [222]: foo(xy,.00005)
Out[222]: array([0.00687967, 0.00921688, 0.0120737 ])
And using that in curve_fit
:
In [223]: k =0.00005 # initial value
In [226]: optimize.curve_fit(foo, xy, z, k)
Out[226]: (array([0.00014051]), array([[1.04449717e-10]]))
A further step is to modify the function so it works with 2d xy
without that iteration. But for a start we need a clear working example. It's always easier to improve working code that we can check our answers against.
Now that we have reference we can try to "vectorize" the function - step by step. We need to do more than generate a 3d array, I think.
Looks like the b1.dot(b2)
and following needs to be a "batched" operation, so lets use @
:
In [228]: def func02(A, k):
...: bb = np.zeros((2,A.shape[1],2,2))
...: for i in range(A.shape[1]):
...: bb[0,i] = np.array([[A[0,i], 3],
...: [4, 5]])
...: bb[1,i] = np.array([[A[1,i], 3],
...: [4, 5]])
...:
...: #B = np.dot(b1, b2)
...: B = bb[0] @ bb[1]
...: w, v = np.linalg.eig(B)
...: C = w[np.argmax(w, axis=-1)] * k
...: return C
...:
In [230]: func02(xy,.00005)
Out[230]:
array([[ 0.00921688, -0.00403688],
[-0.00356467, 0.00687967],
[-0.00356467, 0.00687967]])
Not right. Let's a shape print:
In [231]: def func02(A, k):
...: bb = np.zeros((2,A.shape[1],2,2))
...: for i in range(A.shape[1]):
...: bb[0,i] = np.array([[A[0,i], 3],
...: [4, 5]])
...: bb[1,i] = np.array([[A[1,i], 3],
...: [4, 5]])
...:
...: #B = np.dot(b1, b2)
...: B = bb[0] @ bb[1]
...: w, v = np.linalg.eig(B)
...: print(B.shape, w.shape)
...: C = w[np.argmax(w, axis=-1)] * k
...: return C
...:
...:
In [232]:
In [232]: func02(xy,.00005)
(3, 2, 2) (3, 2)
Out[232]:
array([[ 0.00921688, -0.00403688],
[-0.00356467, 0.00687967],
[-0.00356467, 0.00687967]])
The w
indexing needs tweaking:
In [233]: def func02(A, k):
...: bb = np.zeros((2,A.shape[1],2,2))
...: for i in range(A.shape[1]):
...: bb[0,i] = np.array([[A[0,i], 3],
...: [4, 5]])
...: bb[1,i] = np.array([[A[1,i], 3],
...: [4, 5]])
...:
...: #B = np.dot(b1, b2)
...: B = bb[0] @ bb[1]
...: w, v = np.linalg.eig(B)
...: print(B.shape, w.shape)
...: C = w[:, np.argmax(w, axis=-1)] * k
...: return C
...:
...:
In [234]: func02(xy,.00005)
(3, 2, 2) (3, 2)
Out[234]:
array([[ 0.00687967, -0.00356467, -0.00356467],
[-0.00403688, 0.00921688, 0.00921688],
[-0.0040287 , 0.0120737 , 0.0120737 ]])
The correct values are on the diagonal, so we need another change to the indexing:
In [235]: def func02(A, k):
...: n = A.shape[1]
...: bb = np.zeros((2,n,2,2))
...: for i in range(n):
...: bb[0,i] = np.array([[A[0,i], 3],
...: [4, 5]])
...: bb[1,i] = np.array([[A[1,i], 3],
...: [4, 5]])
...:
...: #B = np.dot(b1, b2)
...: B = bb[0] @ bb[1]
...: w, v = np.linalg.eig(B)
...: print(B.shape, w.shape)
...: C = w[np.arange(n), np.argmax(w, axis=-1)] * k
...: return C
...:
...:
In [236]: func02(xy,.00005)
(3, 2, 2) (3, 2)
Out[236]: array([0.00687967, 0.00921688, 0.0120737 ])
That matches foo
. So works in the curvefit:
In [237]: optimize.curve_fit(func02, xy, z, k)
(3, 2, 2) (3, 2)
...
(3, 2, 2) (3, 2)
Out[237]: (array([0.00014051]), array([[1.04449717e-10]]))
Now that we have the last part of func02
right, we can address your original 3d array issue.
Using the array construction I started with:
In [240]: def func02(A, k):
...: n = A.shape[1]
...: bb = np.zeros((2,n,2,2))
...: bb[:] = np.array([[0,3],[4,5]])
...: bb[:,:,0,0] = A
...: B = bb[0] @ bb[1]
...: w, v = np.linalg.eig(B)
...: C = w[np.arange(n), np.argmax(w, axis=-1)] * k
...: return C
...:
In [241]: func02(xy,.00005)
Out[241]: array([0.00687967, 0.00921688, 0.0120737 ])
Upvotes: 1