Skip to content

Instantly share code, notes, and snippets.

@snowch
Created July 17, 2025 12:29
Show Gist options
  • Select an option

  • Save snowch/3478f3e41363ae0eb6af4aa3a15ec694 to your computer and use it in GitHub Desktop.

Select an option

Save snowch/3478f3e41363ae0eb6af4aa3a15ec694 to your computer and use it in GitHub Desktop.
grad
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Visualizing Gradients 📈\n",
"\n",
"This notebook demonstrates the concepts of **scalar fields** and their corresponding **gradient fields** as described in the provided document.\n",
"\n",
"1. **Function (Scalar Field):** We will first plot the function $f(x, y) = x^2 + xy + y^2$ as a 3D surface. This is a **scalar field** because it assigns a single scalar value (z) to every point (x, y). Think of this as a topographical map or a landscape.\n",
"\n",
"2. **Gradient (Vector Field):** We will then plot the gradient of that function, $\\nabla f(x, y) = [2x + y, 2y + x]$. The gradient is a **vector field** because it assigns a vector (with direction and magnitude) to every point. These vectors point in the direction of the steepest ascent on our landscape, and their length represents how steep it is at that point."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 1: Plotting the Function (3D Surface)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, let's import the necessary libraries and generate the data points for our 3D plot."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from mpl_toolkits.mplot3d import Axes3D\n",
"\n",
"# Generate evenly spaced points for x and y axes\n",
"x_vals = np.linspace(-1.0, 1.0, 50)\n",
"y_vals = np.linspace(-1.0, 1.0, 50)\n",
"\n",
"# Prepare lists to hold the (x, y, z) coordinates for our scatter plot\n",
"xx = []\n",
"yy = []\n",
"zz = []\n",
"\n",
"# Loop through each x and y to calculate the corresponding z value\n",
"for i in range(50):\n",
" for j in range(50):\n",
" # Get the specific x and y\n",
" xi = x_vals[i]\n",
" yj = y_vals[j]\n",
" \n",
" # Append the point to our lists\n",
" xx.append(xi)\n",
" yy.append(yj)\n",
" # Calculate z using the function f(x,y) = x^2 + xy + y^2\n",
" zz.append(xi*xi + xi*yj + yj*yj)\n",
"\n",
"# Convert the lists to NumPy arrays for plotting\n",
"x_points = np.array(xx)\n",
"y_points = np.array(yy)\n",
"z_points = np.array(zz)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, let's create the 3D scatter plot to visualize the function's surface."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Create a new figure and a 3D subplot\n",
"fig = plt.figure(figsize=(10, 8))\n",
"ax = fig.add_subplot(111, projection='3d')\n",
"\n",
"# Create the 3D scatter plot\n",
"ax.scatter(x_points, y_points, z_points, marker='.', s=2, color='b')\n",
"\n",
"# Set labels for clarity\n",
"ax.set_xlabel('x')\n",
"ax.set_ylabel('y')\n",
"ax.set_zlabel('z = f(x, y)')\n",
"ax.set_title('3D Plot of f(x, y) = x² + xy + y²')\n",
"\n",
"# Adjust the viewing angle for a better perspective\n",
"ax.view_init(30, 20)\n",
"\n",
"# Display the plot\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part 2: Plotting the Gradient (2D Vector Field)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we'll visualize the gradient. The gradient of our function is $\\nabla f = [2x+y, 2y+x]$. We'll plot this as a 2D vector field, where arrows show the direction and magnitude of the greatest change at each point."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Create a new figure for the 2D plot\n",
"fig2 = plt.figure(figsize=(8, 8))\n",
"ax2 = fig2.add_subplot(111)\n",
"\n",
"# Define the domain for the vector field\n",
"x_grid = np.linspace(-1.0, 1.0, 20)\n",
"y_grid = np.linspace(-1.0, 1.0, 20)\n",
"\n",
"# Use np.meshgrid to create a grid of (x, y) points\n",
"xv, yv = np.meshgrid(x_grid, y_grid, indexing='ij', sparse=False)\n",
"\n",
"# Calculate the components of the gradient vector at each point on the grid\n",
"# dx is the x-component of the vector (2x + y)\n",
"dx = 2*xv + yv\n",
"# dy is the y-component of the vector (2y + x)\n",
"dy = 2*yv + xv\n",
"\n",
"# Use ax.quiver to plot the arrows (vectors) on the grid\n",
"ax2.quiver(xv, yv, dx, dy, color='b')\n",
"\n",
"# Set labels and title\n",
"ax2.set_xlabel('x')\n",
"ax2.set_ylabel('y')\n",
"ax2.set_title('Gradient Field of f(x, y) = x² + xy + y²')\n",
"\n",
"# Ensure the axes are scaled equally to avoid distortion\n",
"plt.axis('equal')\n",
"\n",
"# Display the plot\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Conclusion\n",
"\n",
"By comparing the two plots, you can see the connection between the function and its gradient:\n",
"\n",
"- Where the 3D surface is **steep** (like near the corners), the arrows in the 2D gradient plot are **long**.\n",
"- Where the 3D surface is **flat** (near the center at (0,0)), the arrows are **short**.\n",
"- The arrows always point in the direction you would have to travel to go \"uphill\" the fastest on the 3D surface."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.7"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment