Difference quotients from scratch with Python
From the Data Science from Scratch book.
import pandas as pd
import altair as alt
from typing import List
Vector = List[float]
Vector
def dot(vector1: Vector, vector2: Vector) -> float:
assert len(vector1) == len(vector2)
return sum(v1 * v2 for v1, v2 in zip(vector1, vector2))
assert dot([1, 2, 3], [4, 5, 6]) == 32
def sum_of_squares(v: Vector) -> Vector:
return dot(v, v)
assert sum_of_squares([1, 2, 3]) == 14
from typing import Callable
def difference_quotient(
f: Callable[[float], float],
x: float,
h: float
) -> float :
return (f(x + h) - f(x)) / h
def square(x: float) -> float:
return x * x
def derivative_x2(x: float) -> float:
return 2 * x
xs = range(-10, 11)
actuals = [derivative_x2(x) for x in xs]
actuals
estimates = [difference_quotient(square, x, h=0.001) for x in xs]
estimates
df = pd.DataFrame({'actuals': actuals, 'estimates': estimates}).reset_index()
df = df.melt(id_vars='index')
df.sample(10)
alt.Chart(df).mark_circle(opacity=0.75).encode(
alt.X('index:Q'),
alt.Y('value:Q'),
alt.Size('variable:N'),
alt.Color('variable:N')
).properties(title='Actual derivatives and estimated quotients')
def partial_difference_quotient(
f: Callable[[Vector], float],
v: Vector,
i: int,
h: float
) -> float:
"""Return i-th parital difference quotient of `f` at a`v`"""
w = [
v_j + (h if j == i else 0)
for j, v_j in enumerate(v)
]
return (f(w) - f(v)) / h
def estimate_gradient(
f: Callable[[Vector], float],
v: Vector,
h: float = 0.0001
):
return [
partial_difference_quotient(f, v, i, h)
for i in range(len(v))
]