Sem o tensorflow
import numpy as np
from scipy.optimize import minimize, line_search
contaf = 0
contagrad = 0
np.set_printoptions(precision=1)
A funcao f
def f(x):
global contaf
contaf += 1
return x[0]**2 - 102*x[0] + 101*(x[1]**2)- 92*x[1] + 90*(x[2]**2) + 2
O gradiente
def grad(x):
global contagrad
contagrad += 1
g = np.zeros((3))
g[0] = 2*x[0] - 102
g[1] = 202*x[1] - 92
g[2] = 180*x[2]
return g
O erro relativo de 2 pontos
def err(x,xnew):
return np.linalg.norm(xnew-x)/np.linalg.norm(x)
contaf = 0
contagrad = 0
x = np.array([0.5, 0.5, 0.5])
zz = 99.0
while zz > 1.0e-5:
xnew=x-1.0e-6*grad(x)
zz = err(x,xnew)
x = xnew
print("xmin=",x)
print("fmin=",round(f(x),2))
print("chamadas da funcao=",contaf-1)
print("chamadas do gradiente=",contagrad)
print("total de chamadas=", contaf+contagrad-1)
Deu meio errado - o xmin e o fmin estao errados. O que parece que aconteceu é que o passo da decida do gradiente esta tao pequeno que para por causa do erro/diferença relativa. Uma solucao é talvez neste caso diminuir a tolerancia
contaf = 0
contagrad = 0
x = np.array([0.5, 0.5, 0.5])
zz = 99.0
while zz > 1.0e-5/10:
xnew=x-1.0e-6*grad(x)
zz = err(x,xnew)
x = xnew
print("xmin=",x)
print("fmin=",round(f(x),2))
print("chamadas da funcao=",contaf-1)
print("chamadas do gradiente=",contagrad)
print("total de chamadas=", contaf+contagrad-1)
Melhorou mas ainda esta um pouco errado. Diminuindo mais a tolerancia...
contaf = 0
contagrad = 0
x = np.array([0.5, 0.5, 0.5])
zz = 99.0
while zz > 1.0e-5/30:
xnew=x-1.0e-6*grad(x)
zz = err(x,xnew)
x = xnew
print("xmin=",x)
print("fmin=",round(f(x),2))
print("chamadas da funcao=",contaf-1)
print("chamadas do gradiente=",contagrad)
print("total de chamadas=", contaf+contagrad-1)
Melhorou mas o numero de chamadas para o gradiente é enorme!!!
contaf = 0
contagrad = 0
x = np.array([0.5, 0.5, 0.5])
zz = 99.0
while zz > 1.0e-5:
alpha, _, _, _ ,_ ,_ = line_search(f, grad, x, -grad(x))
xnew = x - alpha * grad(x)
zz = err(x,xnew)
x = xnew
print("xmin=",x)
print("fmin=",round(f(x),2))
print("chamadas da funcao=",contaf)
print("chamadas do gradiente=",contagrad)
print("total de chamadas=", contaf+contagrad)
contaf = 0
contagrad = 0
x = np.array([0.5, 0.5, 0.5])
res = minimize(f, x, method="L-BFGS-B", tol=1.0e-5)
print("xmin=",res.x)
print("fmin=",round(f(res.x),2))
print("chamadas da funcao=",contaf)
print("chamadas do gradiente=",contagrad)
print("total de chamadas=", contaf+contagrad)
contaf = 0
contagrad = 0
x = np.array([0.5, 0.5, 0.5])
res = minimize(f, x, method="Nelder-Mead", tol=1.0e-5)
print("xmin=",res.x)
print("fmin=",round(f(res.x),2))
print("chamadas da funcao=",contaf)
print("chamadas do gradiente=",contagrad)
print("total de chamadas=", contaf+contagrad)
import pybobyqa
contaf = 0
contagrad = 0
x = np.array([0.5, 0.5, 0.5])
res = pybobyqa.solve(f, x)
print("xmin=",res.x)
print("fmin=",round(f(res.x),2))
print("chamadas da funcao=",contaf)
print("chamadas do gradiente=",contagrad)
print("total de chamadas=", contaf+contagrad)