NeonSamurai's picture
Update Home.py
f5972d3 verified
import streamlit as st
import numpy as np
import pandas as pd
import base64
import plotly.graph_objects as go
st.set_page_config(layout="wide")
# Function parser to evaluate the mathematical function
def parse_function(func_str, x):
try:
return eval(func_str)
except Exception as e:
st.error(f"Error evaluating function: {e}")
return np.zeros_like(x)
# Compute the gradient (derivative) at a point using numerical differentiation
def compute_gradient(func_str, x):
delta = 1e-8
grad = (parse_function(func_str, x + delta) - parse_function(func_str, x)) / delta
return grad
# Streamlit App
def encode_image(image_path):
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode()
def add_bg_from_local(image_file):
encoded_string = encode_image(image_file)
st.markdown(
f"""
<style>
.stApp {{
background-image: url(data:image/{"png"};base64,{encoded_string});
background-size: cover;
background-repeat: no-repeat;
background-attachment: fixed;
}}
</style>
""",
unsafe_allow_html=True
)
add_bg_from_local("Icon/rm183-kul-21.jpg")
st.markdown(
"""
<style>
.reportview-container {
background: "white"
}
</style>
""",
unsafe_allow_html=True
)
st.markdown("""
<style>
body {
font-family: 'Roboto', sans-serif;
}
.stButton>button {
color: white;
border-radius: 8px;
padding: 10px 20px;
font-weight: bold;
transition: background-color 0.3s ease;
}
.stButton>button:hover {
background-color: Black;
border-color: white;
color: white;
}
.sidebar .sidebar-content {
padding: 2rem;
}
.stApp {
font-family: 'Roboto', sans-serif;
}
</style>
""", unsafe_allow_html=True)
file_ = open("Icon/wave-chart-ezgif.com-gif-maker.gif", "rb").read()
base64_gif = base64.b64encode(file_).decode("utf-8")
st.markdown(
f"""
<h1 style='text-align: center; color: Black; margin-top: -50px; padding-top: 0px;'>
Interactive Gradient Descent Visualizer
<img src="data:image/gif;base64,{base64_gif}" alt="Icon" style="width: 85px; margin-right: 10px;">
</h1>
""",
unsafe_allow_html=True
)
st.markdown("""
<p style="color: black;">
Explore how gradient descent works visually and interactively.
Adjust parameters and watch as the algorithm converges towards the minimum of a function.
</p>
""",
unsafe_allow_html=True)
st.sidebar.header("Input Parameters")
# Dropdown menu
function_options = ["x**2", "x**3", "np.sin(x)", "1/x", "Custom Polynomial"]
selected_function = st.sidebar.selectbox("Choose a function:", function_options)
if selected_function == "Custom Polynomial":
func_str = st.sidebar.text_input("Enter custom polynomial in terms of x:", value="x**2 - 4*x + 4")
else:
func_str = st.sidebar.text_input(f"Modify the selected function ({selected_function}):", value=selected_function)
# Initialize session state variables if not already initialized
if "x_vals" not in st.session_state:
st.session_state.x_vals = []
if "y_vals" not in st.session_state:
st.session_state.y_vals = []
if "current_step" not in st.session_state:
st.session_state.current_step = 0
# Input for initial x point and learning rate
initial_x = st.sidebar.number_input("Initial Point (x):", value=0.00)
learning_rate = st.sidebar.number_input("Learning Rate:", value=0.1, step=0.01, format="%.2f")
# Update session state with initial values
if st.session_state.current_step == 0:
st.session_state.x_vals = [initial_x]
st.session_state.y_vals = [parse_function(func_str, initial_x)]
col1, col2 = st.sidebar.columns(2)
if col1.button("Reset Graph"):
st.session_state.x_vals = [initial_x]
st.session_state.y_vals = [parse_function(func_str, initial_x)]
st.session_state.current_step = 0
if col2.button("Next Iteration"):
current_x = st.session_state.x_vals[-1]
grad = compute_gradient(func_str, current_x)
next_x = current_x - learning_rate * grad
st.session_state.x_vals.append(next_x)
st.session_state.y_vals.append(parse_function(func_str, next_x))
st.session_state.current_step += 1
x_vals = np.linspace(-20, 30, 1000)
y_vals = parse_function(func_str, x_vals)
fig = go.Figure()
# Add the function curve to the plot
fig.add_trace(go.Scatter(x=x_vals, y=y_vals, mode='lines', name='Function Curve', line=dict(color='teal')))
# Add the gradient descent steps (if any)
if st.session_state.current_step > 0:
fig.add_trace(go.Scatter(
x=st.session_state.x_vals, y=st.session_state.y_vals,
mode='markers+lines', name='Gradient Descent Steps',
marker=dict(color='red', size=10), line=dict(dash='dash', width=1.5)
))
# Function to draw the tangent line at the current point
def draw_tangent(fig, func_str, x_point):
y_point = parse_function(func_str, x_point)
grad = compute_gradient(func_str, x_point)
tangent_x = np.linspace(-20, 30, 1000)
tangent_y = grad * (tangent_x - x_point) + y_point
fig.add_trace(go.Scatter(
x=tangent_x, y=tangent_y, mode='lines', name=f'Tangent at x={x_point:.2f}',
line=dict(dash='dot', color='green', width=2)
))
fig.add_trace(go.Scatter(
x=[x_point], y=[y_point], mode='markers', name='Tangent Point',
marker=dict(color='blue', size=12, symbol='circle')
))
# Draw tangent at the last gradient descent point
if len(st.session_state.x_vals) > 0:
draw_tangent(fig, func_str, st.session_state.x_vals[-1])
fig.update_layout(
shapes=[
dict(type="line", x0=-20, y0=0, x1=30, y1=0, line=dict(color="black", width=2)),
dict(type="line", x0=0, y0=-110, x1=0, y1=120, line=dict(color="black", width=2))
],
xaxis=dict(
title='x',
range=[-20, 30],
showline=True,
linecolor='black',
linewidth=2,
mirror=True,
ticks='inside',
tickfont=dict(color='black'),
titlefont=dict(color='black'),
),
yaxis=dict(
title='y',
range=[-110, 120],
showline=True,
linecolor='Black',
linewidth=2,
mirror=True,
ticks='inside',
tickfont=dict(color='black'),
titlefont=dict(color='black'),
),
plot_bgcolor= 'rgba(0, 0, 0, 0)',
paper_bgcolor= 'rgba(0, 0, 0, 0)',
font=dict(color='black'),
legend=dict(
font=dict(color='black'),
x=1.05,
xanchor='left',
y=1,
yanchor='top'
),
width=800, height=500,
template="plotly_white",
title="Gradient Descent on the Selected Function",
titlefont=dict(color='black'),
margin=dict(l=50, r=50, t=50, b=50),
)
st.plotly_chart(fig, use_container_width=True)
if st.session_state.current_step > 0:
iteration_data = {
"Iteration": list(range(st.session_state.current_step + 1)),
"x Value": [f"{x_val:.5f}" for x_val in st.session_state.x_vals],
"y Value": [f"{y_val:.5f}" for y_val in st.session_state.y_vals]
}
iteration_df = pd.DataFrame(iteration_data)
st.markdown("<h3 style='color: black;'>Iteration Details</h3>", unsafe_allow_html=True)
st.markdown(
iteration_df.to_html(index=False, escape=False),
unsafe_allow_html=True
)
st.markdown("""
<style>
.dataframe {
color: black;
font-size: 14px;
border-collapse: collapse;
width: 100%;
}
.dataframe th, .dataframe td {
padding: 8px;
text-align: center;
border: 1px solid black;
}
.dataframe th {
background-color: #f2f2f2;
border: 2px solid black;
}
</style>
""", unsafe_allow_html=True)
st.sidebar.subheader("Current Status")
st.sidebar.write(f"Iteration: {st.session_state.current_step}")
st.sidebar.write(f"Current x: {st.session_state.x_vals[-1]:.5f}")
st.sidebar.write(f"Current y: {st.session_state.y_vals[-1]:.5f}")