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/dW1W2 = 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
- Implemente
numerical_second_derivative(f, x)usandonumerical_derivativechamado duas vezes. Verifique que a segunda derivada de x^3 em x=2 é 12. - 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).
- 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
- 3Blue1Brown: Essence of Calculus - intuição visual para derivadas, integrais e a regra da cadeia
- Stanford CS231n: Backpropagation - como os gradientes fluem pelas camadas de redes neurais