KSaiManikanta/gradient_descent
0
1import streamlit as st2import numpy as np3import plotly.graph_objects as go4import pandas as pd5 6# Title and Description7st.title("Gradient Descent Visualizer with Dynamic Learning Rate ๐")8st.write(9 """10 Visualize the steps of gradient descent on a user-defined function. 11 Adjust parameters like the starting point and learning rate to see how the algorithm converges.12 Change the learning rate dynamically at any step!13 """14)15st.markdown("---")16 17# Safe evaluation of the function18def safe_eval(func_str, x_val):19 """Evaluate the function safely at a given x value."""20 allowed_names = {"x": x_val, "np": np} # Allow only x and numpy21 return eval(func_str, {"_builtins_": None}, allowed_names)22 23# Numerical derivative24def derivative(func_str, x_val, h=1e-5):25 """Compute the derivative using the central difference method."""26 return (safe_eval(func_str, x_val + h) - safe_eval(func_str, x_val - h)) / (2 * h)27 28# Tangent line computation29def tangent_line(func_str, x_val, x_range):30 """Compute the tangent line for the function at a given x value."""31 y_val = safe_eval(func_str, x_val)32 slope = derivative(func_str, x_val)33 return slope * (x_range - x_val) + y_val34 35# Reset session state36def reset_state():37 st.session_state.x = st.session_state.starting_point38 st.session_state.iteration = 039 st.session_state.x_vals = [st.session_state.starting_point]40 st.session_state.y_vals = [safe_eval(st.session_state.func_input, st.session_state.starting_point)]41 st.session_state.history = [{42 "Iteration": 0, 43 "Starting Point": st.session_state.starting_point, 44 "Learning Rate": st.session_state.learning_rate,45 "x": st.session_state.x, 46 "f(x)": st.session_state.y_vals[0]47 }]48 st.session_state.learning_rate = initial_learning_rate # Reset learning rate to initial value49 50# User inputs for the function51st.sidebar.header("Define the Function")52func_input = st.sidebar.text_input(53 "Enter a function of x (e.g., x**2 + x, np.sin(x), etc.):", 54 "x**2 + x", 55 key="func_input", 56 on_change=reset_state57)58 59# Gradient Descent Parameters60st.sidebar.header("Gradient Descent Settings")61 62# Replace slider with number input for Starting Point with high precision63starting_point = st.sidebar.number_input(64 "Starting Point", 65 value=4.0, # Default value66 step=0.1, # Step size for increment/decrement67 format="%.10f", # Allow up to 10 decimal places68 key="starting_point", 69 on_change=reset_state70)71 72# Replace slider with number input for Learning Rate with high precision73initial_learning_rate = st.sidebar.number_input(74 "Initial Learning Rate", 75 value=0.1, # Default value76 step=0.01, # Step size for increment/decrement77 min_value=0.0, # Minimum value78 format="%.10f", # Allow up to 10 decimal places79 key="initial_learning_rate", 80 on_change=reset_state81)82 83# Dynamically update the learning rate with high precision84new_learning_rate = st.sidebar.number_input(85 "New Learning Rate", 86 value=initial_learning_rate, # Default value87 step=0.01, # Step size for increment/decrement88 min_value=0.0, # Minimum value89 format="%.10f" # Allow up to 10 decimal places90)91 92# Initialize session state variables93if "x" not in st.session_state:94 st.session_state.x = starting_point95 st.session_state.iteration = 096 st.session_state.x_vals = [starting_point]97 st.session_state.y_vals = [safe_eval(func_input, starting_point)]98 st.session_state.history = [{99 "Iteration": 0, 100 "Starting Point": starting_point, 101 "Learning Rate": initial_learning_rate,102 "x": starting_point, 103 "f(x)": st.session_state.y_vals[0]104 }]105 st.session_state.learning_rate = initial_learning_rate106 107# Update the learning rate dynamically108if st.session_state.learning_rate != new_learning_rate:109 st.session_state.learning_rate = new_learning_rate110 st.sidebar.success(f"Learning rate updated to {new_learning_rate:.2f}")111 112# Perform the next iteration of gradient descent113if st.button("Next Iteration ๐"):114 try:115 grad = derivative(func_input, st.session_state.x)116 st.session_state.x = st.session_state.x - st.session_state.learning_rate * grad117 st.session_state.iteration += 1118 st.session_state.x_vals.append(st.session_state.x)119 st.session_state.y_vals.append(safe_eval(func_input, st.session_state.x))120 121 # Add the new values to the history122 st.session_state.history.append({123 "Iteration": st.session_state.iteration, 124 "Starting Point": starting_point, 125 "Learning Rate": st.session_state.learning_rate,126 "x": st.session_state.x, 127 "f(x)": st.session_state.y_vals[-1]128 })129 except Exception as e:130 st.error(f"Error: {e}")131 132# Gradient Descent Progress133st.subheader("Progress Overview")134st.write(f"**Iteration:** {st.session_state.iteration}")135st.write(f"**Current x:** {st.session_state.x:.4f}")136st.write(f"**Current f(x):** {st.session_state.y_vals[-1]:.4f}")137st.markdown("---")138 139# Visualization of the function and gradient descent steps140x_plot = np.linspace(-10, 10, 400)141y_plot = [safe_eval(func_input, x) for x in x_plot]142 143fig = go.Figure()144 145# Function curve146fig.add_trace(147 go.Scatter(x=x_plot, y=y_plot, mode="lines", line=dict(color="blue", width=2), name="Function")148)149 150# Gradient descent points151fig.add_trace(152 go.Scatter(153 x=st.session_state.x_vals,154 y=st.session_state.y_vals,155 mode="markers+lines",156 line=dict(color="red", dash="dot"),157 marker=dict(size=8, symbol="circle"),158 name="Gradient Descent Steps"159 )160)161 162# Tangent line at the current point163current_x = st.session_state.x164current_y = safe_eval(func_input, current_x)165tangent_x = np.linspace(current_x - 2, current_x + 2, 100)166tangent_y = tangent_line(func_input, current_x, tangent_x)167 168fig.add_trace(169 go.Scatter(170 x=tangent_x,171 y=tangent_y,172 mode="lines",173 line=dict(color="orange", width=2, dash="dash"),174 name="Tangent Line"175 )176)177 178# Update plot layout179fig.update_layout(180 title="Gradient Descent Visualization with Tangent Lines",181 xaxis_title="x",182 yaxis_title="f(x)",183 template="plotly_white",184 legend=dict(bordercolor="gray", borderwidth=1),185)186 187# Render plot188st.plotly_chart(fig)189# Table of Iterations190st.subheader("Iteration History")191history_df = pd.DataFrame(st.session_state.history)192st.dataframe(history_df, use_container_width=True)