Skip to content

Commit c87b991

Browse files
committed
Add optimizer app (wip)
1 parent a5d495f commit c87b991

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed

apps/optimizers.py

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import marimo
2+
3+
__generated_with = "0.14.10"
4+
app = marimo.App(width="medium")
5+
6+
7+
@app.cell(hide_code=True)
8+
def _():
9+
import marimo as mo
10+
return (mo,)
11+
12+
13+
@app.cell(hide_code=True)
14+
def _(grad_fn1, grad_fn2, mo, toy_function1, toy_function2):
15+
dropdown_dict = mo.ui.dropdown(
16+
options={
17+
"Nice function": (toy_function1, grad_fn1, (-10, 10)),
18+
"Bumpy function": (toy_function2, grad_fn2, (1, 3)),
19+
},
20+
value="Nice function",
21+
label="Pick a function"
22+
)
23+
dropdown_dict
24+
return (dropdown_dict,)
25+
26+
27+
@app.cell(hide_code=True)
28+
def _(mo):
29+
lr_slider = mo.ui.slider(start=0.01, stop=10, step=0.01, label="Step size", show_value=True)
30+
num_iters_slider = mo.ui.slider(start=10, stop=1000, step=1, label="Number of iterations", show_value=True)
31+
x_init_ui = mo.ui.slider(start=-10, stop=10, step=0.1, value=0.0, label="Initial value", show_value=True)
32+
33+
hparams = mo.ui.dictionary({
34+
"num_iters": num_iters_slider,
35+
"lr": lr_slider,
36+
"x_init": x_init_ui
37+
}
38+
)
39+
hparams.vstack()
40+
return (hparams,)
41+
42+
43+
@app.cell(hide_code=True)
44+
def _(f_iterations, mo, np, x_grid, x_iterations, y_grid):
45+
import plotly.graph_objects as go
46+
from plotly.subplots import make_subplots
47+
import matplotlib.cm as cm
48+
import matplotlib.colors as mcolors
49+
import matplotlib
50+
norm = mcolors.Normalize(vmin=0, vmax=len(x_iterations) - 1)
51+
cmap = matplotlib.colormaps["jet"]
52+
colors = [mcolors.to_hex(cmap(norm(i))) for i in range(len(x_iterations))]
53+
54+
fig = make_subplots(rows=2, cols=3, vertical_spacing=0.05, subplot_titles=("Algorithm 1", "Algorithm 2", "Algorithm 3"))
55+
for col in range(1, 4):
56+
fig.add_trace(
57+
go.Scatter(
58+
x=x_grid,
59+
y=y_grid,
60+
mode="lines",
61+
name=f"Plot name {col}",
62+
line=dict(color="black"),
63+
showlegend=False,
64+
),
65+
row=1,
66+
col=col,
67+
)
68+
fig.add_trace(
69+
go.Scatter(
70+
x=x_iterations,
71+
y=f_iterations,
72+
mode="markers+lines",
73+
marker=dict(
74+
size=8,
75+
color=colors
76+
),
77+
line=dict(color="red", width=0.3),
78+
showlegend=False
79+
),
80+
row=1,
81+
col=col
82+
)
83+
for col in range(1, 4):
84+
fig.add_trace(
85+
go.Scatter(
86+
x=np.arange(len(f_iterations)),
87+
y=f_iterations,
88+
mode="lines+markers",
89+
name=f"Plot name {col}",
90+
line=dict(color="black"),
91+
marker=dict(size=4),
92+
showlegend=False,
93+
),
94+
row=2,
95+
col=col,
96+
)
97+
fig.update_layout(height=600, width=1000, title_text="Optimization algorithms")
98+
99+
plot = mo.ui.plotly(fig)
100+
plot
101+
return
102+
103+
104+
@app.cell(hide_code=True)
105+
def _():
106+
import numpy as np
107+
from numpy.typing import NDArray
108+
109+
def toy_function1(x: NDArray[np.float64]) -> NDArray[np.float64]:
110+
return np.log(1.0 + np.exp(x)) + 0.1*x**2
111+
112+
def grad_fn1(x: NDArray[np.float64]) -> NDArray[np.float64]:
113+
sigmoid = 1 / (1 + np.exp(-x))
114+
return sigmoid + 0.2 * x
115+
116+
a = 1.0
117+
def toy_function2(x: NDArray[np.float64]) -> NDArray[np.float64]:
118+
return (x-2)**2 + 0.3*np.sin(10.0*x)
119+
120+
def grad_fn2(x: NDArray[np.float64]) -> NDArray[np.float64]:
121+
return 2.0*(x-2) + 3.0*np.cos(10.0*x)
122+
123+
def toy_function3(x: NDArray[np.float64]) -> NDArray[np.float64]:
124+
return x**6 - 6*x**4 + 9*x**2 + 0.5 * x
125+
126+
def grad_fn3(x: NDArray[np.float64]) -> NDArray[np.float64]:
127+
return 6*x**5 - 24*x**3 + 18*x + 0.5
128+
return NDArray, grad_fn1, grad_fn2, np, toy_function1, toy_function2
129+
130+
131+
@app.cell(hide_code=True)
132+
def _(NDArray, dropdown_dict, hparams, np):
133+
from typing import Callable
134+
135+
objective_fn = dropdown_dict.value[0]
136+
grad_fn = dropdown_dict.value[1]
137+
bounds = dropdown_dict.value[2]
138+
139+
def gradient_descent(n_iters: int, step_size: float, x_init: NDArray[np.float64]) -> NDArray[np.float64]:
140+
x = x_init.copy()
141+
stacked_values = [x]
142+
for _ in range(n_iters):
143+
grad = grad_fn(x)
144+
x = x - step_size * grad
145+
stacked_values.append(x)
146+
return np.array(stacked_values)
147+
148+
x_init = np.array([hparams["x_init"].value])
149+
x_iterations = gradient_descent(hparams["num_iters"].value, hparams["lr"].value, x_init).squeeze()
150+
f_iterations = np.array([objective_fn(xi) for xi in x_iterations]).squeeze()
151+
152+
x_grid = np.linspace(np.minimum(bounds[0], np.min(x_iterations)), np.maximum(bounds[1], np.max(x_iterations)), 1000)
153+
y_grid = objective_fn(x_grid)
154+
155+
return f_iterations, x_grid, x_iterations, y_grid
156+
157+
158+
if __name__ == "__main__":
159+
app.run()

0 commit comments

Comments
 (0)