Hi guys, going through my text book i stumbled upon the following statement (see picture) and decided to test its validity by implementing it in Python.
def objective_fct(point):
"""custom loss function
"""
A = np.array([[1,1],[1,1]])
b = np.array([[4],[2]])
c = np.array([1])
return (point.T@A@point + b.T@point + c).item()
def objective_gradient(point):
return 2*A@point+b
def ag_test(objective_fct,current_point,eta,c,desc_direction):
# computes the Armijo-Goldstein test and returns a boolean value
right = objective_fct(current_point)-c*eta*desc_direction.T@objective_gradient(current_point)
left = objective_fct(current_point-eta*desc_direction)
return (right-left>0)
# starting point, could be a random guess too
theta_0 = np.array([[0],[0]])
def steepest_descent(theta_0,n_steps,eps):
"""
implements the steepest descent algorithm for a quadratic objective function
"""
c = 10**-4
states = [theta_0]
up = upperbound_stepsize(np.array([[1,1],[1,1]]),eps)
step_size,copy = up, up
for t in range(n_steps):
theta_t = states[-1]
while not ag_test(objective_fct,theta_t,step_size,c,objective_gradient(theta_t)):
step_size-=c # shrink the step size
#print(f"Step size: {step_size}")
states.append(theta_t - step_size*objective_fct(theta_t))
step_size = copy # reset the step size to the max
# add a breaking statement if we have redundant calculations
if np.linalg.norm(states[-1]-states[-2],ord=2)<10**-8:
return (states,t)
return states,step_size
steps, n_steps = steepest_descent(theta_0,1000,0.1)
x = []
for k in range(len(steps)):
x.append(steepest_descent(A,b,c,steps[k]))
x