1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
|
import numpy as np
def linear_solve(a,b):
#not what is important
return np.matmul(np.linalg.inv(a), b)
def S(f, y, x, beta):
v = y-f(x, beta)
return np.dot(v,v)
def run(y, x, f, jac):
MAX_ITER = 50
MAX_K = 20
eps = 1e-7
n_steps = 0
err = 1e5
lambd = 1 #should be 0.01 according to https://damien-forthomme.developpez.com/tutoriels/matlab/ajustement-equations-non-lineaires/
mu = 2
beta = [1,1]
J = computeJacobian(x, beta)
I = np.eye(len(beta))
while n_steps<MAX_ITER and err > eps:
left = np.matmul(J.T,J)+lambd*I
right = np.dot(J.T, y-f(x, beta))
delta = linear_solve(left, right)
err1 = S(f,y,x, beta+delta)
lambd2 = lambd / mu
left2 = np.matmul(J.T,J)+lambd2*I
delta2 = linear_solve(left2, right)
err2 = S(f,y,x, beta+delta2)
if err2 < err:
lambd = lambd2
err = err2
beta += delta2
elif err1 > err:
lambdk = lambd2
i = 0
while i < MAX_K:
lambdk = lambdk * mu
leftk = np.matmul(J.T,J)+lambdk*I
deltak = linear_solve(leftk, right)
errk = S(f,y,x, beta+deltak)
if errk < err:
lambd = lambdk
err = errk
beta += deltak
break
if i == MAX_K:
print('FAILED to reduce error')
else:
err = err1
beta += delta
n_steps += 1
print('err : ', err, 'beta', beta, 'lambda', lambd)
return [err, beta, n_steps]
def f(x, beta):
return beta[0]*(1-np.exp(-x/beta[1]))
def computeJacobian(x, beta):
J = np.zeros((len(x), 2))
[a, t1] = beta;
dfda = 1 - np.exp(-x/t1)
dfdt1 = -a/(t1*t1)*np.exp(-x/t1)
J[:,0] = dfda
J[:,1] = dfdt1
return J
x=np.array([1,2,3,4,5,6,7,8])
y=f(x, [5,3])
[err, beta, n_steps] = run(y=y, x=x, f=f, jac=computeJacobian)
#we expect beta to be [5,3]... |
Partager