diff --git a/gd.py b/gd.py index d0a49ab8c71a2d3b69837d0373bded9d0c890849..6cab80067bf4997800ff06ebb98bb939ae4bfffb 100644 --- a/gd.py +++ b/gd.py @@ -5,6 +5,8 @@ from typing import Callable import matplotlib.pyplot as plt from matplotlib.colors import LogNorm +MAX_ITER = 1e5 + def symb_grad_2d(f: Function) -> (Function, Function): return f.diff(x), f.diff(y) @@ -21,7 +23,7 @@ def callable_func(f: Function) -> Callable[[float, float], float]: def base_gd(f: Function, init_pt: list[float], lr: float) -> \ - float: + pd.DataFrame: df = pd.DataFrame(columns=['x', 'y', 'Cost', 'NormGrad']) partialx, partialy = callable_grad_2d(f) @@ -32,16 +34,16 @@ def base_gd(f: Function, init_pt: list[float], lr: float) -> \ f_call = callable_func(f) - while iter < 1e4: + while iter < MAX_ITER: if np.linalg.norm(grad) < 1e-6: break grad = np.array([partialx(x, y), partialy(x, y)]) df.loc[iter] = [x, y, f_call(x, y), np.linalg.norm(grad)] - step = -lr * grad + step = lr * grad - x += step[0] - y += step[1] + x -= step[0] + y -= step[1] iter += 1 @@ -49,7 +51,7 @@ def base_gd(f: Function, init_pt: list[float], lr: float) -> \ def momentum_gd(f: Function, init_pt: list[float], lr: float, momentum: float)\ - -> float: + -> pd.DataFrame: df = pd.DataFrame(columns=['x', 'y', 'Cost', 'NormGrad']) partialx, partialy = callable_grad_2d(f) @@ -62,7 +64,7 @@ def momentum_gd(f: Function, init_pt: list[float], lr: float, momentum: float)\ step = np.array([0, 0]) - while iter < 1e4: + while iter < MAX_ITER: if np.linalg.norm(grad) < 1e-6: break @@ -80,7 +82,7 @@ def momentum_gd(f: Function, init_pt: list[float], lr: float, momentum: float)\ def nesterov_gd(f: Function, init_pt: list[float], lr: float, momentum: float)\ - -> float: + -> pd.DataFrame: df = pd.DataFrame(columns=['x', 'y', 'Cost', 'NormGrad']) partialx, partialy = callable_grad_2d(f) @@ -93,7 +95,7 @@ def nesterov_gd(f: Function, init_pt: list[float], lr: float, momentum: float)\ step = np.array([0, 0]) - while iter < 1e4: + while iter < MAX_ITER: grad = np.array([partialx(x, y), partialy(x, y)]) if np.linalg.norm(grad) < 1e-6: break @@ -113,7 +115,7 @@ def nesterov_gd(f: Function, init_pt: list[float], lr: float, momentum: float)\ def adam_gd(f: Function, init_pt: list[float], lr: float)\ - -> float: + -> pd.DataFrame: df = pd.DataFrame(columns=['x', 'y', 'Cost', 'NormGrad']) partialx, partialy = callable_grad_2d(f) @@ -130,8 +132,7 @@ def adam_gd(f: Function, init_pt: list[float], lr: float)\ iter = 0 grad = np.array([partialx(x, y), partialy(x, y)]) - while iter < 1e4: - iter += 1 + while iter < MAX_ITER: grad = np.array([partialx(x, y), partialy(x, y)]) if np.linalg.norm(grad) < 1e-6: break @@ -163,12 +164,12 @@ def adam_gd(f: Function, init_pt: list[float], lr: float)\ if __name__ == "__main__": x, y = symbols('x y') - # f: Function = x**2 + 5 * y**2 + f: Function = x**2 + 7 * y**2 # f: Function = 1 - exp(-10 * x**2 - y**2) # f: Function = x**2 * y - 2 * x * y**3 + 3 * x * y + 4 # Rosenbrock(x, y) - # f: Function = (1 - x)**2 + 100 * (y - x**2)**2 + # f: Function = (1 - x)**2 + 1 * (y - x**2)**2 # Beale(x, y) # f: Function = (1.5 - x + x * y)**2 + (2.25 - x + x * @@ -178,17 +179,15 @@ if __name__ == "__main__": # f: Function = (x + 2 * y - 7)**2 + (2 * x + y - 5)**2 # Ackley(x, y) - f: Function = -20.0 * exp(-0.2 * sqrt(0.5 * (x**2 + y**2))) - \ - exp(0.5 * (cos(2 * pi * x) + cos(2 * pi * y))) + exp(1) + 20 + # f: Function = -20.0 * exp(-0.2 * sqrt(0.5 * (x**2 + y**2))) - \ + # exp(0.5 * (cos(2 * pi * x) + cos(2 * pi * y))) + exp(1) + 20 f_call = callable_func(f) LR = 1e-2 MOMENTUM = 0.9 - plot_range = (10, 10) - - # init_pt = [1, 1] + plot_range = (7, 7) init_pt = np.array([np.random.randint(-plot_range[0], plot_range[0] + 1), np.random.randint(-plot_range[1], plot_range[1] + 1)]) @@ -212,7 +211,7 @@ if __name__ == "__main__": fig = plt.figure(1) ax = plt.axes(projection='3d') ax.plot_surface(X, Y, Z, cmap='jet', rstride=1, - cstride=1, norm=LogNorm(), alpha=0.2) + cstride=1, norm=LogNorm(), alpha=0.4) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_zlabel('z')