""" ___ """
from scipy.optimize import root
import numpy as np
LENGTH = 3
def process(x):
return x[0, 0] + x[0, 1] * 5
def draw(process, length):
""" """
X = np.matrix(np.random.normal(0, 10, (length, 2)))
y = np.matrix([process(x) for x in X])
y += np.random.normal(3, 1, len(y))
return y.T, X.T
def maximum_likelyhood(y, X):
def objective(b):
return (X.T * (y - X * b.T))
x0 = np.matrix([0, 0])
res = root(objective, x0=x0)
return res.x
y, X = draw(process, LENGTH)
X = X.transpose()
b = np.matrix([[0], [1]])
print maximum_likelyhood(y, X)
produces a
Traceback (most recent call last):
File "ml.py", line 33, in <module>
maximum_likelyhood(y, X)
File "ml.py", line 26, in maximum_likelyhood
res = root(objective, x0=x0)
File "/usr/local/lib/python2.7/dist-packages/scipy/optimize/_root.py", line 168, in root
sol = _root_hybr(fun, x0, args=args, jac=jac, **options)
File "/usr/local/lib/python2.7/dist-packages/scipy/optimize/minpack.py", line 193, in _root_hybr
ml, mu, epsfcn, factor, diag)
ValueError: object too deep for desired array
I can't even gasp what the problem is is it in the b which goes into the objective
function? or is it in its output?
The problem is that fsolve and root do not accept matrixes as return value of the objective function.
For example this is a solution of above problem:
def maximum_likelyhood(y, X):
def objective(b):
b = np.matrix(b).T
return np.transpose(np.array((X.T * (y - X * b))))[0]
x0 = (1, 1)
res = root(objective, x0=x0)
return res.x
Related
I want to use scipy.optimize.minimize on a function with an array type variable input. This is what I hope to do.
I have the following signal,
import numpy as np
time = np.linspace(0, 1, 501)
data = np.cos(2 * np.pi * 4 * time) + np.cos(2 * np.pi * 9 * time) + np.cos(2 * np.pi * 20 * time)
noise = np.sqrt(1 / 25) * np.random.randn(501)
signal = data + noise
and I am hoping to find a curve fit for this signal. Since I created the data myself, I know that a sum of cosine functions will work for this. So the function that I hope to optimize is the following:
def cos_sum(x, P):
assert isinstance(P, np.ndarray)
assert P.shape[0] == P.shape[1]
sums = []
for param in P:
a, b, c = param
sums.append(a * np.cos(b * (x - c)))
sums = np.array(sums)
return np.sum(sums, axis=0)
In order to use minimize to find the correct parameters, I create this residual function.
def resid(params, x):
assert isinstance(params, np.ndarray)
fit = cos_sum(x, params)
residual = np.sqrt(np.mean(np.abs(fit - signal)) ** 2)
return residual
I now need to create a guess. Since I already know how the signal was created, I made the following guess:
guess_A = np.random.normal(1, .2, size=3)
guess_B = 2 * np.pi * np.array([4, 9, 20], dtype=float)
guess_C = np.random.normal(0, .2, size=3)
guess = np.array([guess_A, guess_B, guess_C]).T
However, I am unable to run the following:
from scipy.optimize import minimize
optimization = minimize(resid, guess, args=(time))
and I receive the following error:
Traceback (most recent call last):
File "/Users/nickeisenberg/GitRepos/Python_Misc/Misc/minimize_curvefit_vector_variables.py", line 70, in <module>
optimization = minimize(resid, guess, args=(time))
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/scipy/optimize/_minimize.py", line 676, in minimize
res = _minimize_bfgs(fun, x0, args, jac, callback, **options)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/scipy/optimize/_optimize.py", line 1296, in _minimize_bfgs
sf = _prepare_scalar_function(fun, x0, jac, args=args, epsilon=eps,
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/scipy/optimize/_optimize.py", line 263, in _prepare_scalar_function
sf = ScalarFunction(fun, x0, args, grad, hess,
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/scipy/optimize/_differentiable_functions.py", line 158, in __init__
self._update_fun()
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/scipy/optimize/_differentiable_functions.py", line 251, in _update_fun
self._update_fun_impl()
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/scipy/optimize/_differentiable_functions.py", line 155, in update_fun
self.f = fun_wrapped(self.x)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/scipy/optimize/_differentiable_functions.py", line 137, in fun_wrapped
fx = fun(np.copy(x), *args)
File "/Users/nickeisenberg/GitRepos/Python_Misc/Misc/minimize_curvefit_vector_variables.py", line 53, in resid
fit = cos_sum(x, params)
File "/Users/nickeisenberg/GitRepos/Python_Misc/Misc/minimize_curvefit_vector_variables.py", line 30, in cos_sum
assert P.shape[0] == P.shape[1]
IndexError: tuple index out of range
Is this possible to do?
The problem is that minimize treats parameters as 1D array. Adding print just before failing assert shows, that it reshaped guess array to 1D array.
Changing cos_sum so that it accepts 1D array of params fixes this problem. Here is the code.
def cos_sum(x, P):
assert isinstance(P, np.ndarray)
sums = []
for i in range(0, P.shape[0], 3):
a, b, c = P[i], P[i+1], P[i+2]
sums.append(a * np.cos(b * (x - c)))
sums = np.array(sums)
return np.sum(sums, axis=0)
Result:
optimization = minimize(resid, guess, args=(time))
print(optimization.x)
[ 0.96805816 25.1679919 0.25020317 1.00261543 56.44511497
0.77872223 1.00966167 125.71622787 0.55004217]
plt.figure(figsize=(8, 4))
plt.plot(data)
plt.plot([cos_sum(t, optimization.x) for t in time], 'C1--')
plt.show()
def fun(z):
g = np.zeros(4 * N)
for i in range(4 * N):
f = np.zeros(4 * N)
for j in range(4 * N):
f[i] = f[i] + M_kk[i][j] * z[j] * np.arcsinh(w_c / z[j])
g[i] = f[i] - z[i]
return(g)
z = fsolve(fun, dk)
When solving the equation, it reports the error: Cannot cast array data from dtype('complex128') to dtype('float64') according to the rule 'safe'. How can I solve this issue?
ComplexWarning: Casting complex values to real discards the imaginary part
f[i] = f[i] + M_kk[i][j] * z[j] * np.arcsinh(w_c / z[j])
ComplexWarning: Casting complex values to real discards the imaginary part
g[i] = f[i] - z[i]
Traceback (most recent call last):
File "C:\Users\AppData\Local\Programs\Python\Python310\Lib\site-packages\simple test.py", line 112, in <module>
z = fsolve(fun, dk)
File "C:\Users\AppData\Local\Programs\Python\Python310\Lib\site-packages\scipy\optimize\_minpack_py.py", line 160, in fsolve
res = _root_hybr(func, x0, args, jac=fprime, **options)
File "C:\Users\AppData\Local\Programs\Python\Python310\Lib\site-packages\scipy\optimize\_minpack_py.py", line 237, in _root_hybr
retval = _minpack._hybrd(func, x0, args, 1, xtol, maxfev,
TypeError: Cannot cast array data from dtype('complex128') to dtype('float64') according to the rule 'safe'
I am doing a project, where I want to use Euler's Method to show a solution to this Second Order Different equation
0=y''+y'+9.81y
So I started by changing the second-order into a system of first-order equations
y'=u, u'=f(t,y,u)
With initial condition
y(0)=180, u(0)=0
So I get two equation in the end
y[n + 1] = y[n] + u[n] * (t[n + 1] - t[n]), u[n + 1] = u[n] + f(u[0], y[n], t[0]) * (t[n + 1] - t[n])
This is my code
import numpy as np
import matplotlib.pyplot as plt
def odeEuler(f, y0, u0, t):
y = np.zeros(len(t))
u = np.zeros(len(t))
y[0] = y0
u[0] = u0
for n in range(0, len(t) - 1):
y[n + 1] = y[n] + u[n] * (t[n + 1] - t[n])
u[n + 1] = u[n] + f(u[0], y[n], t[0]) * (t[n + 1] - t[n])
return y, u
t = np.linspace(0, 100)
y0 = 180
u0 = 0
f = lambda u, y, t: -9.81 * y - u
y = odeEuler(f, y0, u0, t)
plt.plot(t, y, 'b.-')
plt.legend(['Euler'])
plt.axis([0, 100, 0, 200])
plt.grid(True)
plt.show()
However, when I run the code, it give me the error
Traceback (most recent call last):
File "/Users/huangy15/PycharmProjects/Draft/Damped Driven Pendulum/Praying this works.py", line 22, in <module>
plt.plot(t, y, 'b.-')
File "/Users/huangy15/PycharmProjects/Draft/Damped Driven Pendulum/venv/lib/python3.7/site-packages/matplotlib/pyplot.py", line 3021, in plot
**({"data": data} if data is not None else {}), **kwargs)
File "/Users/huangy15/PycharmProjects/Draft/Damped Driven Pendulum/venv/lib/python3.7/site-packages/matplotlib/axes/_axes.py", line 1605, in plot
lines = [*self._get_lines(*args, data=data, **kwargs)]
File "/Users/huangy15/PycharmProjects/Draft/Damped Driven Pendulum/venv/lib/python3.7/site-packages/matplotlib/axes/_base.py", line 315, in __call__
yield from self._plot_args(this, kwargs)
File "/Users/huangy15/PycharmProjects/Draft/Damped Driven Pendulum/venv/lib/python3.7/site-packages/matplotlib/axes/_base.py", line 501, in _plot_args
raise ValueError(f"x and y must have same first dimension, but "
ValueError: x and y must have same first dimension, but have shapes (50,) and (2, 50)
Can anyone help me check if my idea works, and if not, what other approaches I can take? Thanks!
Your odeEuler function is returning two variables: y and u, you need to select just one of them to plot.
Store the output of the function in two different variables will solve the problem:
y, u = odeEuler(f, y0, u0, t)
I have the following system of 2 matricial equations where a and b are unknown vectors with for each 7 components. D, D1, D2, P1, P2, F1, F2 are matrices (7x7).
# define the equations
def f(x):
a = np.zeros(7)
b = np.zeros(7)
for i in range(7):
a[i] = x[i]
b[i] = x[7+i]
# Looking for an endomorphism that has D eigen values
D = a**2*D1 + b**2*D2
eq1 = np.dot(P1.T*a**2,P1) + np.dot(P1.T*a,b*P2) + np.dot(P2.T*b,a*P1) + np.dot(P2.T*b**2,P2) - np.eye(7)
eq2 = np.dot(F1,a*P1) + np.dot(F1,b*P2) + np.dot(F2,a*P1) + np.dot(F2,b*P2) - np.dot(a*P1 + b*P2,D)
return np.array([eq1,eq2])
# inital guess
x0 = np.ones(14)
print('x0 = ', x0)
# solving
x = fsolve(f, x0)
print(x)
Unfortunately, at the execution, I get :
Traceback (most recent call last):
File "compute_solving_Matricial_Equations_with_vectors_a_and_b_unknown.py", line 110, in <module>
x = fsolve(f, x0)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/minpack.py", line 139, in fsolve
res = _root_hybr(func, x0, args, jac=fprime, **options)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/minpack.py", line 196, in _root_hybr
shape, dtype = _check_func('fsolve', 'func', func, x0, args, n, (n,))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/minpack.py", line 32, in _check_func
raise TypeError(msg)
TypeError: fsolve: there is a mismatch between the input and output shape of the 'func' argument 'f'.
I tried previously by doing at the end of f function :
return np.array([eq1,eq2].ravel()
instead of return np.array([eq1,eq2].
But I get the same error. What might be wrong here?
I am handling with (7x7) matrices in my 2 equations but I have only 14 unknown (7 components for vector a and 7 for vector b).
Update 1
Following the advice of #Warren Weckesser, I did to check:
# define the equations
def f(x):
a = np.zeros(7)
b = np.zeros(7)
for i in range(7):
a[i] = x[i]
b[i] = x[7+i]
# Looking for an endomorphism that has D eigen values
#D = D1 + D2
D = a**2*D1 + b**2*D2
eq1 = np.dot(P1.T*a**2,P1) + np.dot(P1.T*a,b*P2) + np.dot(P2.T*b,a*P1) + np.dot(P2.T*b**2,P2) - np.eye(7)
eq2 = np.dot(F1,a*P1) + np.dot(F1,b*P2) + np.dot(F2,a*P1) + np.dot(F2,b*P2) - np.dot(a*P1 + b*P2,D)
print(' shape(a) = ', np.shape(a))
print(' shape(b) = ', np.shape(b))
#return np.array([eq1,eq2]).ravel()
return np.concatenate((eq1, eq2))
and get as output :
Traceback (most recent call last):
File "compute_solving_Matricial_Equations_with_vectors_a_and_b_unknown_FOR_STACKOVER.py", line 89, in <module>
shape(a) = (7,)
shape(b) = (7,)
x = fsolve(f, x0)
File "/opt/intel/intelpython3/lib/python3.7/site-packages/scipy/optimize/minpack.py", line 147, in fsolve
res = _root_hybr(func, x0, args, jac=fprime, **options)
File "/opt/intel/intelpython3/lib/python3.7/site-packages/scipy/optimize/minpack.py", line 213, in _root_hybr
shape, dtype = _check_func('fsolve', 'func', func, x0, args, n, (n,))
File "/opt/intel/intelpython3/lib/python3.7/site-packages/scipy/optimize/minpack.py", line 40, in _check_func
raise TypeError(msg)
TypeError: fsolve: there is a mismatch between the input and output shape of the 'func' argument 'f'.Shape should be (14,) but it is (14, 7).
As you can see, it shows one time the print of shape(a) and shape(b) before failing.
I am currently using Python to solve a function with the rk method. r8_rkf45 is a file, which helps to plot the function (http://people.sc.fsu.edu/~jburkardt/py_src/rkf45/rkf45.py).
import numpy as np
import matplotlib.pyplot as plt
from numpy import zeros, linspace, exp, sqrt
from rkf45 import *
from r8_rkf45 import *
def rungekutta(ode2, x0, t, n):
n = 200
z = zeros(n)
a = zeros(n)
f = ode2
neqn = 1
abserr = sqrt(finfo(double).eps)
relerr = sqrt(finfo(double).eps)
flag = 1
t_start = 0.0
t_stop = 10.0
t_out = t = 0.0
y = np.array([0.0])
yp[t, y] = ode2[t, y]
for i_step in xrange(0, n - 1):
t = ((n - i_step + 1) * t_start + (i_step - 1) * t_stop) / (n)
t_out = ((n - i_step) * t_start + (i_step) * t_stop) / (n)
y, yp, t = r8_rkf45(ode2, neqn, y, yp, t, t_out, relerr, abserr, flag)
z[i_step - 1] = t
a[i_step - 1] = y
def ode2(x0, t):
alpha = -1
xp = -alpha * x0
return xp
def main():
n = 200
c, b = (0.0, 10.0)
x0 = 1.0
t = linspace(c, b, n)
y = np.array([0.0])
yp[t, y] = ode2[t, y]
plt.plot()
result_rungekutta = rungekutta(yp, x0, t, n)
plt.plot(t, result_rungekutta, "r")
plt.xlabel(t)
plt.ylabel(xp)
plt.legend("Runge-Kutta")
plt.show()
if __name__ == "__main__":
main()
But I still get a Traceback:
Traceback (most recent call last):
File "C:/Python27/idea.py", line 50, in <module>
main()
File "C:/Python27/idea.py", line 40, in main
yp [t,y]= ode2 [t, y]
TypeError: 'function' object has no attribute '__getitem__'
What am I doing wrong?
ode2 is a function, not a list (or other object that has members that can be accessed via indices). Try, yp [t,y]= ode2(t, y)
You need to call a function with ():
yp [t,y]= ode2(t, y)