Fit a line

Drag a line through ice cream sales data, score it by its squared misses, then watch gradient descent find the best line.

NoviceExplained in Getting less wrong

Fit a line to the ice cream sales

Each dot is one day: the temperature and how many cones sold. Drag the two handles to place a line that predicts sales from temperature.

Your line's typical miss65 cones
Best possible18 cones
Predicted sales at 30°C146 cones

Challenges

0 of 3 complete

  1. Make the line flat, so it predicts the same sales whatever the weather, and find the flat line with the smallest typical miss. (not yet)
  2. By hand, before letting the computer fit it, get your line's typical miss within 2 cones of the best possible. (not yet)
  3. Let the computer fit two bad lines, one tilted down and one tilted up, each missing by more than 40 cones. Do both end in the same place? (not yet)

Try this

  • Drag the handles to beat a typical miss of 25 cones, then 20.
  • Make the line slope downward. How big do the squares get?
  • Press Let the computer fit it from a few different starting lines. Does it always end in the same place?
Optional: the same idea in codePython with NumPy
import numpy as np

# The sixteen days from the demo: temperature (°C) and cones sold.
temp = np.array([26, 27, 19, 23, 29, 24, 14, 15, 19, 30, 17, 30, 15, 26, 18, 31])
cones = np.array([176, 140, 118, 160, 196, 136, 78, 92, 123, 214, 81, 171, 36, 146, 97, 209])

# Measure temperature from the average day (about 23°C). The best line is
# the same, but tilt and height stop interfering, so small steps work well.
t = temp - temp.mean()

def typical_miss(slope, height):
    """Square each day's miss, average the squares, take the square root."""
    predicted = slope * t + height
    return np.sqrt(np.mean((predicted - cones) ** 2))

# Start with a flat line: the same sales whatever the weather.
slope, height = 0.0, 136.0
print(f"flat line: misses by {typical_miss(slope, height):.1f} cones")

# Gradient descent: work out which way each number should move to lower
# the error, move it a small step that way, and repeat.
for step in range(300):
    miss = slope * t + height - cones
    slope -= 0.02 * np.mean(2 * miss * t)
    height -= 0.02 * np.mean(2 * miss)

print(f"after 300 steps: misses by {typical_miss(slope, height):.1f} cones")
print(f"predicted sales at 30°C: {slope * (30 - temp.mean()) + height:.0f} cones")
flat line: misses by 49.3 cones
after 300 steps: misses by 18.4 cones
predicted sales at 30°C: 194 cones

Try "embedding", "softmax", "overfitting", or "backpropagation".