Phase 01 - Lesson 04

Cálculo para Aprendizado de Máquina

This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.

As derivadas te dizem qual é o caminho ladeira abaixo. É só isso que uma rede neural precisa para aprender.

Tipo: Aprender Linguagem: Python Pré-requisitos: Fase 1, Lições 01-03 Tempo: ~60 minutos

Objetivos de Aprendizagem

  • Calcular derivadas numéricas e analíticas para funções comuns de ML (x^2, sigmoide, entropia cruzada)
  • Implementar o gradiente descendente do zero para minimizar uma função de perda em 1D e 2D
  • Derivar o gradiente de um modelo de regressão linear e treiná-lo via atualizações manuais de pesos
  • Explicar a matriz Hessiana, as aproximações por séries de Taylor e sua conexão com métodos de otimização

O Problema

Você tem uma rede neural com milhões de pesos. Cada peso é um botão. Você precisa descobrir em qual direção girar cada botão para deixar o modelo um pouco menos errado. O cálculo te dá essa direção.

Sem cálculo, treinar uma rede neural significaria tentar mudanças aleatórias e torcer pelo melhor. Com derivadas, você sabe exatamente como cada peso afeta o erro. Você gira cada botão do jeito certo, toda vez.

O Conceito

O que é uma derivada?

Uma derivada mede a taxa de variação. Para uma função y = f(x), a derivada f'(x) te diz: se você empurrar x por uma quantidade minúscula, quanto y muda?

Geometricamente, a derivada é a inclinação da reta tangente em um ponto.

f(x) = x^2:

x f(x) f'(x) (inclinação)
0 0 0 (plano, no fundo)
1 1 2
2 4 4 (inclinação da reta tangente neste ponto)
3 9 6

Em x=2, a inclinação é 4. Se você mover x um pouquinho para a direita, y aumenta em cerca de 4 vezes essa quantidade. Em x=0, a inclinação é 0. Você está no fundo da tigela.

A definição formal:

f'(x) = lim   f(x + h) - f(x)
        h->0  -----------------
                     h

No código, você pula o limite e usa apenas um h muito pequeno. Essa é a derivada numérica.

Derivadas parciais: uma variável por vez

Funções reais têm muitas entradas. A perda de uma rede neural depende de milhares de pesos. Uma derivada parcial mantém todas as variáveis constantes, exceto uma, e então calcula a derivada em relação a essa única variável.

f(x, y) = x^2 + 3xy + y^2

df/dx = 2x + 3y     (treat y as a constant)
df/dy = 3x + 2y     (treat x as a constant)

Cada derivada parcial responde: se eu empurrar apenas este peso, como a perda muda?

O gradiente: vetor de todas as derivadas parciais

O gradiente reúne cada derivada parcial em um único vetor. Para uma função f(x, y, z), o gradiente é:

grad f = [ df/dx, df/dy, df/dz ]

O gradiente aponta na direção de maior crescimento. Para minimizar uma função, vá na direção oposta.

Grafico de contorno de f(x,y) = x^2 + y^2:

A função forma um formato de tigela com circulos concentricos como linhas de contorno. O mínimo está em (0, 0).

Ponto grad f -grad f (direção de descida)
(1, 1) [2, 2] (aponta ladeira acima, longe do mínimo) [-2, -2] (aponta ladeira abaixo, em direção ao mínimo)
(0, 0) [0, 0] (plano, no mínimo) [0, 0]

Isto é o gradiente descendente em uma imagem. Calcule o gradiente, negue-o, de um passo.

A conexão com a otimização

Treinar uma rede neural é otimização. Você tem uma função de perda L(w1, w2, ..., wn) que mede o quão errado o modelo está. Você quer minimizá-la.

Gradient descent update rule:

  w_new = w_old - learning_rate * dL/dw

For every weight:
  1. Compute the partial derivative of loss with respect to that weight
  2. Subtract a small multiple of it from the weight
  3. Repeat

A taxa de aprendizado controla o tamanho do passo. Grande demais e você ultrapassa. Pequena demais e você se arrasta.

Paisagem de perda (corte 1D):

A função de perda L(w) forma uma curva com picos e vales conforme o peso w varia.

Característica Descrição
Mínimo global O ponto mais baixo de toda a curva -- a melhor solução
Mínimo local Um vale que é mais baixo que seus vizinhos, mas não o mais baixo de todos
Inclinação O gradiente descendente segue a inclinação ladeira abaixo a partir de qualquer ponto de partida

O gradiente descendente segue a inclinação ladeira abaixo. Ele pode ficar preso em mínimos locais, mas em espaços de alta dimensão (milhões de pesos) isso raramente é um problema prático.

Derivadas numéricas vs analíticas

Existem duas maneiras de calcular uma derivada.

Analítica: aplicar as regras do cálculo à mão. Para f(x) = x^2, a derivada é f'(x) = 2x. Exata. Rápida.

Numérica: aproximar usando a definição. Calcule f(x+h) e f(x-h) para um h minúsculo, depois use a diferença.

Numerical (central difference):

f'(x) ~= f(x + h) - f(x - h)
          -----------------------
                  2h

h = 0.0001 works well in practice

As derivadas numéricas são mais lentas, mas funcionam para qualquer função. As derivadas analíticas são rápidas, mas exigem que você derive a fórmula. Os frameworks de redes neurais usam uma terceira abordagem: a diferenciação automática, que calcula derivadas exatas de forma mecânica. Você verá isso na Fase 3.

Derivadas à mão para funções simples

Estas são as derivadas que você verá o tempo todo em ML.

Function        Derivative       Used in
--------        ----------       -------
f(x) = x^2     f'(x) = 2x      Loss functions (MSE)
f(x) = wx + b  f'(w) = x        Linear layer (gradient w.r.t. weight)
                f'(b) = 1        Linear layer (gradient w.r.t. bias)
                f'(x) = w        Linear layer (gradient w.r.t. input)
f(x) = e^x     f'(x) = e^x     Softmax, attention
f(x) = ln(x)   f'(x) = 1/x     Cross-entropy loss
f(x) = 1/(1+e^-x)  f'(x) = f(x)(1-f(x))   Sigmoid activation

Para f(x) = x^2:

f(x) = x^2    f'(x) = 2x

  x    f(x)   f'(x)   meaning
  -2    4      -4      slope tilts left (decreasing)
  -1    1      -2      slope tilts left (decreasing)
   0    0       0      flat (minimum!)
   1    1       2      slope tilts right (increasing)
   2    4       4      slope tilts right (increasing)

Para f(w) = wx + b com x=3, b=1:

f(w) = 3w + 1    f'(w) = 3

The derivative with respect to w is just x.
If x is big, a small change in w causes a big change in output.

A regra da cadeia

Quando funções são compostas, a regra da cadeia te diz como diferenciar.

If y = f(g(x)), then dy/dx = f'(g(x)) * g'(x)

Example: y = (3x + 1)^2
  outer: f(u) = u^2       f'(u) = 2u
  inner: g(x) = 3x + 1    g'(x) = 3
  dy/dx = 2(3x + 1) * 3 = 6(3x + 1)

As redes neurais são cadeias de funções: entrada -> linear -> ativação -> linear -> ativação -> perda. A backpropagation é a regra da cadeia aplicada repetidamente da saída até a entrada. E esse é o algoritmo inteiro.

A Matriz Hessiana

O gradiente te diz a inclinação. A Hessiana te diz a curvatura.

A Hessiana é a matriz de derivadas parciais de segunda ordem. Para uma função f(x1, x2, ..., xn), a entrada (i, j) da Hessiana é:

H[i][j] = d^2f / (dx_i * dx_j)

Para uma função de 2 variáveis f(x, y):

H = | d^2f/dx^2    d^2f/dxdy |
    | d^2f/dydx    d^2f/dy^2 |

O que a Hessiana te diz em um ponto crítico (onde o gradiente = 0):

Propriedade da Hessiana Significado Superfície de exemplo
Positiva definida (todos os autovalores > 0) Mínimo local Tigela apontando para cima
Negativa definida (todos os autovalores < 0) Máximo local Tigela apontando para baixo
Indefinida (autovalores mistos) Ponto de sela Formato de sela de cavalo

Exemplo: f(x, y) = x^2 - y^2 (uma função de sela)

df/dx = 2x       df/dy = -2y
d^2f/dx^2 = 2    d^2f/dy^2 = -2    d^2f/dxdy = 0

H = | 2   0 |
    | 0  -2 |

Eigenvalues: 2 and -2 (one positive, one negative)
--> Saddle point at (0, 0)

Compare com f(x, y) = x^2 + y^2 (uma tigela):

H = | 2  0 |
    | 0  2 |

Eigenvalues: 2 and 2 (both positive)
--> Local minimum at (0, 0)

Por que a Hessiana importa em ML:

O método de Newton usa a Hessiana para dar passos de otimização melhores que o gradiente descendente. Em vez de apenas seguir a inclinação, ele leva em conta a curvatura:

Newton's update:    w_new = w_old - H^(-1) * gradient
Gradient descent:   w_new = w_old - lr * gradient

O método de Newton converge mais rápido porque a Hessiana "reescala" o gradiente -- direções íngremes recebem passos menores, direções planas recebem passos maiores.

O problema: para uma rede neural com N parâmetros, a Hessiana é N x N. Um modelo com 1 milhão de parâmetros precisaria de uma matriz de 1 trilhão de entradas. É por isso que usamos aproximações.

Método O que usa Custo Convergência
Gradiente descendente Apenas primeiras derivadas O(N) por passo Lenta (linear)
Método de Newton Hessiana completa O(N^3) por passo Rápida (quadrática)
L-BFGS Hessiana aproximada a partir do histórico de gradientes O(N) por passo Média (superlinear)
Adam Taxas adaptativas por parâmetro (aproximação diagonal da Hessiana) O(N) por passo Média
Gradiente natural Matriz de informação de Fisher (Hessiana estatística) O(N^2) por passo Rápida

Na prática, o Adam é o otimizador padrão para deep learning. Ele aproxima informação de segunda ordem de forma barata rastreando a média e a variância móveis dos gradientes por parâmetro.

Aproximação por Série de Taylor

Qualquer função suave pode ser aproximada localmente por um polinômio:

f(x + h) = f(x) + f'(x)*h + (1/2)*f''(x)*h^2 + (1/6)*f'''(x)*h^3 + ...

Quanto mais termos você incluir, melhor a aproximação -- mas apenas perto do ponto x.

Por que as séries de Taylor importam para ML:

  • Taylor de primeira ordem = gradiente descendente. Quando você usa f(x + h) ~ f(x) + f'(x)*h, você está fazendo uma aproximação linear. O gradiente descendente minimiza esse modelo linear para escolher h = -lr * f'(x).

  • Taylor de segunda ordem = método de Newton. Usando f(x + h) ~ f(x) + f'(x)*h + (1/2)*f''(x)*h^2, você obtém um modelo quadrático. Minimizá-lo dá h = -f'(x)/f''(x) -- o passo de Newton.

  • Design de funções de perda. O MSE e a entropia cruzada são suaves, o que significa que suas expansões de Taylor são bem comportadas. Isso não é por acaso. Perdas suaves tornam a otimização previsível.

Approximation order    What it captures    Optimization method
-------------------    -----------------   -------------------
0th order (constant)   Just the value      Random search
1st order (linear)     Slope               Gradient descent
2nd order (quadratic)  Curvature           Newton's method
Higher orders          Finer structure     Rarely used in ML

O insight chave: toda otimização baseada em gradiente é, na verdade, sobre aproximar a função de perda localmente e dar um passo até o mínimo dessa aproximação.

Integrais em ML

As derivadas te dizem taxas de variação. As integrais calculam acumulações -- a área sob uma curva.

Em ML, você raramente calcula integrais à mão, mas o conceito está em todo lugar:

Probabilidade. Para uma variável aleatória contínua com densidade p(x):

P(a < X < b) = integral from a to b of p(x) dx

A área sob a curva de densidade de probabilidade entre a e b é a probabilidade de cair nesse intervalo.

Valor esperado. O resultado médio ponderado pela probabilidade:

E[f(X)] = integral of f(x) * p(x) dx

A perda esperada sobre uma distribuição de dados é uma integral. O treinamento minimiza uma aproximação empírica disso.

Divergência KL. Mede o quanto duas distribuições são diferentes:

KL(p || q) = integral of p(x) * log(p(x) / q(x)) dx

Usada em VAEs, destilação de conhecimento e inferência bayesiana.

Constantes de normalização. Na inferência bayesiana:

p(w | data) = p(data | w) * p(w) / integral of p(data | w) * p(w) dw

O denominador é uma integral sobre todos os valores possíveis de parâmetros. Ele costuma ser intratável, e por isso usamos aproximações como MCMC e inferência variacional.

Conceito de integral Onde aparece em ML
Área sob a curva Probabilidade a partir de funções de densidade
Valor esperado Funções de perda, minimização de risco
Divergência KL VAEs, otimização de políticas, destilação
Normalização Posteriores bayesianos, denominador do softmax
Verossimilhança marginal Comparação de modelos, limite inferior da evidência (ELBO)

Regra da Cadeia Multivariável em um Grafo de Computação

A regra da cadeia não se aplica apenas a funções escalares em linha. Em uma rede neural, as variáveis se ramificam e se fundem. Veja como as derivadas fluem por um forward pass simples:

graph LR
    x["x (input)"] -->|"*w"| z1["z1 = w*x"]
    z1 -->|"+b"| z2["z2 = w*x + b"]
    z2 -->|"sigmoid"| a["a = sigmoid(z2)"]
    a -->|"loss fn"| L["L = -(y*log(a) + (1-y)*log(1-a))"]

O backward pass calcula os gradientes da direita para a esquerda:

graph RL
    dL["dL/dL = 1"] -->|"dL/da"| da["dL/da = -y/a + (1-y)/(1-a)"]
    da -->|"da/dz2 = a(1-a)"| dz2["dL/dz2 = dL/da * a(1-a)"]
    dz2 -->|"dz2/dw = x"| dw["dL/dw = dL/dz2 * x"]
    dz2 -->|"dz2/db = 1"| db["dL/db = dL/dz2 * 1"]

Cada seta multiplica pela derivada local. O gradiente de qualquer parâmetro é o produto de todas as derivadas locais ao longo do caminho da perda até esse parâmetro. Quando os caminhos se ramificam e se fundem, você soma as contribuições (regra da cadeia multivariável).

É só isso que a backpropagation é: a regra da cadeia aplicada sistematicamente através de um grafo de computação, da saída até as entradas.

A matriz Jacobiana

Quando uma função mapeia um vetor para um vetor (como uma camada de rede neural), sua derivada é uma matriz. A Jacobiana contém todas as derivadas parciais de cada saída em relação a cada entrada.

Para f: R^n -> R^m, a Jacobiana J é uma matriz m x n:

x1 x2 ... xn
f1 df1/dx1 df1/dx2 ... df1/dxn
f2 df2/dx1 df2/dx2 ... df2/dxn
... ... ... ... ...
fm dfm/dx1 dfm/dx2 ... dfm/dxn

Você não vai calcular Jacobianas à mão para redes neurais. O PyTorch cuida disso. Mas saber que ela existe ajuda a entender os formatos na backpropagation: se uma camada mapeia R^n para R^m, sua Jacobiana é m x n. O gradiente flui para trás através da transposta dessa matriz.

Por que isso importa para redes neurais

Todo peso em uma rede neural recebe um gradiente. O gradiente te diz como ajustar aquele peso para reduzir a perda.

graph LR
    subgraph Forward["Forward Pass"]
        I["input"] --> W1["W1"] --> R["relu"] --> W2["W2"] --> S["softmax"] --> L["loss"]
    end
graph RL
    subgraph Backward["Backward Pass"]
        dL["dL/dloss"] --> dW2["dL/dW2"] --> d2["..."] --> dW1["dL/dW1"]
    end

Cada atualização de peso:

  • W1 = W1 - lr * dL/dW1
  • W2 = W2 - lr * dL/dW2

O forward pass calcula a predição e a perda. O backward pass calcula o gradiente da perda em relação a cada peso. Então cada peso dá um pequeno passo ladeira abaixo. Repita por milhões de passos. Isso é deep learning.

Construa

Passo 1: Derivada numérica do zero

def numerical_derivative(f, x, h=1e-7):
    return (f(x + h) - f(x - h)) / (2 * h)

def f(x):
    return x ** 2

for x in [-2, -1, 0, 1, 2]:
    numerical = numerical_derivative(f, x)
    analytical = 2 * x
    print(f"x={x:2d}  f'(x) numerical={numerical:.6f}  analytical={analytical:.1f}")

A derivada numérica coincide com a analítica até muitas casas decimais.

Passo 2: Derivadas parciais e gradientes

def numerical_gradient(f, point, h=1e-7):
    gradient = []
    for i in range(len(point)):
        point_plus = list(point)
        point_minus = list(point)
        point_plus[i] += h
        point_minus[i] -= h
        partial = (f(point_plus) - f(point_minus)) / (2 * h)
        gradient.append(partial)
    return gradient

def f_multi(point):
    x, y = point
    return x**2 + 3*x*y + y**2

grad = numerical_gradient(f_multi, [1.0, 2.0])
print(f"Numerical gradient at (1,2): {[f'{g:.4f}' for g in grad]}")
print(f"Analytical gradient at (1,2): [2*1+3*2, 3*1+2*2] = [{2*1+3*2}, {3*1+2*2}]")

Passo 3: Gradiente descendente para encontrar o mínimo de f(x) = x^2

x = 5.0
lr = 0.1
for step in range(20):
    grad = 2 * x
    x = x - lr * grad
    print(f"step {step:2d}  x={x:8.4f}  f(x)={x**2:10.6f}")

Começando em x=5, cada passo se aproxima de x=0 (o mínimo).

Passo 4: Gradiente descendente em uma função 2D

def f_2d(point):
    x, y = point
    return x**2 + y**2

point = [4.0, 3.0]
lr = 0.1
for step in range(30):
    grad = numerical_gradient(f_2d, point)
    point = [p - lr * g for p, g in zip(point, grad)]
    loss = f_2d(point)
    if step % 5 == 0 or step == 29:
        print(f"step {step:2d}  point=({point[0]:7.4f}, {point[1]:7.4f})  f={loss:.6f}")

Passo 5: Comparando derivadas numéricas e analíticas

import math

test_functions = [
    ("x^2",      lambda x: x**2,          lambda x: 2*x),
    ("x^3",      lambda x: x**3,          lambda x: 3*x**2),
    ("sin(x)",   lambda x: math.sin(x),   lambda x: math.cos(x)),
    ("e^x",      lambda x: math.exp(x),   lambda x: math.exp(x)),
    ("1/x",      lambda x: 1/x,           lambda x: -1/x**2),
]

x = 2.0
print(f"{'Function':<12} {'Numerical':>12} {'Analytical':>12} {'Error':>12}")
print("-" * 50)
for name, f, df in test_functions:
    num = numerical_derivative(f, x)
    ana = df(x)
    err = abs(num - ana)
    print(f"{name:<12} {num:12.6f} {ana:12.6f} {err:12.2e}")

Passo 6: Calculando a Hessiana numericamente

def hessian_2d(f, x, y, h=1e-5):
    fxx = (f(x + h, y) - 2 * f(x, y) + f(x - h, y)) / (h ** 2)
    fyy = (f(x, y + h) - 2 * f(x, y) + f(x, y - h)) / (h ** 2)
    fxy = (f(x + h, y + h) - f(x + h, y - h) - f(x - h, y + h) + f(x - h, y - h)) / (4 * h ** 2)
    return [[fxx, fxy], [fxy, fyy]]

def saddle(x, y):
    return x ** 2 - y ** 2

def bowl(x, y):
    return x ** 2 + y ** 2

H_saddle = hessian_2d(saddle, 0.0, 0.0)
H_bowl = hessian_2d(bowl, 0.0, 0.0)
print(f"Saddle Hessian: {H_saddle}")  # [[2, 0], [0, -2]] -- mixed signs
print(f"Bowl Hessian:   {H_bowl}")    # [[2, 0], [0, 2]]  -- both positive

A Hessiana da função de sela tem autovalores 2 e -2 (sinais mistos, confirmando um ponto de sela). A tigela tem autovalores 2 e 2 (ambos positivos, confirmando um mínimo).

Passo 7: Aproximação de Taylor em ação

import math

def taylor_approx(f, f_prime, f_double_prime, x0, h, order=2):
    result = f(x0)
    if order >= 1:
        result += f_prime(x0) * h
    if order >= 2:
        result += 0.5 * f_double_prime(x0) * h ** 2
    return result

x0 = 0.0
for h in [0.1, 0.5, 1.0, 2.0]:
    true_val = math.sin(h)
    t1 = taylor_approx(math.sin, math.cos, lambda x: -math.sin(x), x0, h, order=1)
    t2 = taylor_approx(math.sin, math.cos, lambda x: -math.sin(x), x0, h, order=2)
    print(f"h={h:.1f}  sin(h)={true_val:.4f}  order1={t1:.4f}  order2={t2:.4f}")

Perto de x0=0, sin(x) ~ x (Taylor de primeira ordem). A aproximação é excelente para h pequeno, mas se degrada para h grande. É por isso que o gradiente descendente funciona melhor com taxas de aprendizado pequenas -- cada passo assume que a aproximação linear é precisa.

Passo 8: Por que isso importa para uma rede neural

import random

random.seed(42)

w = random.gauss(0, 1)
b = random.gauss(0, 1)
lr = 0.01

xs = [1.0, 2.0, 3.0, 4.0, 5.0]
ys = [3.0, 5.0, 7.0, 9.0, 11.0]

for epoch in range(200):
    total_loss = 0
    dw = 0
    db = 0
    for x, y in zip(xs, ys):
        pred = w * x + b
        error = pred - y
        total_loss += error ** 2
        dw += 2 * error * x
        db += 2 * error
    dw /= len(xs)
    db /= len(xs)
    total_loss /= len(xs)
    w -= lr * dw
    b -= lr * db
    if epoch % 40 == 0 or epoch == 199:
        print(f"epoch {epoch:3d}  w={w:.4f}  b={b:.4f}  loss={total_loss:.6f}")

print(f"\nLearned: y = {w:.2f}x + {b:.2f}")
print(f"Actual:  y = 2x + 1")

Todo loop de treinamento baseado em gradiente segue este padrão: prever, calcular a perda, calcular os gradientes, atualizar os pesos.

Use

Com NumPy, as mesmas operações são mais rápidas e concisas:

import numpy as np

x = np.array([1, 2, 3, 4, 5], dtype=float)
y = np.array([3, 5, 7, 9, 11], dtype=float)

w, b = np.random.randn(), np.random.randn()
lr = 0.01

for epoch in range(200):
    pred = w * x + b
    error = pred - y
    loss = np.mean(error ** 2)
    dw = np.mean(2 * error * x)
    db = np.mean(2 * error)
    w -= lr * dw
    b -= lr * db

print(f"Learned: y = {w:.2f}x + {b:.2f}")

Você acabou de construir o gradiente descendente do zero. O PyTorch automatiza o cálculo do gradiente, mas o loop de atualização é idêntico.

Exercícios

  1. Implemente numerical_second_derivative(f, x) usando numerical_derivative chamado duas vezes. Verifique que a segunda derivada de x^3 em x=2 é 12.
  2. Use o gradiente descendente para encontrar o mínimo de f(x, y) = (x - 3)^2 + (y + 1)^2. Comece de (0, 0). A resposta deve convergir para (3, -1).
  3. Adicione momentum ao loop de gradiente descendente: mantenha um vetor de velocidade que acumula gradientes passados. Compare a velocidade de convergência com e sem momentum em f(x) = x^4 - 3x^2.

Termos-chave

Termo O que as pessoas dizem O que realmente significa
Derivada "A inclinação" A taxa de variação de uma função em um ponto. Te diz o quanto a saída muda por unidade de variação na entrada.
Derivada parcial "Derivada de uma variável" A derivada em relação a uma variável enquanto todas as outras são mantidas constantes.
Gradiente "Direção de maior crescimento" Um vetor de todas as derivadas parciais. Aponta na direção que aumenta a função mais rápido.
Gradiente descendente "Ir ladeira abaixo" Subtrair o gradiente (vezes uma taxa de aprendizado) dos parâmetros para reduzir a perda. O nucleo do treinamento de redes neurais.
Taxa de aprendizado "Tamanho do passo" Um escalar que controla o tamanho de cada passo do gradiente descendente. Grande demais: diverge. Pequena demais: converge lentamente.
Regra da cadeia "Multiplicar as derivadas" A regra para diferenciar funções compostas: df/dx = df/dg * dg/dx. A base matemática da backpropagation.
Jacobiana "Matriz de derivadas" Quando uma função mapeia vetores para vetores, a Jacobiana é a matriz de todas as derivadas parciais das saídas em relação às entradas.
Derivada numérica "Diferenças finitas" Aproximar uma derivada avaliando a função em dois pontos próximos e calculando a inclinação entre eles.
Backpropagation "Autodiff em modo reverso" Calcular gradientes camada por camada da saída até a entrada usando a regra da cadeia. Como as redes neurais aprendem.
Hessiana "Matriz de segundas derivadas" A matriz de todas as derivadas parciais de segunda ordem. Descreve a curvatura de uma função. Uma Hessiana positiva definida em um ponto crítico significa mínimo local.
Série de Taylor "Aproximação polinomial" Aproximar uma função perto de um ponto usando suas derivadas: f(x+h) ~ f(x) + f'(x)h + (1/2)f''(x)h^2 + ... A base para entender por que o gradiente descendente e o método de Newton funcionam.
Integral "Área sob a curva" A acumulação de uma quantidade ao longo de um intervalo. Em ML, integrais definem probabilidades, valores esperados e divergência KL.

Leitura Complementar

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).