Turunan sebagai laju perubahan instan, aturan turunan (power, product, chain, quotient), dan partial derivative — fondasi dari gradient descent di machine learning, Newton's method, dan optimization dalam algoritma.

Setelah di episode 21 kita mempelajari limits dan continuity — fondasi formal dari "mendekati" — pada episode ini kita mempelajari derivatives (turunan): laju perubahan instan dari sebuah fungsi. Turunan menjawab pertanyaan: "seberapa cepat fungsi berubah di titik tertentu?" Dalam dunia programming, turunan muncul di gradient descent (optimasi ML), Newton's method (root finding), dan rate of change dalam simulasi.
Mengapa turunan penting? Karena di dunia nyata, kita sering perlu menemukan optimal — harga terbaik, jalur terpendek, waktu minimum. Turunan memberikan cara untuk menemukan titik di mana fungsi mencapai minimum atau maximum tanpa mencoba semua kemungkinan — mengubah pencarian brute-force O(n) menjadi pencarian gradient-based yang jauh lebih efisien.
f'(x) = lim(h→0) [f(x+h) - f(x)] / h
Ini adalah limit dari perubahan rata-rata saat h mendekati 0 — laju perubahan instan.
import math
def numerical_derivative(f, x, h=1e-8):
"""Turunan numerik menggunakan limit definisi."""
return (f(x + h) - f(x)) / h
# f(x) = x² → f'(x) = 2x
f = lambda x: x**2
f_prime_analytical = lambda x: 2*x
print("f(x) = x²:")
for x in [-2, -1, 0, 1, 2, 3]:
num = numerical_derivative(f, x)
ana = f_prime_analytical(x)
print(f" f'({x}) numerik: {num:.6f}, analitis: {ana}, match: {abs(num-ana) < 1e-4}")d/dx (xⁿ) = n × xⁿ⁻¹
def power_rule_derivative(n, x):
"""Turunan dari x^n = n * x^(n-1)."""
return n * x**(n-1)
# f(x) = x³ → f'(x) = 3x²
print("Power rule:")
for x in [0, 1, 2, 3]:
print(f" f'(x) = 3x² at x={x}: {power_rule_derivative(3, x)}")
# f(x) = 5x⁴ → f'(x) = 20x³
print(f"\nf(x) = 5x⁴ → f'(x) = 20x³")
for x in [0, 1, 2]:
print(f" f'({x}) = {20 * x**3}")d/dx [f(x) × g(x)] = f'(x)g(x) + f(x)g'(x)
import math
# f(x) = x² × sin(x)
# f'(x) = 2x × sin(x) + x² × cos(x)
def f(x):
return x**2 * math.sin(x)
def f_prime(x):
return 2*x * math.sin(x) + x**2 * math.cos(x)
print("Product rule: f(x) = x² × sin(x)")
for x in [0, 1, 2, 3]:
num = numerical_derivative(f, x)
ana = f_prime(x)
print(f" f'({x}): numerik={num:.4f}, analitis={ana:.4f}")d/dx [f(g(x))] = f'(g(x)) × g'(x)
# f(x) = (2x + 1)³
# f'(x) = 3(2x + 1)² × 2 = 6(2x + 1)²
def f(x):
return (2*x + 1)**3
def f_prime(x):
return 6 * (2*x + 1)**2
print("Chain rule: f(x) = (2x + 1)³")
for x in [0, 1, 2]:
num = numerical_derivative(f, x)
ana = f_prime(x)
print(f" f'({x}): numerik={num:.4f}, analitis={ana:.4f}")d/dx [f/g] = [f'g - fg'] / g²
# f(x) = sin(x) / x
# f'(x) = [cos(x) × x - sin(x) × 1] / x²
def f(x):
if x == 0:
return 1
return math.sin(x) / x
def f_prime(x):
if x == 0:
return 0
return (math.cos(x) * x - math.sin(x)) / x**2
print("Quotient rule: f(x) = sin(x)/x")
for x in [0.5, 1, 2, 3]:
num = numerical_derivative(f, x)
ana = f_prime(x)
print(f" f'({x}): numerik={num:.6f}, analitis={ana:.6f}")Fungsi multivariabel f(x,y) punya partial derivative terhadap setiap variabel:
def numerical_partial(f, x, y, var, h=1e-8):
"""Partial derivative numerik."""
if var == "x":
return (f(x + h, y) - f(x, y)) / h
else:
return (f(x, y + h) - f(x, y)) / h
# f(x,y) = x² + 2xy + y²
def f(x, y):
return x**2 + 2*x*y + y**2
# ∂f/∂x = 2x + 2y, ∂f/∂y = 2x + 2y
print("f(x,y) = x² + 2xy + y²")
x, y = 2, 3
dfdx_num = numerical_partial(f, x, y, "x")
dfdy_num = numerical_partial(f, x, y, "y")
dfdx_ana = 2*x + 2*y
dfdy_ana = 2*x + 2*y
print(f" ∂f/∂x at ({x},{y}): numerik={dfdx_num:.4f}, analitis={dfdx_ana}")
print(f" ∂f/∂y at ({x},{y}): numerik={dfdy_num:.4f}, analitis={dfdy_ana}")
# Gradient vector
grad = [dfdx_ana, dfdy_ana]
print(f" Gradient: ∇f = ({grad[0]}, {grad[1]})")import math
def gradient_descent(f_prime, x0, learning_rate=0.1, n_iter=20):
"""Gradient descent untuk minimize f(x)."""
x = x0
history = [x]
for _ in range(n_iter):
grad = f_prime(x)
x = x - learning_rate * grad
history.append(x)
return x, history
# f(x) = x² → f'(x) = 2x → minimum di x=0
f_prime = lambda x: 2*x
x_min, history = gradient_descent(f_prime, x0=5.0, learning_rate=0.1)
print("Gradient descent: minimize f(x) = x²")
print(f" Start: x = {history[0]}")
print(f" End: x = {x_min:.8f}")
print(f" Steps: {len(history)}")
# Tampilkan convergence
print("\nConvergence:")
for i in range(0, len(history), 4):
print(f" Step {i}: x = {history[i]:.6f}")# Terlalu besar: oscillate / diverge
_, hist_big = gradient_descent(f_prime, x0=5.0, learning_rate=0.6, n_iter=10)
print("Learning rate 0.6:")
for i, x in enumerate(hist_big):
print(f" Step {i}: x = {x:.4f}")
# Terlalu kecil: lambat
_, hist_small = gradient_descent(f_prime, x0=5.0, learning_rate=0.01, n_iter=20)
print(f"\nLearning rate 0.01: final x = {hist_small[-1]:.6f} (setelah 20 steps)")def newton_method(f, f_prime, f_double_prime, x0, tol=1e-10):
"""Newton's method: x_{n+1} = x_n - f'(x_n)/f''(x_n) untuk minimize f."""
x = x0
history = [x]
for i in range(100):
fp = f_prime(x)
if abs(fp) < tol:
break
fpp = f_double_prime(x)
x = x - fp / fpp
history.append(x)
return x, history
# Minimize f(x) = x⁴ - 4x² + 2
f = lambda x: x**4 - 4*x**2 + 2
f_prime = lambda x: 4*x**3 - 8*x
f_double_prime = lambda x: 12*x**2 - 8
x_min, history = newton_method(f, f_prime, f_double_prime, x0=2.0)
print(f"Newton's method: minimize f(x) = x⁴ - 4x² + 2")
print(f" Minimum di x = {x_min:.8f}")
print(f" f({x_min:.4f}) = {f(x_min):.8f}")Tip
Gradient descent membutuhkan learning rate yang tepat — terlalu besar menyebabkan oscillation, terlalu kecil menyebabkan konvergensi lambat. Dalam praktik, learning rate scheduling (menurunkan learning rate seiring waktu) adalah teknik umum untuk mengatasi ini.
Inti yang harus dibawa pulang:
f'(x) = laju perubahan instan = limit dari difference quotient.nxⁿ⁻¹), product (f'g + fg'), chain (f'(g(x)) × g'(x)), quotient.∇f = vektor partial derivatives — arah perubahan terbesar.x ← x - lr × ∇f — iteratif menuju minimum.Di episode 23 selanjutnya kita akan mempelajari integral dan Fundamental Theorem — kebalikan dari turunan, menghitung area di bawah kurva, dan Riemann sum. Turunan dan integral adalah dua sisi koin calculus — yang satu mengukur perubahan, yang lain mengakumulasi!