CoolFace
Apppublic

trohith89/Gradient-Descent-Visualizer

sourceHugging Faceupdated 2y agoView on Hugging Face
1likes
app.py280 linesDownload Raw Back to root
1import streamlit as st2import numpy as np3import plotly.graph_objects as go4 5# Safe function evaluation6def safe_eval(func_str, x_val):7    """ Safely evaluates the function at a given x value. """8    allowed_names = {"x": x_val, "np": np}9    try:10        return eval(func_str, {"__builtins__": None}, allowed_names)11    except Exception as e:12        raise ValueError(f"Error evaluating the function: {e}")13 14# Function derivative using finite difference method15def derivative(func_str, x_val, h=1e-5):16    """ Numerically compute the derivative of the function at x using finite differences. """17    return (safe_eval(func_str, x_val + h) - safe_eval(func_str, x_val - h)) / (2 * h)18 19# Tangent line equation20def tangent_line(func_str, x_val, x_range):21    """ Compute the tangent line at a given x value. """22    y_val = safe_eval(func_str, x_val)23    slope = derivative(func_str, x_val)24    return slope * (x_range - x_val) + y_val25 26# Callback to reset session state27def reset_state():28    st.session_state.x = st.session_state.starting_point29    st.session_state.iteration = 030    st.session_state.x_vals = [st.session_state.starting_point]31    st.session_state.y_vals = [safe_eval(st.session_state.func_input, st.session_state.starting_point)]32 33# Initialize session state variables34if "func_input" not in st.session_state:35    st.session_state.func_input = "x**2 + x"36if "x" not in st.session_state:37    st.session_state.x = 4.038    st.session_state.iteration = 039    st.session_state.x_vals = [4.0]40    st.session_state.y_vals = [safe_eval(st.session_state.func_input, 4.0)]41 42# Full-width layout43st.set_page_config(layout="wide")44 45# CSS Styles for Borders, Font, Reduced Padding, and Custom Border Color46st.markdown(47    """48    <style>49    * {50        font-family: Cambria, Arial, sans-serif !important;51    }52    h1, h2, h3, h4, h5 {53        text-align: center;54        margin-top: 0;55    }56    input, .stButton button, .stDownloadButton button {57        border: 2px solid #ea445a;58        border-radius: 5px;59        padding: 10px;60    }61    .stInfo, .stSuccess {62        border: 2px solid #ea445a;63        border-radius: 5px;64        padding: 10px;65    }66    .stButton {67        margin-top: 10px;68    }69    /* Reduced Padding at the top */70    .css-1d391kg {71        padding-top: 0.5rem;72    }73    /* Centering the legend in the plot */74    .stPlotlyChart {75        display: block;76        margin: 0 auto;77    }78    /* Adjusting for full width without scrolling */79    .css-1lcbvhc {80        padding-left: 0;81        padding-right: 0;82    }83    /* Custom borders for input fields */84    .stTextInput input, .stNumberInput input {85        border: 2px solid #001A6E;86        border-radius: 5px;87        padding: 10px;88    }89    /* Tooltip styling */90    .tooltip {91        position: relative;92        display: inline-block;93        cursor: pointer;94    }95    .tooltip .tooltiptext {96        visibility: hidden;97        opacity: 0;98        width: 300px;99        background-color: #001A6E;100        color: #fff;101        text-align: center;102        border-radius: 5px;103        padding: 5px;104        position: absolute;105        z-index: 1;106        bottom: 125%; /* Position the tooltip above */107        left: 50%;108        margin-left: -150px;109        transition: opacity 0.3s;110    }111    .tooltip:hover .tooltiptext {112        visibility: visible;113        opacity: 1;114    }115    </style>116    """,117    unsafe_allow_html=True,118)119 120# Page Layout121st.title("๐ŸŒŸ Gradient Descent Visualization Tool ๐ŸŒŸ")122 123col1, col2 = st.columns([1, 2])124 125# Left Section: User Input126with col1:127    st.subheader("๐Ÿ”ง Define Your Function")128 129    # Tooltip with instructions when hovering over the function input label130    st.markdown(131        """132        <div class="tooltip">133            <label for="func_input">Enter a function of 'x':</label>134            <span class="tooltiptext">135                **How to input your function:**136                - Please give the inputs as mentioned below                137                - x^n as  x**n,                138                - sin(x) as np.sin(x)                139                - log(x) as np.log(x),                140                - e^x or exp(x) as np.exp(x).141            </span>142        </div>143        """,144        unsafe_allow_html=True145    )146    147    # Use text input for the user to define a function, but no value argument148    func_input = st.text_input(149        "๐Ÿ‘‡", 150        key="func_input", 151        on_change=reset_state152    )153 154    st.subheader("โš™๏ธ Gradient Descent Parameters")155    starting_point = st.number_input(156        "Starting Point (Xโ‚€)", 157        value=4.0, 158        step=0.1, 159        format="%.2f", 160        key="starting_point", 161        on_change=reset_state162    )163    learning_rate = st.number_input(164        "Learning Rate (ล‹)", 165        value=0.25, 166        step=0.01, 167        format="%.2f", 168        key="learning_rate", 169        on_change=reset_state170    )171 172    col3, col4 = st.columns(2)173    with col3:174        if st.button("๐Ÿ”„ Set Up Function"):175            reset_state()176    with col4:177        if st.button("โ–ถ๏ธ Next Iteration"):178            try:179                grad = derivative(st.session_state.func_input, st.session_state.x)180                st.session_state.x = st.session_state.x - learning_rate * grad181                st.session_state.iteration += 1182                st.session_state.x_vals.append(st.session_state.x)183                st.session_state.y_vals.append(safe_eval(st.session_state.func_input, st.session_state.x))184            except Exception as e:185                st.error(f"โš ๏ธ Error: {str(e)}")186 187# Right Section: Visualization188with col2:189    st.subheader("๐Ÿ“Š Gradient Descent Visualization")190    try:191        # Plot the function and all current and previous gradient descent points192        x_plot = np.linspace(-10, 10, 400)193        y_plot = [safe_eval(st.session_state.func_input, x) for x in x_plot]194 195        fig = go.Figure()196 197        # Function curve198        fig.add_trace(go.Scatter(199            x=x_plot, 200            y=y_plot, 201            mode="lines+markers", 202            line=dict(color="blue", width=2), 203            marker=dict(size=4, color="blue", symbol="circle"),204            name="Function"205        ))206 207        # All gradient descent points (red points without coordinates)208        fig.add_trace(go.Scatter(209            x=st.session_state.x_vals,210            y=st.session_state.y_vals,211            mode="markers",212            marker=dict(color="red", size=10),213            name="Gradient Descent Points"214        ))215 216        # Tangent line at the current gradient descent point217        current_x = st.session_state.x218        tangent_x = np.linspace(-10, 10, 200)  # Adjusting range to cover entire plot219        tangent_y = tangent_line(st.session_state.func_input, current_x, tangent_x)220        fig.add_trace(go.Scatter(221            x=tangent_x,222            y=tangent_y,223            mode="lines",224            line=dict(color="orange", width=3),225            name="Tangent Line"226        ))227 228        # Dynamic zoom for better visibility229        fig.update_layout(230            xaxis=dict(231                title="x-axis",232                range=[-10, 10],233                showline=True,234                linecolor="white",235                tickcolor="white",236                tickfont=dict(color="white"),237                ticks="outside",238            ),239            yaxis=dict(240                title="y-axis",241                range=[min(y_plot) - 5, min(max(y_plot) + 5, 1000)],  # Limiting the max y to 1000242                showline=True,243                linecolor="white",244                tickcolor="white",245                tickfont=dict(color="white"),246                ticks="outside",247            ),248            plot_bgcolor="black",249            paper_bgcolor="black",250            title="",251            margin=dict(l=10, r=10, t=10, b=10),252            width=800,253            height=400,254            showlegend=True,255            legend=dict(256                x=1.1,257                y=0.5,258                xanchor="left",259                yanchor="middle",260                orientation="v",261                font=dict(size=12, color="white"),262                bgcolor="black",263                bordercolor="white",264                borderwidth=2,265            )266        )267 268        # Axis lines for quadrants269        fig.add_shape(type="line", x0=-10, x1=10, y0=0, y1=0, line=dict(color="white", width=2))  # x-axis270        fig.add_shape(type="line", x0=0, x1=0, y0=-100, y1=100, line=dict(color="white", width=2))  # y-axis271 272        st.plotly_chart(fig, use_container_width=True)273 274    except Exception as e:275        st.error(f"โš ๏ธ Error in visualization: {str(e)}")276 277    # Iteration stats and download278    col5, col6 = st.columns(2)279    col5.info(f"๐Ÿง‘โ€๐Ÿ’ป Iteration: {st.session_state.iteration}")280    col6.success(f"โœ… Current x: {st.session_state.x:.4f}, Current f(x): {st.session_state.y_vals[-1]:.4f}")