Notas de Econometria I — CAEN

Author

Ierê Gondim

Published

May 12, 2026

Aula 1 — Função de Expectativa Condicional e Projeção Linear

A Aula 1 tem uma função muito importante dentro do curso: separar três ideias que muitas vezes aparecem misturadas na prática aplicada: predição, projeção e causalidade. A Função de Expectativa Condicional, ou CEF, descreve a média de \(Y\) para cada valor de \(X\). O Melhor Preditor Linear, ou BLP, é a melhor aproximação linear de \(Y\) usando \(X\), mesmo quando a verdadeira CEF não é linear. Já a interpretação causal exige hipóteses adicionais, como a CIA, e não decorre automaticamente de uma regressão.

O fio condutor desta aula é: primeiro entendemos o que significa prever \(Y\) a partir de \(X\); depois vemos o que acontece quando restringimos a previsão a uma forma linear; por fim, discutimos por que uma relação preditiva ou associativa não é, por si só, uma relação causal.

1.1 Intuição: o que é a CEF?

A Função de Expectativa Condicional é definida por

\[m(x) \equiv \mathbb{E}[Y \mid X=x].\]

Ela responde à pergunta: qual é o valor médio esperado de \(Y\) quando observamos \(X=x\)? Portanto, a CEF não descreve cada observação individual, mas sim o comportamento médio de \(Y\) dentro de cada valor, ou faixa de valores, de \(X\).

A CEF é central porque é o melhor preditor de \(Y\) dado \(X\) quando usamos erro quadrático médio como critério. Isto é, entre todos os preditores possíveis da forma \(g(X)\), a função que minimiza

\[\mathbb{E}[(Y-g(X))^2]\]

é justamente

\[g(X)=\mathbb{E}[Y\mid X].\]

Assim, a CEF é o objeto populacional que concentra toda a informação preditiva de \(X\) sobre a média de \(Y\). Se definirmos o erro da CEF como

\[e=Y-m(X),\]

então vale

\[\mathbb{E}[e\mid X]=0.\]

Essa propriedade significa que, depois de usar a melhor previsão condicional possível, não sobra erro sistemático previsível por \(X\). O erro pode continuar existindo, mas sua média condicional é zero. O slide da Aula 1 destaca justamente essa propriedade: o erro da CEF é ortogonal, em média, a qualquer função integrável de \(X\).

Vamos verificar essa ideia empiricamente. Simulamos dados em que a CEF verdadeira é conhecida:

\[Y=X^2+\varepsilon, \qquad \varepsilon\sim N(0,1), \qquad X\sim U(-3,3).\]

Nesse caso,

\[\mathbb{E}[Y\mid X=x] = \mathbb{E}[x^2+\varepsilon\mid X=x] = x^2.\]

Ou seja, a CEF verdadeira é \(m(x)=x^2\).

set.seed(42)
n <- 1000

X <- runif(n, -3, 3)
Y <- X^2 + rnorm(n)

dados <- data.frame(X = X, Y = Y)
dados$faixa <- cut(X, breaks = 20)

cef_empirica <- dados |>
  group_by(faixa) |>
  summarise(
    X_medio = mean(X),
    Y_medio = mean(Y),
    .groups = "drop"
  )

ggplot(dados, aes(x = X, y = Y)) +
  geom_point(alpha = 0.2, color = "steelblue") +
  geom_line(data = cef_empirica,
            aes(x = X_medio, y = Y_medio),
            color = "red", linewidth = 1.2) +
  stat_function(fun = function(x) x^2,
                color = "black", linetype = "dashed", linewidth = 1) +
  labs(title = "CEF empírica (vermelho) vs. CEF verdadeira (preto tracejado)",
       x = "X", y = "Y") +
  theme_minimal()

CEF verdadeira vs. médias condicionais empíricas

A linha vermelha representa médias empíricas de \(Y\) dentro de faixas de \(X\). Ela é uma aproximação amostral da CEF. A linha preta tracejada é a CEF verdadeira, \(m(x)=x^2\). Como a amostra é grande, as médias por faixa se aproximam bem da curva verdadeira.

1.2 CEF vs BLP: o que acontece quando a CEF não é linear?

A CEF pode ter qualquer formato: linear, quadrático, descontínuo, com interações, com efeitos heterogêneos etc. O Melhor Preditor Linear impõe uma restrição adicional: ele procura a melhor aproximação de \(Y\) entre funções lineares de \(X\).

O BLP resolve

\[\beta = \arg\min_b \mathbb{E}[(Y-X^\top b)^2],\]

e, sob invertibilidade de \(\mathbb{E}[XX^\top]\), tem forma fechada

\[\beta = (\mathbb{E}[XX^\top])^{-1}\mathbb{E}[XY].\]

A diferença central é: a CEF é o melhor preditor geral, enquanto o BLP é o melhor preditor dentro da classe linear. Se a CEF for linear, o BLP recupera a CEF. Mas se a CEF for não linear, o BLP apenas fornece a melhor reta no sentido de erro quadrático médio.

blp <- lm(Y ~ X, data = dados)

ggplot(dados, aes(x = X, y = Y)) +
  geom_point(alpha = 0.15, color = "steelblue") +
  stat_function(fun = function(x) x^2,
                color = "black", linetype = "dashed", linewidth = 1) +
  geom_abline(intercept = coef(blp)[1], slope = coef(blp)[2],
              color = "blue", linewidth = 1.2) +
  labs(title = "BLP linear (azul) falha em capturar a CEF quadrática (tracejado)",
       x = "X", y = "Y") +
  theme_minimal()

BLP (azul) vs CEF verdadeira (preto tracejado)
cat("Coeficientes do BLP:\n")
Coeficientes do BLP:
cat("Intercepto:", round(coef(blp)[1], 4), "\n")
Intercepto: 3.027 
cat("Inclinação:", round(coef(blp)[2], 4), "\n")
Inclinação: -0.0128 
cat("\nNota: inclinação próxima de zero — X~U(-3,3) é simétrico,",
    "então E[XY] = E[X·X²] = E[X³] = 0 por simetria.\n")

Nota: inclinação próxima de zero — X~U(-3,3) é simétrico, então E[XY] = E[X·X²] = E[X³] = 0 por simetria.

Neste exemplo, a inclinação estimada fica próxima de zero. Isso não significa que \(X\) não tenha relação com \(Y\). Na verdade, a relação é fortíssima: \(Y\) cresce quando \(|X|\) cresce. O problema é que essa relação é quadrática e simétrica, enquanto o BLP procura uma reta.

Como \(X\sim U(-3,3)\) é simétrico, temos aproximadamente

\[\mathbb{E}[XY]=\mathbb{E}[X\cdot X^2]=\mathbb{E}[X^3]=0.\]

Por isso a melhor reta é praticamente horizontal. Esse exemplo é fundamental: uma inclinação linear perto de zero não implica ausência de relação; pode significar apenas que a forma linear é inadequada.

Observação importante: \(\mathbb{E}[Xe]=0\) é uma propriedade da projeção linear. Ela vale por construção para o erro do BLP. Isso não deve ser confundido com exogeneidade causal.

1.2.1 CEF linear, BLP e modelo populacional

Quando a CEF é linear, temos

\[\mathbb{E}[Y\mid X]=X^\top\beta.\]

Nesse caso, podemos escrever

\[Y=X^\top\beta+e, \qquad \mathbb{E}[e\mid X]=0.\]

Aqui, a regressão linear tem uma interpretação forte: ela descreve a própria média condicional de \(Y\). Já quando a CEF não é linear, ainda podemos calcular o BLP, mas ele deixa de ser a CEF e passa a ser apenas a melhor aproximação linear.

Essa distinção é uma das mais importantes da primeira aula:

\[\text{CEF linear} \Rightarrow \text{BLP coincide com a CEF},\]

mas

\[\text{BLP existe} \nRightarrow \text{CEF é linear}.\]

1.3 Viés de Variável Omitida (OVB)

O viés de variável omitida aparece quando estimamos uma regressão curta, omitindo um regressor relevante que está correlacionado com os regressores incluídos.

Considere a regressão populacional completa:

\[Y=X_1^\top\beta_1+X_2^\top\beta_2+e, \qquad \mathbb{E}[Xe]=0.\]

Agora suponha que estimamos uma regressão reduzida, omitindo \(X_2\):

\[Y=X_1^\top\gamma_1+u.\]

O coeficiente da regressão curta é

\[\gamma_1 = \beta_1+\Gamma_{12}\beta_2,\]

onde

\[\Gamma_{12} = (\mathbb{E}[X_1X_1^\top])^{-1}\mathbb{E}[X_1X_2^\top]\]

é o coeficiente da projeção linear de \(X_2\) em \(X_1\). Portanto, o termo \(\Gamma_{12}\beta_2\) é o viés de variável omitida.

O OVB desaparece em dois casos:

  1. \(\beta_2=0\): a variável omitida não afeta \(Y\);
  2. \(\Gamma_{12}=0\): a variável omitida é ortogonal a \(X_1\).
set.seed(123)
n <- 2000

beta1_true <- 2
beta2_true <- 3

X1 <- rnorm(n)
X2 <- 0.7 * X1 + rnorm(n)
e  <- rnorm(n)
Y  <- beta1_true * X1 + beta2_true * X2 + e

mod_completo <- lm(Y ~ X1 + X2)
mod_curto    <- lm(Y ~ X1)

gamma12     <- coef(lm(X2 ~ X1))["X1"]
ovb_teorico <- gamma12 * beta2_true

cat("=== Verificação do OVB ===\n\n")
=== Verificação do OVB ===
cat("beta1 verdadeiro:         ", beta1_true, "\n")
beta1 verdadeiro:          2 
cat("beta1 regressão completa: ", round(coef(mod_completo)["X1"], 4), "\n")
beta1 regressão completa:  1.9787 
cat("beta1 regressão curta:    ", round(coef(mod_curto)["X1"], 4), "\n\n")
beta1 regressão curta:     4.0504 
cat("OVB observado:            ",
    round(coef(mod_curto)["X1"] - coef(mod_completo)["X1"], 4), "\n")
OVB observado:             2.0717 
cat("OVB teórico (Γ₁₂·β₂):   ", round(ovb_teorico, 4), "\n")
OVB teórico (Γ₁₂·β₂):    2.0616 
cat("\n→ Os dois coincidem: a fórmula funciona exatamente.\n")

→ Os dois coincidem: a fórmula funciona exatamente.

1.4 CIA e identificação causal

A Aula 1 termina com uma mensagem essencial: regressão, CEF e BLP são objetos de predição e associação. Para transformar diferenças condicionais em efeitos causais, precisamos de hipóteses adicionais.

Considere um tratamento binário \(T\in\{0,1\}\). O resultado observado é

\[Y=\begin{cases}Y(1), & T=1,\\ Y(0), & T=0.\end{cases}\]

O efeito causal individual é \(Y(1)-Y(0)\), e o efeito causal médio, ou ACE, é

\[ACE=\mathbb{E}[Y(1)-Y(0)].\]

Sem CIA, a diferença observada de médias mistura efeito causal com seleção:

\[\mathbb{E}[Y\mid T=1]-\mathbb{E}[Y\mid T=0] = ACE+ \underbrace{\mathbb{E}[Y(0)\mid T=1]-\mathbb{E}[Y(0)\mid T=0]}_{\text{viés de seleção}}.\]

A CIA, ou ignorabilidade condicional, diz que, controlando por \(X\), a seleção para o tratamento não depende dos fatores não observados \(U\):

\[T\perp U\mid X.\]

set.seed(42)
n <- 3000

U      <- rnorm(n, mean = 0, sd = 1)
prob_T <- plogis(1.5 * U)
T_trat <- rbinom(n, 1, prob_T)

Y0 <- 2 + U + rnorm(n, sd = 0.5)
Y1 <- Y0 + 0.5
Y  <- ifelse(T_trat == 1, Y1, Y0)

diff_ingenua  <- mean(Y[T_trat == 1]) - mean(Y[T_trat == 0])
ace_verdadeiro <- mean(Y1 - Y0)

cat("=== CIA e Viés de Seleção ===\n\n")
=== CIA e Viés de Seleção ===
cat("ACE verdadeiro:              ", round(ace_verdadeiro, 4), "\n")
ACE verdadeiro:               0.5 
cat("Diferença de médias ingênua: ", round(diff_ingenua, 4), "\n")
Diferença de médias ingênua:  1.5798 
cat("Viés de seleção:             ", round(diff_ingenua - ace_verdadeiro, 4), "\n")
Viés de seleção:              1.0798 
cat("\n→ A diferença de médias superestima o efeito causal.\n")

→ A diferença de médias superestima o efeito causal.
cat("  Quem faz mestrado já teria salário maior (U alto) mesmo sem mestrado.\n")
  Quem faz mestrado já teria salário maior (U alto) mesmo sem mestrado.

A simulação mostra um caso de seleção positiva. Pessoas com maior \(U\), interpretado como habilidade não observada, têm maior probabilidade de fazer mestrado. Como \(U\) também aumenta o salário, a diferença de médias entre quem fez e quem não fez mestrado mistura o efeito causal verdadeiro com a diferença prévia de habilidade entre os grupos.

Aula 2 — Álgebra do MQO: Matrizes P, M, FWL e Alavancagem

A Aula 2 muda o foco da população para a amostra. Na Aula 1, o objeto central era o BLP populacional,

\[\beta=(\mathbb{E}[XX^\top])^{-1}\mathbb{E}[XY].\]

Agora, substituímos momentos populacionais por momentos amostrais. Essa é a lógica plug-in:

\[\mathbb{E}[XX^\top] \leadsto \frac{1}{n}X^\top X, \qquad \mathbb{E}[XY] \leadsto \frac{1}{n}X^\top Y.\]

Daí nasce o MQO:

\[\hat\beta=(X^\top X)^{-1}X^\top Y.\]

2.1 Setup: dados simulados com verdade conhecida

set.seed(42)
n  <- 100
k  <- 3

X1 <- rnorm(n)
X2 <- 0.5 * X1 + rnorm(n)
e  <- rnorm(n, sd = 1)

beta_true <- c(1, 2, -1)

X <- cbind(1, X1, X2)
Y <- X %*% beta_true + e

cat("Dimensões: X =", dim(X), "| Y =", length(Y), "\n")
Dimensões: X = 100 3 | Y = 100 

2.2 Estimador MQO: forma fechada

O MQO escolhe \(\hat\beta\) para minimizar a soma dos quadrados dos resíduos:

\[SSE(\beta)=(Y-X\beta)^\top(Y-X\beta).\]

As condições de primeira ordem geram as equações normais:

\[X^\top(Y-X\hat\beta)=0 \implies \hat\beta=(X^\top X)^{-1}X^\top Y.\]

XtX      <- t(X) %*% X
XtY      <- t(X) %*% Y
beta_hat <- solve(XtX) %*% XtY

mod <- lm(Y ~ X1 + X2)

cat("=== Comparação: MQO manual vs lm() ===\n\n")
=== Comparação: MQO manual vs lm() ===
cat(sprintf("%-20s %10s %10s\n", "Parâmetro", "Manual", "lm()"))
Parâmetro               Manual       lm()
cat(sprintf("%-20s %10.4f %10.4f\n", "Intercepto", beta_hat[1], coef(mod)[1]))
Intercepto               1.0018     1.0018
cat(sprintf("%-20s %10.4f %10.4f\n", "beta1",      beta_hat[2], coef(mod)[2]))
beta1                    1.8136     1.8136
cat(sprintf("%-20s %10.4f %10.4f\n", "beta2",      beta_hat[3], coef(mod)[3]))
beta2                   -0.9147    -0.9147
cat("\n→ Idênticos. O lm() usa decomposição QR (mais estável),",
    "mas o resultado é o mesmo.\n")

→ Idênticos. O lm() usa decomposição QR (mais estável), mas o resultado é o mesmo.

2.3 Matrizes \(P\) e \(M\)

A matriz de projeção \(P=X(X^\top X)^{-1}X^\top\) transforma \(Y\) em sua projeção no espaço coluna de \(X\): \(\hat Y=PY\). A matriz residualizadora \(M=I_n-P\) remove essa parte projetada: \(\hat e=MY\).

Como \(PX=X\), temos \(MX=(I-P)X=0\), o que implica a ortogonalidade dos resíduos: \(X^\top\hat e=0\).

P <- X %*% solve(XtX) %*% t(X)
M <- diag(n) - P

Y_hat <- P %*% Y
e_hat <- M %*% Y

cat("=== Propriedades de P ===\n")
=== Propriedades de P ===
cat("Simétrica  (P = P'):    ", isTRUE(all.equal(P, t(P))),    "\n")
Simétrica  (P = P'):     TRUE 
cat("Idempotente (P² = P):   ", isTRUE(all.equal(P %*% P, P)), "\n")
Idempotente (P² = P):    TRUE 
cat("tr(P) = k =", k, ":     ", round(sum(diag(P)), 8),        "\n\n")
tr(P) = k = 3 :      3 
cat("=== Propriedades de M ===\n")
=== Propriedades de M ===
cat("Simétrica  (M = M'):    ", isTRUE(all.equal(M, t(M))),    "\n")
Simétrica  (M = M'):     TRUE 
cat("Idempotente (M² = M):   ", isTRUE(all.equal(M %*% M, M)), "\n")
Idempotente (M² = M):    TRUE 
cat("tr(M) = n-k =", n-k, ": ", round(sum(diag(M)), 8),        "\n\n")
tr(M) = n-k = 97 :  97 
cat("=== MX = 0? ===\n")
=== MX = 0? ===
cat("max|MX|:", round(max(abs(M %*% X)), 10), "→ essencialmente zero\n\n")
max|MX|: 0 → essencialmente zero
cat("=== Decomposição Y = Ŷ + ê ===\n")
=== Decomposição Y = Ŷ + ê ===
cat("Ŷ·ê =", round(t(Y_hat) %*% e_hat, 8), "\n")
Ŷ·ê = 0 

2.3.1 Decomposição ANOVA e \(R^2\)

Como \(Y=PY+MY=\hat Y+\hat e\) e \(P\), \(M\) projetam em subespaços ortogonais:

\[\sum_{i=1}^n (Y_i-\bar Y)^2 = \sum_{i=1}^n (\hat Y_i-\bar Y)^2 + \sum_{i=1}^n \hat e_i^2.\]

Definimos então

\[R^2 = 1-\frac{SSE}{TSS}.\]

Y_bar <- mean(Y)

TSS <- sum((Y - Y_bar)^2)
SSE <- sum(e_hat^2)
ESS <- sum((Y_hat - Y_bar)^2)

R2_manual <- 1 - SSE / TSS
R2_lm     <- summary(mod)$r.squared

cat("=== Decomposição ANOVA ===\n\n")
=== Decomposição ANOVA ===
cat("TSS:        ", round(TSS, 6), "\n")
TSS:         357.6334 
cat("ESS + SSE:  ", round(ESS + SSE, 6), "\n")
ESS + SSE:   357.6334 
cat("Diferença:  ", round(TSS - (ESS + SSE), 10), "\n\n")
Diferença:   0 
cat("R² manual:  ", round(R2_manual, 6), "\n")
R² manual:   0.721328 
cat("R² lm():    ", round(R2_lm, 6), "\n")
R² lm():     0.721328 

2.4 Teorema de Frisch-Waugh-Lovell (FWL)

No modelo \(Y=X_1\beta_1+X_2\beta_2+e\), o coeficiente de \(X_1\) mede a associação entre \(Y\) e a parte de \(X_1\) que não é explicada por \(X_2\). O procedimento é:

  1. remover de \(Y\) a parte explicada por \(X_2\);
  2. remover de \(X_1\) a parte explicada por \(X_2\);
  3. regressar os resíduos de \(Y\) nos resíduos de \(X_1\).

O coeficiente obtido é exatamente o mesmo da regressão múltipla original.

X2_mat    <- cbind(1, X2)
M2        <- diag(n) - X2_mat %*% solve(t(X2_mat) %*% X2_mat) %*% t(X2_mat)
Y_til     <- M2 %*% Y
X1_til    <- M2 %*% X1

beta1_fwl <- sum(X1_til * Y_til) / sum(X1_til^2)

cat("=== Verificação do FWL ===\n\n")
=== Verificação do FWL ===
cat("beta1 (regressão múltipla): ", round(beta_hat[2], 6), "\n")
beta1 (regressão múltipla):  1.813644 
cat("beta1 (via FWL):            ", round(beta1_fwl, 6),   "\n")
beta1 (via FWL):             1.813644 
cat("\n→ Idênticos. FWL confirma que beta1 mede o efeito",
    "\n  de X1 *após remover* a influência de X2.\n")

→ Idênticos. FWL confirma que beta1 mede o efeito 
  de X1 *após remover* a influência de X2.

2.5 Alavancagem e LOO

A alavancagem da observação \(i\) é \(h_{ii}=P_{ii}=X_i^\top(X^\top X)^{-1}X_i\). O erro leave-one-out tem fórmula fechada:

\[\tilde e_i=\frac{\hat e_i}{1-h_{ii}}.\]

h_ii  <- diag(P)
e_loo <- e_hat / (1 - h_ii)

cat("=== Propriedades da alavancagem ===\n")
=== Propriedades da alavancagem ===
cat("min(h_ii):", round(min(h_ii), 4),
    " | esperado >= 1/n =", round(1/n, 4), "\n")
min(h_ii): 0.01  | esperado >= 1/n = 0.01 
cat("max(h_ii):", round(max(h_ii), 4), " | deve ser <= 1\n")
max(h_ii): 0.1787  | deve ser <= 1
cat("sum(h_ii):", round(sum(h_ii), 4), " | deve ser k =", k, "\n\n")
sum(h_ii): 3  | deve ser k = 3 
data.frame(h = h_ii, e = as.numeric(e_hat)) |>
  ggplot(aes(x = h, y = e)) +
  geom_point(aes(size = abs(h_ii * e_loo), color = abs(h_ii * e_loo)),
             alpha = 0.7) +
  scale_color_gradient(low = "steelblue", high = "red") +
  geom_hline(yintercept = 0, linetype = "dashed") +
  geom_vline(xintercept = 2*k/n, linetype = "dashed", color = "gray50") +
  labs(title = "Alavancagem × Resíduo",
       subtitle = "Tamanho/cor = influência |h_ii × ẽ_i| | linha = limiar 2k/n",
       x = "Alavancagem (h_ii)", y = "Resíduo (ê_i)",
       color = "Influência", size = "Influência") +
  theme_minimal()

Alavancagem vs resíduo — identificando observações influentes

No gráfico, pontos mais à direita têm maior alavancagem. Pontos com bolhas maiores e mais avermelhadas são mais influentes segundo a medida \(|h_{ii}\tilde e_i|\). A influência nasce da combinação de alta alavancagem com erro leave-one-out grande.

Fechamento da Aula 2

A Aula 2 mostra que o MQO é uma projeção ortogonal em \(\mathbb{R}^n\). A matriz \(P\) projeta \(Y\) no espaço coluna de \(X\), gerando \(\hat Y\), enquanto \(M=I-P\) gera os resíduos \(\hat e\). As equações normais \(X^\top\hat e=0\) dizem que os resíduos são ortogonais a todos os regressores. O Teorema FWL mostra que coeficientes de regressão múltipla podem ser entendidos como associações parciais entre resíduos. Por fim, alavancagem e leave-one-out permitem estudar observações potencialmente influentes e antecipam temas posteriores como HC3, jackknife e validação cruzada.

Aula 3 — Propriedades em Amostra Finita e Erros-Padrão Robustos

A Aula 3 estuda o comportamento do MQO em amostras finitas, isto é, sem depender ainda de argumentos assintóticos. A pergunta central é: dado um desenho amostral \(X\), o que conseguimos dizer sobre \(\hat\beta\)?

A aula parte de três hipóteses fundamentais:

  1. amostragem aleatória/i.i.d.;
  2. exogeneidade em média, \(\mathbb{E}[e\mid X]=0\);
  3. homocedasticidade, quando aplicável, \(\mathbb{E}[e^2\mid X]=\sigma^2\).

Sob essas condições, o MQO é não viesado condicionalmente, sua variância pode ser escrita explicitamente e, sob homocedasticidade, ele é BLUE pelo Teorema de Gauss-Markov. Quando há heterocedasticidade, o MQO continua não viesado sob exogeneidade, mas a matriz de variância clássica deixa de ser válida; por isso entram os estimadores robustos HC0–HC3.

3.1 Setup

Vamos simular um modelo linear em que a verdade é conhecida:

\[Y=X\beta+e, \qquad \beta=(1,2,-1)^\top.\]

Neste primeiro desenho, os erros são homocedásticos: \(e_i\sim N(0,1)\).

library(ggplot2)

set.seed(123)
n <- 200
k <- 3

X1 <- rnorm(n)
X2 <- 0.5 * X1 + rnorm(n)
X  <- cbind(1, X1, X2)

beta_true <- c(1, 2, -1)
e_true    <- rnorm(n)
Y         <- X %*% beta_true + e_true

XtX      <- t(X) %*% X
beta_hat <- solve(XtX) %*% t(X) %*% Y
e_hat    <- Y - X %*% beta_hat
P        <- X %*% solve(XtX) %*% t(X)
h_ii     <- diag(P)

3.2 Não viés do MQO: verificação por simulação

O Teorema C1 afirma que, sob amostragem i.i.d. e exogeneidade em média,

\[\mathbb{E}[\hat\beta\mid X]=\beta.\]

Como

\[\hat\beta = (X^\top X)^{-1}X^\top Y = \beta+(X^\top X)^{-1}X^\top e,\]

temos

\[\mathbb{E}[\hat\beta-\beta\mid X] = (X^\top X)^{-1}X^\top \mathbb{E}[e\mid X] = 0.\]

Na simulação abaixo, mantemos \(X\) fixo e geramos muitos vetores de erro \(e\). Assim, estamos verificando a ideia de média condicional: ao repetir o experimento muitas vezes com o mesmo desenho \(X\), a média de \(\hat\beta\) se aproxima de \(\beta\).

B <- 2000
beta1_sim <- numeric(B)

for (b in 1:B) {
  e_b          <- rnorm(n)
  Y_b          <- X %*% beta_true + e_b
  b_hat        <- solve(t(X) %*% X) %*% t(X) %*% Y_b
  beta1_sim[b] <- b_hat[2]
}

cat("=== Verificação do não-viés ===\n\n")
=== Verificação do não-viés ===
cat("beta1 verdadeiro:        ", beta_true[2], "\n")
beta1 verdadeiro:         2 
cat("Média de β̂₁ (B=2000):  ", round(mean(beta1_sim), 4), "\n")
Média de β̂₁ (B=2000):   1.9959 
cat("Diferença:               ", round(mean(beta1_sim) - beta_true[2], 4), "\n")
Diferença:                -0.0041 
ggplot(data.frame(b1 = beta1_sim), aes(x = b1)) +
  geom_histogram(aes(y = after_stat(density)),
                 bins = 50, fill = "steelblue", alpha = 0.7) +
  geom_vline(xintercept = beta_true[2],
             color = "red", linewidth = 1.2, linetype = "dashed") +
  geom_vline(xintercept = mean(beta1_sim),
             color = "black", linewidth = 1) +
  labs(title = "Distribuição de β̂₁ em 2000 simulações",
       subtitle = "Vermelho = valor verdadeiro | Preto = média simulada",
       x = "β̂₁", y = "Densidade") +
  theme_minimal()

Distribuição de β̂₁ em 2000 amostras — centragem no valor verdadeiro

A média simulada de \(\hat\beta_1\) fica próxima de \(2\), o valor verdadeiro. Isso não significa que cada amostra individual produz exatamente \(2\). Significa que, repetindo o processo muitas vezes sob as hipóteses do modelo, o MQO fica centrado no parâmetro verdadeiro.

3.3 Variância do MQO e Teorema de Gauss-Markov

A variância condicional geral do MQO é

\[\operatorname{Var}(\hat\beta\mid X) = (X^\top X)^{-1}X^\top D X(X^\top X)^{-1},\]

onde \(D=\operatorname{Var}(e\mid X)\). No caso homocedástico, \(D=\sigma^2 I_n\), então

\[\operatorname{Var}(\hat\beta\mid X) = \sigma^2(X^\top X)^{-1}.\]

Essa fórmula mostra que a precisão do MQO depende de duas coisas: da variância do erro \(\sigma^2\) e da geometria dos regressores, capturada por \((X^\top X)^{-1}\).

O Teorema de Gauss-Markov diz que, sob homocedasticidade, o MQO é o melhor estimador linear não viesado: nenhum outro estimador linear e não viesado tem matriz de variância menor. Nos slides, isso aparece como o resultado BLUE.

sigma2_true   <- 1
V_beta_teo    <- sigma2_true * solve(XtX)
var_beta1_teo <- V_beta_teo[2, 2]
var_beta1_emp <- var(beta1_sim)

cat("=== Gauss-Markov: variância de β̂₁ ===\n\n")
=== Gauss-Markov: variância de β̂₁ ===
cat("Variância teórica σ²(X'X)⁻¹₂₂: ", round(var_beta1_teo, 4), "\n")
Variância teórica σ²(X'X)⁻¹₂₂:  0.0068 
cat("Variância empírica (simulação):  ", round(var_beta1_emp, 4), "\n")
Variância empírica (simulação):   0.0068 

3.4 Estimação de \(\sigma^2\): por que dividir por \(n-k\)?

A variância do erro é \(\sigma^2=\mathbb{E}[e_i^2]\). Como os erros verdadeiros não são observados, usamos os resíduos:

\[\hat\sigma^2=\frac{1}{n}\sum_{i=1}^n \hat e_i^2.\]

O problema é que os resíduos MQO são menores, em média, que os erros verdadeiros, porque a regressão escolhe \(\hat\beta\) justamente para minimizar a soma dos quadrados. Sob homocedasticidade,

\[\mathbb{E}[\hat\sigma^2\mid X] = \sigma^2\frac{n-k}{n}.\]

Logo, \(\hat\sigma^2\) é viesado para baixo. A correção clássica é

\[s^2=\frac{1}{n-k}\sum_{i=1}^n \hat e_i^2,\]

que satisfaz \(\mathbb{E}[s^2\mid X]=\sigma^2\). Essa é a origem dos graus de liberdade residuais \(n-k\): a regressão estimou \(k\) parâmetros antes de calcular a soma de quadrados residual, consumindo \(k\) graus de liberdade.

sigma2_hat_n  <- sum(e_hat^2) / n
sigma2_hat_df <- sum(e_hat^2) / (n - k)

cat("=== Estimação de sigma² ===\n\n")
=== Estimação de sigma² ===
cat("sigma² verdadeiro:              ", sigma2_true, "\n")
sigma² verdadeiro:               1 
cat("Estimador com divisor n:        ", round(sigma2_hat_n, 4), "\n")
Estimador com divisor n:         0.9228 
cat("Estimador com divisor n-k (s²): ", round(sigma2_hat_df, 4), "\n")
Estimador com divisor n-k (s²):  0.9369 
cat("\nFator esperado de viés com divisor n: (n-k)/n =",
    round((n-k)/n, 4), "\n")

Fator esperado de viés com divisor n: (n-k)/n = 0.985 

3.5 Estimadores HC0 a HC3 — construídos à mão

Quando há heterocedasticidade, a matriz correta de variância condicional do MQO é

\[V_{\hat\beta} = (X^\top X)^{-1}(X^\top D X)(X^\top X)^{-1},\]

onde \(D=\operatorname{diag}(\sigma_1^2,\ldots,\sigma_n^2)\). Como \(D\) é desconhecida, os estimadores HC substituem os erros verdadeiros \(e_i^2\) por funções dos resíduos \(\hat e_i^2\):

\[\text{HC0}: \hat e_i^2, \qquad \text{HC2}: \frac{\hat e_i^2}{1-h_{ii}}, \qquad \text{HC3}: \frac{\hat e_i^2}{(1-h_{ii})^2}.\]

XtX_inv <- solve(XtX)

# HC0 (Eicker-White)
Omega_HC0 <- t(X) %*% diag(as.numeric(e_hat)^2) %*% X
V_HC0     <- XtX_inv %*% Omega_HC0 %*% XtX_inv

# HC1 (correção de graus de liberdade)
V_HC1 <- (n / (n - k)) * V_HC0

# HC2 (corrige 1 - h_ii)
w_HC2     <- as.numeric(e_hat)^2 / (1 - h_ii)
Omega_HC2 <- t(X) %*% diag(w_HC2) %*% X
V_HC2     <- XtX_inv %*% Omega_HC2 %*% XtX_inv

# HC3 (jackknife; corrige (1 - h_ii)^2)
w_HC3     <- as.numeric(e_hat)^2 / (1 - h_ii)^2
Omega_HC3 <- t(X) %*% diag(w_HC3) %*% X
V_HC3     <- XtX_inv %*% Omega_HC3 %*% XtX_inv

se_HC0 <- sqrt(V_HC0[2, 2])
se_HC1 <- sqrt(V_HC1[2, 2])
se_HC2 <- sqrt(V_HC2[2, 2])
se_HC3 <- sqrt(V_HC3[2, 2])

cat("=== Erros-padrão de β̂₁ (construídos à mão) ===\n\n")
=== Erros-padrão de β̂₁ (construídos à mão) ===
cat(sprintf("%-6s  %8s\n", "Tipo", "EP(β̂₁)"))
Tipo    EP(β̂₁)
cat(sprintf("%-6s  %8.4f\n", "HC0", se_HC0))
HC0       0.0895
cat(sprintf("%-6s  %8.4f\n", "HC1", se_HC1))
HC1       0.0902
cat(sprintf("%-6s  %8.4f\n", "HC2", se_HC2))
HC2       0.0908
cat(sprintf("%-6s  %8.4f\n", "HC3", se_HC3))
HC3       0.0920
library(sandwich)
mod    <- lm(Y ~ X1 + X2)
se_pkg <- sqrt(c(
  sandwich::vcovHC(mod, type = "HC0")[2, 2],
  sandwich::vcovHC(mod, type = "HC1")[2, 2],
  sandwich::vcovHC(mod, type = "HC2")[2, 2],
  sandwich::vcovHC(mod, type = "HC3")[2, 2]
))

cat("\n=== Comparação com pacote sandwich ===\n\n")

=== Comparação com pacote sandwich ===
cat(sprintf("%-6s  %8s  %8s  %8s\n", "Tipo", "Manual", "Pacote", "Diferença"))
Tipo      Manual    Pacote  Diferença
for (i in 1:4) {
  tipo <- c("HC0","HC1","HC2","HC3")[i]
  man  <- c(se_HC0, se_HC1, se_HC2, se_HC3)[i]
  pkg  <- se_pkg[i]
  cat(sprintf("%-6s  %8.6f  %8.6f  %8.2e\n", tipo, man, pkg, man - pkg))
}
HC0     0.089519  0.089519  -6.94e-17
HC1     0.090198  0.090198  -5.55e-17
HC2     0.090755  0.090755  -8.33e-17
HC3     0.092021  0.092021  -9.71e-17
cat("\n→ Diferenças numéricas desprezíveis — construção manual confirmada.\n")

→ Diferenças numéricas desprezíveis — construção manual confirmada.

3.6 Por que HC3 > HC2 > HC0?

A diferença entre HC0, HC2 e HC3 está nos pesos aplicados aos resíduos ao quadrado. Como \(0\le h_{ii}<1\), temos

\[1 \;\le\; \frac{1}{1-h_{ii}} \;\le\; \frac{1}{(1-h_{ii})^2},\]

e portanto, para uma mesma observação, \(\text{HC0} \le \text{HC2} \le \text{HC3}\). Essa desigualdade é especialmente relevante quando \(h_{ii}\) é grande. O HC3 aumenta bastante o peso de observações com alta alavancagem, por isso costuma ser mais conservador em amostras finitas.

pesos <- data.frame(
  obs  = 1:n,
  HC0  = as.numeric(e_hat)^2,
  HC2  = w_HC2,
  HC3  = w_HC3,
  h_ii = h_ii
)

pesos_long <- tidyr::pivot_longer(pesos, cols = c(HC0, HC2, HC3),
                                   names_to = "tipo", values_to = "peso")

ggplot(pesos_long, aes(x = h_ii, y = peso, color = tipo)) +
  geom_point(alpha = 0.5) +
  facet_wrap(~tipo, scales = "free_y") +
  labs(title = "Pesos dos estimadores HC em função da alavancagem",
       subtitle = "HC2 e HC3 inflam os pesos para obs. com alta alavancagem",
       x = "Alavancagem (h_ii)", y = "Peso") +
  theme_minimal() + theme(legend.position = "none")

Pesos dos estimadores HC em função da alavancagem

3.7 Simulação com heterocedasticidade: erro-padrão clássico vs. robusto

Agora geramos um desenho em que a variância do erro depende de \(X_1\):

\[e_i=(1+|X_{1i}|)\varepsilon_i, \qquad \varepsilon_i\sim N(0,1),\]

de modo que \(\operatorname{Var}(e_i\mid X_i)=(1+|X_{1i}|)^2\). O MQO continua centrado em \(\beta\), porque mantemos \(\mathbb{E}[e_i\mid X_i]=0\). Porém, a fórmula homocedástica da variância deixa de ser apropriada.

set.seed(321)
eps_het <- rnorm(n)
e_het   <- (1 + abs(X1)) * eps_het
Y_het   <- X %*% beta_true + e_het

mod_het     <- lm(as.numeric(Y_het) ~ X1 + X2)
se_classico <- sqrt(vcov(mod_het)[2, 2])
se_hc1      <- sqrt(vcovHC(mod_het, type = "HC1")[2, 2])
se_hc2      <- sqrt(vcovHC(mod_het, type = "HC2")[2, 2])
se_hc3      <- sqrt(vcovHC(mod_het, type = "HC3")[2, 2])

cat("=== Erros-padrão sob heterocedasticidade ===\n\n")
=== Erros-padrão sob heterocedasticidade ===
cat(sprintf("%-12s %8.4f\n", "Clássico", se_classico))
Clássico      0.1403
cat(sprintf("%-12s %8.4f\n", "HC1",      se_hc1))
HC1            0.1992
cat(sprintf("%-12s %8.4f\n", "HC2",      se_hc2))
HC2            0.2015
cat(sprintf("%-12s %8.4f\n", "HC3",      se_hc3))
HC3            0.2053

Quando há heterocedasticidade, o erro-padrão clássico pode ficar subestimado ou superestimado, dependendo do desenho. Os erros-padrão robustos estimam diretamente

\[V_{\hat\beta} = (X^\top X)^{-1}(X^\top D X)(X^\top X)^{-1}\]

sem impor \(D=\sigma^2 I_n\).

3.8 Multicolinearidade: quando \(X^\top X\) quase não é invertível

Na multicolinearidade estrita, existe \(\alpha\neq 0\) tal que \(X\alpha=0\). Nesse caso, \(X^\top X\) é singular e \((X^\top X)^{-1}\) não existe. O MQO não é definido de forma única.

Na quase multicolinearidade, \(X^\top X\) ainda é invertível, mas é mal condicionado. Sob homocedasticidade,

\[\operatorname{Var}(\hat\beta\mid X)=\sigma^2(X^\top X)^{-1}.\]

Quando \((X^\top X)^{-1}\) tem entradas muito grandes, os erros-padrão também crescem. A quase multicolinearidade afeta a precisão do MQO exclusivamente por meio de \((X^\top X)^{-1}\).

set.seed(123)
X1_mc <- rnorm(n)
X2_mc <- X1_mc + rnorm(n, sd = 0.05)   # quase combinação linear
X_mc  <- cbind(1, X1_mc, X2_mc)
Y_mc  <- X_mc %*% beta_true + rnorm(n)

mod_mc      <- lm(as.numeric(Y_mc) ~ X1_mc + X2_mc)
cond_normal <- kappa(XtX)
cond_mc     <- kappa(t(X_mc) %*% X_mc)

cat("=== Multicolinearidade ===\n\n")
=== Multicolinearidade ===
cat("Condition number do desenho original:     ", round(cond_normal, 2), "\n")
Condition number do desenho original:      3.04 
cat("Condition number com quase colinearidade: ", round(cond_mc, 2), "\n\n")
Condition number com quase colinearidade:  1458.14 
print(summary(mod_mc)$coefficients)
             Estimate Std. Error   t value     Pr(>|t|)
(Intercept)  1.033632 0.06850599 15.088193 1.074398e-34
X1_mc        2.980762 1.37833627  2.162579 3.177849e-02
X2_mc       -2.013170 1.37843133 -1.460479 1.457514e-01

Mesmo que os coeficientes verdadeiros estejam bem definidos, a amostra tem dificuldade em separar o efeito individual de \(X_1\) e \(X_2\) quando eles carregam quase a mesma informação. O resultado típico é: coeficientes instáveis, erros-padrão grandes e baixa precisão individual.

3.9 Amostragem por clusters e dependência intracluster

Em muitos bancos de dados, as observações vêm agrupadas em clusters: alunos em escolas, trabalhadores em firmas, indivíduos em municípios. A hipótese apropriada é independência entre clusters, mas dependência dentro do cluster.

Para o cluster \(g\), escrevemos \(Y_g=X_g\beta+e_g\) e permitimos \(\Sigma_g=\mathbb{E}[e_ge_g^\top\mid X_g]\). O MQO continua sendo \((X^\top X)^{-1}X^\top Y\), mas a matriz de variância muda para

\[\operatorname{Var}(\hat\beta\mid X) = (X^\top X)^{-1} \left(\sum_{g=1}^G X_g^\top \Sigma_g X_g\right) (X^\top X)^{-1}.\]

A mensagem central: com clusters, o tamanho efetivo da amostra é mais próximo de \(G\), o número de clusters, do que de \(n\), o número total de observações.

library(lmtest)

set.seed(123)
G   <- 40
ng  <- 10
n_cl <- G * ng

cluster <- rep(1:G, each = ng)
X1_cl   <- rnorm(n_cl)
X2_cl   <- rnorm(n_cl)

# choque comum ao cluster + choque individual
a_g  <- rnorm(G, sd = 1)
u_cl <- a_g[cluster] + rnorm(n_cl, sd = 1)
Y_cl <- 1 + 2 * X1_cl - 1 * X2_cl + u_cl

mod_cl         <- lm(Y_cl ~ X1_cl + X2_cl)
se_classico_cl <- sqrt(vcov(mod_cl)[2, 2])
se_cluster_cl  <- sqrt(vcovCL(mod_cl, cluster = cluster)[2, 2])

cat("=== Erro-padrão clássico vs. cluster-robusto ===\n\n")
=== Erro-padrão clássico vs. cluster-robusto ===
cat("EP clássico de beta1:        ", round(se_classico_cl, 4), "\n")
EP clássico de beta1:         0.0755 
cat("EP cluster-robusto de beta1: ", round(se_cluster_cl, 4), "\n")
EP cluster-robusto de beta1:  0.0603 

Como os erros compartilham um componente comum dentro de cada cluster, tratar todas as observações como independentes tende a subestimar a incerteza. O erro-padrão cluster-robusto corrige a matriz de variância para permitir dependência arbitrária dentro dos clusters.

Fechamento da Aula 3

A Aula 3 mostra que, em amostra finita, o MQO tem propriedades muito fortes sob exogeneidade em média. Condicionalmente em \(X\), ele é não viesado:

\[\mathbb{E}[\hat\beta\mid X]=\beta.\]

Sua variância geral é \((X^\top X)^{-1}X^\top D X(X^\top X)^{-1}\) e, sob homocedasticidade, simplifica para \(\sigma^2(X^\top X)^{-1}\). O Teorema de Gauss-Markov garante que o MQO é BLUE sob homocedasticidade. Quando ela falha, entram os estimadores robustos HC0–HC3. A aula também mostra que \(\sigma^2\) precisa da correção \(n-k\), que multicolinearidade prejudica precisão via \((X^\top X)^{-1}\), e que em dados agrupados a inferência precisa respeitar a dependência intracluster.

Aula 4 — Regressões Normais: Inferência Exata

A Aula 4 introduz o modelo de regressão normal. Até aqui, nas aulas anteriores, conseguimos obter propriedades importantes do MQO, como não viés, variância condicional e Teorema de Gauss-Markov. Mas esses resultados ainda não davam, em geral, a distribuição exata das estatísticas de interesse.

A hipótese adicional desta aula é:

\[e\mid X\sim \mathcal{N}(0,\sigma^2 I_n).\]

Essa hipótese permite sair de resultados apenas sobre média e variância e obter distribuições exatas em amostra finita. Assim, conseguimos justificar formalmente:

\[\hat\beta\mid X\sim \mathcal{N}(\beta,\sigma^2(X^\top X)^{-1}),\]

\[\frac{(n-k)s^2}{\sigma^2}\sim \chi^2_{n-k},\]

\[T(\beta_j)=\frac{\hat\beta_j-\beta_j}{s(\hat\beta_j)}\sim t_{n-k},\]

e, para hipóteses conjuntas,

\[F\sim F_{q,n-k}.\]

A grande mensagem da Aula 4 é que, sob normalidade dos erros, a inferência clássica da regressão linear deixa de ser apenas aproximada e passa a ser exata em amostras finitas.

4.0 As distribuições da inferência exata

A normal padrão é \(Z\sim \mathcal{N}(0,1)\). Toda normal escalar pode ser escrita como transformação afim da normal padrão:

\[X=\mu+\sigma Z \quad\Rightarrow\quad X\sim \mathcal{N}(\mu,\sigma^2).\]

Na versão multivariada, se \(Z\sim \mathcal{N}(0,I_k)\), então seus componentes são independentes e normais padrão. Além disso, transformações afins preservam normalidade:

\[X\sim \mathcal{N}(\mu,\Sigma),\quad Y=a+BX \quad\Rightarrow\quad Y\sim \mathcal{N}(a+B\mu,B\Sigma B^\top).\]

Essas propriedades são fundamentais porque o MQO é uma transformação linear de \(Y\). Logo, se \(Y\mid X\) é normal, então \(\hat\beta\mid X\) também será normal.

As distribuições \(\chi^2\), \(t\) e \(F\) aparecem a partir da normal:

\[X\sim \mathcal{N}(0,I_k) \quad\Rightarrow\quad X^\top X\sim \chi^2_k.\]

Se \(Z\sim \mathcal{N}(0,1)\), \(Q\sim \chi^2_k\) e \(Z\perp Q\), então

\[\frac{Z}{\sqrt{Q/k}}\sim t_k.\]

E se \(U\sim\chi^2_q\), \(V\sim\chi^2_m\) e \(U\perp V\), então

\[\frac{U/q}{V/m}\sim F_{q,m}.\]

Essas três relações são a base matemática de toda a inferência exata da regressão normal.

4.1 Setup: modelo normal

Vamos trabalhar com o modelo \(Y=X\beta+e\), com \(e\mid X\sim\mathcal{N}(0,\sigma^2I_n)\).

A normalidade dos erros implica que, condicionalmente em \(X\), o vetor \(Y\) também é normal:

\[Y\mid X\sim \mathcal{N}(X\beta,\sigma^2I_n).\]

Essa hipótese é mais forte do que as hipóteses da Aula 3. Na Aula 3, bastava ter \(\mathbb{E}[e\mid X]=0\) e, para a fórmula clássica de variância, homocedasticidade. Agora, além disso, assumimos uma forma distributiva completa para os erros. O ganho é que podemos obter distribuições exatas em amostras finitas.

library(ggplot2)

set.seed(42)
n  <- 50
k  <- 3

X1 <- rnorm(n)
X2 <- 0.5 * X1 + rnorm(n)
X  <- cbind(1, X1, X2)

sigma2_true <- 4
beta_true   <- c(1, 2, -1)

e_true <- rnorm(n, sd = sqrt(sigma2_true))
Y      <- X %*% beta_true + e_true

XtX      <- t(X) %*% X
XtX_inv  <- solve(XtX)
beta_hat <- XtX_inv %*% t(X) %*% Y
P        <- X %*% XtX_inv %*% t(X)
M        <- diag(n) - P
e_hat    <- M %*% Y

s2 <- as.numeric(t(e_hat) %*% e_hat) / (n - k)

cat("sigma² verdadeiro:", sigma2_true, "\n")
sigma² verdadeiro: 4 
cat("s² (estimado):    ", round(s2, 4), "\n")
s² (estimado):     3.5474 

4.1.1 Verossimilhança e MLE: por que o MLE de \(\beta\) é o MQO?

Sob o modelo normal, \(Y_i\mid X_i\sim \mathcal{N}(X_i^\top\beta,\sigma^2)\). Com independência entre observações, a log-verossimilhança é

\[\ell_n(\beta,\sigma^2) = -\frac{n}{2}\log(2\pi\sigma^2) - \frac{1}{2\sigma^2}\sum_{i=1}^n(Y_i-X_i^\top\beta)^2.\]

Para \(\sigma^2\) fixo, maximizar \(\ell_n(\beta,\sigma^2)\) em relação a \(\beta\) é o mesmo que minimizar \(\sum_{i=1}^n(Y_i-X_i^\top\beta)^2\). Portanto, no modelo normal, o MLE de \(\beta\) coincide com o MQO:

\[\hat\beta_{MLE}=\hat\beta_{MQO}.\]

Essa é uma conexão importante: o MQO pode ser visto tanto como uma projeção geométrica quanto como um estimador de máxima verossimilhança sob normalidade.

sigma2_mle <- as.numeric(t(e_hat) %*% e_hat) / n

cat("=== MLE no modelo normal ===\n\n")
=== MLE no modelo normal ===
cat("beta_hat MQO/MLE:\n")
beta_hat MQO/MLE:
print(round(beta_hat, 4))
      [,1]
    0.6995
X1  2.1548
X2 -0.9570
cat("\nMLE de sigma² usa divisor n:      ", round(sigma2_mle, 4), "\n")

MLE de sigma² usa divisor n:       3.3346 
cat("Estimador não viesado s² usa n-k: ", round(s2, 4), "\n")
Estimador não viesado s² usa n-k:  3.5474 

Note que o MLE de \(\sigma^2\) usa divisor \(n\), enquanto o estimador clássico não viesado usa divisor \(n-k\). Assim, no modelo normal, o MLE de \(\beta\) coincide com o MQO, mas o MLE de \(\sigma^2\) não coincide com \(s^2\).

4.2 Distribuição exata de \(\hat\beta\): verificação por simulação

Como \(\hat\beta = \beta+(X^\top X)^{-1}X^\top e\) e \(e\mid X\sim\mathcal{N}(0,\sigma^2I_n)\), segue que \(\hat\beta\mid X\) é uma transformação afim de um vetor normal. Logo,

\[\hat\beta\mid X \sim \mathcal{N}(\beta,\sigma^2(X^\top X)^{-1}).\]

Esse é o Teorema D.4 dos slides. A diferença em relação à Aula 3 é que lá sabíamos apenas a média e a variância de \(\hat\beta\). Agora sabemos sua distribuição completa.

B <- 5000
beta1_sim <- numeric(B)
beta2_sim <- numeric(B)

for (b in 1:B) {
  e_b          <- rnorm(n, sd = sqrt(sigma2_true))
  Y_b          <- X %*% beta_true + e_b
  b_hat        <- XtX_inv %*% t(X) %*% Y_b
  beta1_sim[b] <- b_hat[2]
  beta2_sim[b] <- b_hat[3]
}

var_beta1_teo <- sigma2_true * XtX_inv[2, 2]
sd_beta1_teo  <- sqrt(var_beta1_teo)

cat("=== Distribuição de β̂₁ ===\n\n")
=== Distribuição de β̂₁ ===
cat("Média teórica:     ", beta_true[2], "\n")
Média teórica:      2 
cat("Média simulada:    ", round(mean(beta1_sim), 4), "\n")
Média simulada:     1.9985 
cat("DP teórico:        ", round(sd_beta1_teo, 4), "\n")
DP teórico:         0.2668 
cat("DP simulado:       ", round(sd(beta1_sim), 4), "\n")
DP simulado:        0.2674 
x_grid     <- seq(min(beta1_sim), max(beta1_sim), length.out = 200)
normal_teo <- dnorm(x_grid, mean = beta_true[2], sd = sd_beta1_teo)

ggplot(data.frame(b1 = beta1_sim), aes(x = b1)) +
  geom_histogram(aes(y = after_stat(density)),
                 bins = 60, fill = "steelblue", alpha = 0.6) +
  geom_line(data = data.frame(x = x_grid, y = normal_teo),
            aes(x = x, y = y), color = "red", linewidth = 1.2) +
  labs(title = "β̂₁ ~ N(β₁, σ²[(X'X)⁻¹]₁₁) — Teorema D.4",
       subtitle = "Histograma simulado (azul) vs Normal teórica (vermelho)",
       x = "β̂₁", y = "Densidade") +
  theme_minimal()

Distribuição simulada de β̂₁ vs Normal teórica

O histograma simulado de \(\hat\beta_1\) coincide muito bem com a densidade normal teórica. Como estamos mantendo \(X\) fixo e simulando apenas novos erros normais, essa é uma ilustração direta da distribuição condicional \(\hat\beta\mid X\).

4.2.1 Distribuição dos resíduos e independência entre \(\hat\beta\) e \(\hat{e}\)

Da Aula 2, sabemos que \(\hat{e}=MY\) com \(M=I-X(X^\top X)^{-1}X^\top\). Como \(MX=0\), temos \(\hat{e}=Me\). Como \(e\mid X\sim\mathcal{N}(0,\sigma^2I_n)\), os resíduos também são normais:

\[\hat{e}\mid X\sim\mathcal{N}(0,\sigma^2M).\]

Além disso, no modelo normal, \(\hat\beta\perp \hat{e}\). Essa independência é crucial: a estatística \(t\) nasce justamente da combinação de uma parte que depende de \(\hat\beta\) com outra que depende de \(s^2\), que é função dos resíduos. A normalidade garante que essas partes sejam independentes.

s2_sim <- numeric(B)
for (b in 1:B) {
  e_b      <- rnorm(n, sd = sqrt(sigma2_true))
  Y_b      <- X %*% beta_true + e_b
  b_hat    <- XtX_inv %*% t(X) %*% Y_b
  e_hat_b  <- Y_b - X %*% b_hat
  s2_sim[b] <- sum(e_hat_b^2) / (n - k)
}

corr_beta1_s2 <- cor(beta1_sim, s2_sim)

cat("=== Independência entre beta_hat e s² ===\n\n")
=== Independência entre beta_hat e s² ===
cat("Correlação simulada entre β̂₁ e s²:", round(corr_beta1_s2, 4), "\n")
Correlação simulada entre β̂₁ e s²: 0.0147 
cat("Sob normalidade, a independência teórica implica correlação zero.\n")
Sob normalidade, a independência teórica implica correlação zero.

4.3 Distribuição exata de \(s^2\): qui-quadrado

O estimador não viesado da variância do erro é \(s^2=\frac{1}{n-k}\hat{e}^\top\hat{e}\). Como \(\hat{e}=Me\) e \(M\) é simétrica, idempotente e tem posto \(n-k\), temos sob normalidade:

\[\frac{(n-k)s^2}{\sigma^2}\sim\chi^2_{n-k}.\]

Esse resultado é o Teorema D.6 e é a base para construir tanto a estatística \(t\) quanto intervalos de confiança para \(\sigma^2\).

stat_sim  <- (n - k) * s2_sim / sigma2_true
x_grid2   <- seq(0, max(stat_sim), length.out = 300)
chi2_teo  <- dchisq(x_grid2, df = n - k)

ggplot(data.frame(stat = stat_sim), aes(x = stat)) +
  geom_histogram(aes(y = after_stat(density)),
                 bins = 60, fill = "steelblue", alpha = 0.6) +
  geom_line(data = data.frame(x = x_grid2, y = chi2_teo),
            aes(x = x, y = y), color = "red", linewidth = 1.2) +
  labs(title = "(n-k)s²/σ² ~ χ²(n-k) — Teorema D.6",
       subtitle = paste("n-k =", n-k, "graus de liberdade"),
       x = "(n-k)s²/σ²", y = "Densidade") +
  theme_minimal()

Distribuição de (n-k)s²/σ² vs χ²(n-k)
cat("Média teórica de χ²(n-k):", n - k, "\n")
Média teórica de χ²(n-k): 47 
cat("Média simulada:           ", round(mean(stat_sim), 4), "\n")
Média simulada:            46.7293 

4.4 Estatística-\(t\): construção manual

Se \(\sigma^2\) fosse conhecido, poderíamos padronizar

\[Z = \frac{\hat\beta_j-\beta_j}{\sigma\sqrt{[(X^\top X)^{-1}]_{jj}}} \sim N(0,1).\]

Mas \(\sigma^2\) não é conhecido. Substituímos por \(s^2\), obtendo o erro-padrão clássico:

\[s(\hat\beta_j) = \sqrt{s^2[(X^\top X)^{-1}]_{jj}}.\]

A estatística resultante é

\[T(\beta_j) = \frac{\hat\beta_j-\beta_j}{s(\hat\beta_j)}.\]

Como o numerador é normal e o denominador depende de uma qui-quadrado independente, temos \(T(\beta_j)\sim t_{n-k}\).

se_beta1 <- sqrt(s2 * XtX_inv[2, 2])
T_obs    <- (beta_hat[2] - beta_true[2]) / se_beta1

cat("=== Estatística-t manual ===\n\n")
=== Estatística-t manual ===
cat("β̂₁:           ", round(beta_hat[2], 4), "\n")
β̂₁:            2.1548 
cat("EP(β̂₁):       ", round(se_beta1, 4), "\n")
EP(β̂₁):        0.2512 
cat("T observado:   ", round(T_obs, 4), "\n")
T observado:    0.6164 
cat("(sob H0 verdadeira, deve vir de t(", n-k, "))\n\n")
(sob H0 verdadeira, deve vir de t( 47 ))
T_sim <- numeric(B)
for (b in 1:B) {
  e_b      <- rnorm(n, sd = sqrt(sigma2_true))
  Y_b      <- X %*% beta_true + e_b
  b_hat_b  <- XtX_inv %*% t(X) %*% Y_b
  e_b_hat  <- Y_b - X %*% b_hat_b
  s2_b     <- sum(e_b_hat^2) / (n - k)
  se_b     <- sqrt(s2_b * XtX_inv[2, 2])
  T_sim[b] <- (b_hat_b[2] - beta_true[2]) / se_b
}

x_t    <- seq(-5, 5, length.out = 300)
t_teo  <- dt(x_t, df = n - k)
t_norm <- dnorm(x_t)

ggplot(data.frame(t = T_sim), aes(x = t)) +
  geom_histogram(aes(y = after_stat(density)),
                 bins = 80, fill = "steelblue", alpha = 0.6) +
  geom_line(data = data.frame(x = x_t, y = t_teo),
            aes(x = x, y = y, color = "t(n-k)"), linewidth = 1.2) +
  geom_line(data = data.frame(x = x_t, y = t_norm),
            aes(x = x, y = y, color = "N(0,1)"),
            linewidth = 1, linetype = "dashed") +
  scale_color_manual(values = c("t(n-k)" = "red", "N(0,1)" = "darkgreen")) +
  labs(title = "T(β₁) ~ t(n-k) — Teorema D.7",
       subtitle = "Com n=50, a t tem caudas mais pesadas que a Normal",
       x = "T", y = "Densidade", color = "") +
  theme_minimal()

Distribuição de T(β₁) vs t(n-k)

4.4.1 Teste-\(t\) para uma única restrição

Para testar \(H_0:\beta_j=\beta_{j,0}\) contra \(H_1:\beta_j\neq\beta_{j,0}\), usamos

\[T = \frac{\hat\beta_j-\beta_{j,0}}{s(\hat\beta_j)}.\]

Sob \(H_0\), \(T\sim t_{n-k}\). No teste bilateral, rejeitamos \(H_0\) ao nível \(\alpha\) se \(|T|>t^{-1}_{n-k}(1-\alpha/2)\). O p-valor bilateral é

\[p=2\left[1-F_{t_{n-k}}(|T|)\right].\]

beta10  <- beta_true[2]
T_beta1 <- as.numeric((beta_hat[2] - beta10) / se_beta1)
pval_t  <- 2 * pt(abs(T_beta1), df = n - k, lower.tail = FALSE)

cat("=== Teste-t bilateral para H0: beta1 =", beta10, "===\n\n")
=== Teste-t bilateral para H0: beta1 = 2 ===
cat("T observado:", round(T_beta1, 4), "\n")
T observado: 0.6164 
cat("p-valor:    ", round(pval_t, 4), "\n")
p-valor:     0.5406 

4.5 Teste-\(F\): construção manual

O teste-\(F\) serve para testar hipóteses conjuntas, como \(H_0:\beta_1=\beta_2=0\). Comparamos dois modelos: o restrito (apenas intercepto) e o irrestrito (intercepto, \(X_1\) e \(X_2\)). A estatística é

\[F = \frac{(SSE_R-SSE_U)/q}{SSE_U/(n-k)},\]

onde \(SSE_R\) é a soma dos quadrados residual do modelo restrito, \(SSE_U\) é a do modelo irrestrito, \(q\) é o número de restrições e \(n-k\) são os graus de liberdade residuais do modelo irrestrito.

A intuição é simples: o numerador mede quanto o ajuste piora ao impor \(H_0\), por restrição. O denominador mede o ruído residual médio do modelo irrestrito. No modelo normal, sob \(H_0\), \(F\sim F_{q,n-k}\).

X_rest   <- matrix(1, n, 1)
b_rest   <- solve(t(X_rest) %*% X_rest) %*% t(X_rest) %*% Y
e_rest   <- Y - X_rest %*% b_rest
SSE_rest <- as.numeric(t(e_rest) %*% e_rest)
SSE_irr  <- as.numeric(t(e_hat) %*% e_hat)
q        <- 2

F_obs  <- ((SSE_rest - SSE_irr) / q) / (SSE_irr / (n - k))
pval_F <- pf(F_obs, df1 = q, df2 = n - k, lower.tail = FALSE)

cat("=== Teste F manual ===\n\n")
=== Teste F manual ===
cat("SSE restrito:   ", round(SSE_rest, 4), "\n")
SSE restrito:    427.723 
cat("SSE irrestrito: ", round(SSE_irr, 4), "\n")
SSE irrestrito:  166.7281 
cat("F observado:    ", round(F_obs, 4), "\n")
F observado:     36.7867 
cat("p-valor:        ", round(pval_F, 6), "\n\n")
p-valor:         0 
mod_irr  <- lm(Y ~ X1 + X2)
mod_rest <- lm(Y ~ 1)
anova_res <- anova(mod_rest, mod_irr)

cat("=== Comparação com anova() ===\n")
=== Comparação com anova() ===
cat("F via anova(): ", round(anova_res$F[2], 4), "\n")
F via anova():  36.7867 
cat("p via anova(): ", round(anova_res$`Pr(>F)`[2], 6), "\n")
p via anova():  0 
cat("\n→ Idênticos. F construído à mão = F do lm().\n")

→ Idênticos. F construído à mão = F do lm().

O resultado manual coincide com anova(). Como \(\beta_1=2\) e \(\beta_2=-1\), a hipótese \(H_0:\beta_1=\beta_2=0\) é falsa; por isso o \(F\) observado é grande e o p-valor é praticamente zero.

4.6 Intervalo de confiança para \(\beta_1\)

O intervalo de confiança exato para \(\beta_j\) usa o quantil da distribuição \(t_{n-k}\):

\[\hat{C} = \left[\hat\beta_j - t^{-1}_{n-k}(1-\alpha/2)\,s(\hat\beta_j),\; \hat\beta_j + t^{-1}_{n-k}(1-\alpha/2)\,s(\hat\beta_j)\right].\]

No modelo normal, esse intervalo tem cobertura exata \(1-\alpha\).

t_crit <- qt(0.975, df = n - k)
IC_low <- beta_hat[2] - t_crit * se_beta1
IC_up  <- beta_hat[2] + t_crit * se_beta1

cat("=== IC 95% para β₁ (manual) ===\n")
=== IC 95% para β₁ (manual) ===
cat("β̂₁:", round(beta_hat[2], 4), "\n")
β̂₁: 2.1548 
cat("IC: [", round(IC_low, 4), ",", round(IC_up, 4), "]\n")
IC: [ 1.6494 , 2.6602 ]
cat("Valor verdadeiro (", beta_true[2], ") está no intervalo?",
    IC_low <= beta_true[2] & beta_true[2] <= IC_up, "\n")
Valor verdadeiro ( 2 ) está no intervalo? TRUE 

4.7 Intervalo de confiança para \(\sigma^2\)

Como \((n-k)s^2/\sigma^2\sim\chi^2_{n-k}\), definindo \(c_1=\chi^2_{n-k}(\alpha/2)\) e \(c_2=\chi^2_{n-k}(1-\alpha/2)\), temos

\[P\!\left(\frac{(n-k)s^2}{c_2} \le \sigma^2 \le \frac{(n-k)s^2}{c_1}\right)=1-\alpha.\]

Diferentemente do intervalo para \(\beta_j\), esse intervalo não é simétrico, porque a distribuição qui-quadrado é assimétrica.

alpha <- 0.05
df    <- n - k
c1    <- qchisq(alpha / 2, df = df)
c2    <- qchisq(1 - alpha / 2, df = df)

IC_sigma_low <- df * s2 / c2
IC_sigma_up  <- df * s2 / c1

cat("=== IC 95% para sigma² ===\n\n")
=== IC 95% para sigma² ===
cat("IC: [", round(IC_sigma_low, 4), ",", round(IC_sigma_up, 4), "]\n")
IC: [ 2.4584 , 5.5657 ]
cat("sigma² verdadeiro:", sigma2_true, "\n")
sigma² verdadeiro: 4 
cat("Contém sigma² verdadeiro?",
    IC_sigma_low <= sigma2_true & sigma2_true <= IC_sigma_up, "\n")
Contém sigma² verdadeiro? TRUE 

4.8 Cobertura empírica do IC 95%

Um intervalo de confiança de 95% não significa que há 95% de probabilidade de o parâmetro fixo estar naquele intervalo específico depois de observado. A interpretação frequentista é: se repetíssemos o experimento muitas vezes, aproximadamente 95% dos intervalos construídos conteriam o parâmetro verdadeiro. No modelo normal, usando a distribuição \(t_{n-k}\), essa cobertura é exata em amostra finita.

cobertura <- numeric(B)
for (b in 1:B) {
  e_b      <- rnorm(n, sd = sqrt(sigma2_true))
  Y_b      <- X %*% beta_true + e_b
  b_hat_b  <- XtX_inv %*% t(X) %*% Y_b
  e_b_hat  <- Y_b - X %*% b_hat_b
  s2_b     <- sum(e_b_hat^2) / (n - k)
  se_b     <- sqrt(s2_b * XtX_inv[2, 2])
  t_crit_b <- qt(0.975, df = n - k)
  low_b    <- b_hat_b[2] - t_crit_b * se_b
  up_b     <- b_hat_b[2] + t_crit_b * se_b
  cobertura[b] <- (low_b <= beta_true[2]) & (beta_true[2] <= up_b)
}

cat("=== Cobertura empírica do IC 95% ===\n\n")
=== Cobertura empírica do IC 95% ===
cat("Taxa de cobertura (B=5000):", round(mean(cobertura), 4), "\n")
Taxa de cobertura (B=5000): 0.9526 
cat("Esperado:                   0.95\n")
Esperado:                   0.95
cat("\n→ O IC t tem cobertura exata sob normalidade dos erros.\n")

→ O IC t tem cobertura exata sob normalidade dos erros.

4.9 Bound de Cramér–Rao e eficiência do MQO

A Aula 4 termina com o bound de Cramér–Rao. No modelo normal, os scores são:

\[\frac{\partial \ell}{\partial \beta} = \frac{1}{\sigma^2}X^\top e, \qquad \frac{\partial \ell}{\partial \sigma^2} = -\frac{n}{2\sigma^2} + \frac{1}{2\sigma^4}\sum_{i=1}^n e_i^2.\]

A matriz de informação condicional em \(X\) é

\[I = \begin{pmatrix} \frac{1}{\sigma^2}X^\top X & 0\\ 0 & \frac{n}{2\sigma^4} \end{pmatrix}, \qquad I^{-1} = \begin{pmatrix} \sigma^2(X^\top X)^{-1} & 0\\ 0 & \frac{2\sigma^4}{n} \end{pmatrix}.\]

Como \(\operatorname{Var}(\hat\beta\mid X)=\sigma^2(X^\top X)^{-1}\), o MQO atinge o bound de Cramér–Rao para \(\beta\). Portanto, no modelo normal, \(\hat\beta\) é eficiente no sentido de Cramér–Rao: nenhum estimador não viesado de \(\beta\) pode ter matriz de variância menor.

V_beta_cr <- sigma2_true * XtX_inv

cat("=== Cramér-Rao para beta ===\n\n")
=== Cramér-Rao para beta ===
cat("Variância exata de beta_hat = bloco de beta em I^{-1}:\n")
Variância exata de beta_hat = bloco de beta em I^{-1}:
print(round(V_beta_cr, 4))
                X1      X2
    0.0810  0.0051 -0.0095
X1  0.0051  0.0712 -0.0312
X2 -0.0095 -0.0312  0.1012

Fechamento da Aula 4

A Aula 4 mostra que a normalidade dos erros transforma a inferência do MQO em uma teoria exata de amostra finita. Sob \(e\mid X\sim \mathcal{N}(0,\sigma^2I_n)\), temos

\[\hat\beta\mid X\sim \mathcal{N}(\beta,\sigma^2(X^\top X)^{-1}), \qquad \frac{(n-k)s^2}{\sigma^2}\sim\chi^2_{n-k}, \qquad T(\beta_j)\sim t_{n-k}, \qquad F\sim F_{q,n-k}.\]

Esses resultados justificam os testes \(t\), os intervalos de confiança, os p-valores e os testes \(F\) clássicos. A aula também mostra que, no modelo normal, o MQO coincide com o MLE de \(\beta\) e atinge o bound de Cramér–Rao. Portanto, nessa estrutura, o MQO é não apenas BLUE, mas também eficiente em um sentido mais forte.

Aula 5 — Normalidade Assintótica do MQO

A Aula 5 muda o regime da inferência. Na Aula 4, a distribuição exata de \(\hat\beta\) vinha da hipótese forte de normalidade dos erros:

\[e\mid X\sim \mathcal{N}(0,\sigma^2 I_n).\]

Agora, essa hipótese é removida. Em vez de exigir normalidade exata dos erros, passamos a usar resultados assintóticos: Lei dos Grandes Números, Teorema Central do Limite, Teorema do Mapeamento Contínuo, Slutsky e Método Delta.

A ideia central é que \(\hat\beta \to_p \beta\) e

\[\sqrt{n}(\hat\beta-\beta)\Rightarrow \mathcal{N}(0,V_\beta).\]

Ou seja, o MQO é consistente e, depois de reescalado por \(\sqrt{n}\), tem distribuição aproximadamente normal para amostras grandes. A Aula 5 mostra que essa normalidade não vem mais da normalidade dos erros, mas do Teorema Central do Limite aplicado ao termo

\[\frac{1}{\sqrt{n}}\sum_{i=1}^n X_i e_i.\]

5.1 A ideia central: de exato para assintótico

Na Aula 4, a normalidade de \(\hat\beta\) veio da hipótese \(e \mid X \sim \mathcal{N}(0,\sigma^2 I_n)\). Aqui removemos essa hipótese. Os erros podem ter qualquer distribuição com média zero e variância finita. A normalidade de \(\hat\beta\) emerge assintoticamente pelo TCL — mas só vale aproximadamente para \(n\) finito.

library(ggplot2)

set.seed(42)
k <- 3

gera_dados <- function(n, dist_erro = "normal") {
  X1 <- rnorm(n)
  X2 <- 0.5 * X1 + rnorm(n)
  X  <- cbind(1, X1, X2)
  e  <- switch(dist_erro,
    "normal"   = rnorm(n),
    "chi2"     = (rchisq(n, df = 2) - 2) / 2,
    "uniforme" = runif(n, -sqrt(3), sqrt(3))
  )
  Y <- X %*% c(1, 2, -1) + e
  list(X = X, Y = Y)
}

5.2 Consistência: \(\hat\beta \to_p \beta\) quando \(n \to \infty\)

A consistência do MQO vem da ideia plug-in. O estimador pode ser escrito como

\[\hat\beta=\hat{Q}_{XX}^{-1}\hat{Q}_{XY},\]

onde

\[\hat{Q}_{XX}=\frac{1}{n}\sum_{i=1}^n X_iX_i^\top \quad\text{e}\quad \hat{Q}_{XY}=\frac{1}{n}\sum_{i=1}^n X_iY_i.\]

Pela Lei Fraca dos Grandes Números,

\[\hat{Q}_{XX}\to_p Q_{XX} \quad\text{e}\quad \hat{Q}_{XY}\to_p Q_{XY}.\]

Como \(Q_{XX}\) é invertível, pelo Teorema do Mapeamento Contínuo,

\[\hat\beta=\hat{Q}_{XX}^{-1}\hat{Q}_{XY} \to_p Q_{XX}^{-1}Q_{XY} = \beta.\]

Na simulação abaixo, usamos erros não normais para reforçar que consistência não depende de normalidade dos erros.

tamanhos   <- c(10, 30, 50, 100, 300, 500, 1000, 3000)
B          <- 1000
beta1_true <- 2

res <- lapply(tamanhos, function(n) {
  b1_vec <- replicate(B, {
    d     <- gera_dados(n, "chi2")
    b_hat <- solve(t(d$X) %*% d$X) %*% t(d$X) %*% d$Y
    b_hat[2]
  })
  data.frame(n = n, media = mean(b1_vec), dp = sd(b1_vec))
})

res_df <- do.call(rbind, res)

cat("=== Consistência de β̂₁ (erros chi² centralizados) ===\n\n")
=== Consistência de β̂₁ (erros chi² centralizados) ===
cat(sprintf("%-6s  %8s  %8s\n", "n", "E[β̂₁]", "DP(β̂₁)"))
n       E[β̂₁]  DP(β̂₁)
for (i in 1:nrow(res_df)) {
  cat(sprintf("%-6d  %8.4f  %8.4f\n",
              res_df$n[i], res_df$media[i], res_df$dp[i]))
}
10        2.0076    0.4546
30        1.9951    0.2148
50        2.0042    0.1683
100       2.0030    0.1080
300       2.0002    0.0670
500       2.0008    0.0518
1000      2.0006    0.0357
3000      2.0017    0.0207
ggplot(res_df, aes(x = n)) +
  geom_line(aes(y = media), color = "steelblue", linewidth = 1) +
  geom_ribbon(aes(ymin = media - 2*dp, ymax = media + 2*dp),
              alpha = 0.2, fill = "steelblue") +
  geom_hline(yintercept = beta1_true, color = "red",
             linetype = "dashed", linewidth = 1) +
  scale_x_log10() +
  labs(title = "Consistência do MQO — erros chi² (não normais)",
       subtitle = "Faixa = média ± 2 DP | Vermelho = valor verdadeiro",
       x = "n (escala log)", y = "β̂₁") +
  theme_minimal()

Convergência de β̂₁ para β₁ conforme n cresce

5.3 Normalidade assintótica: \(\sqrt{n}(\hat\beta - \beta) \to_d \mathcal{N}(0, V_\beta)\)

B      <- 3000
distrs <- c("normal", "chi2", "uniforme")
ns     <- c(30, 200, 1000)

resultados <- list()

for (dist in distrs) {
  for (n in ns) {
    t_stats <- replicate(B, {
      d     <- gera_dados(n, dist)
      b_hat <- solve(t(d$X) %*% d$X) %*% t(d$X) %*% d$Y
      sqrt(n) * (b_hat[2] - beta1_true)
    })
    resultados[[paste(dist, n)]] <- data.frame(
      stat = t_stats,
      dist = dist,
      n    = n
    )
  }
}

df_plot       <- do.call(rbind, resultados)
df_plot$label <- factor(paste0("n=", df_plot$n), levels = paste0("n=", ns))

ggplot(df_plot, aes(x = stat)) +
  geom_histogram(aes(y = after_stat(density)),
                 bins = 50, fill = "steelblue", alpha = 0.6) +
  facet_grid(dist ~ label, scales = "free") +
  labs(title = "√n(β̂₁ - β₁): aproximação normal assintótica",
       subtitle = "A forma se aproxima de uma normal conforme n cresce",
       x = "√n(β̂₁ - β₁)", y = "Densidade") +
  theme_minimal(base_size = 9)

√n(β̂₁ - β₁) para diferentes distribuições de erro

A normalidade assintótica não diz que \(\hat\beta\) é exatamente normal em amostras finitas. Ela diz que, para \(n\) grande, \(\sqrt{n}(\hat\beta-\beta)\) passa a ser aproximadamente normal. A qualidade dessa aproximação depende da distribuição dos erros, da presença de caudas pesadas, da heterocedasticidade e do tamanho amostral. Por isso, não existe um \(n\) universalmente “grande o suficiente” que garanta boa aproximação para todas as distribuições.

5.4 Método Delta: inferência sobre funções de \(\beta\)

O Método Delta permite obter a distribuição assintótica de funções suaves dos parâmetros. Se

\[\sqrt{n}(\hat\beta-\beta)\Rightarrow \mathcal{N}(0,V_\beta) \quad \text{e} \quad \theta=g(\beta),\]

então

\[\sqrt{n}(g(\hat\beta)-g(\beta)) \Rightarrow \mathcal{N}(0,\nabla g(\beta)^\top V_\beta \nabla g(\beta)).\]

Na prática, se usamos diretamente a matriz vcov() do modelo, ela já estima a variância de \(\hat\beta\), não a variância de \(\sqrt{n}(\hat\beta-\beta)\). Por isso, nesse caso, não devemos dividir novamente por \(n\).

Exemplo: razão entre os coeficientes dos dois regressores:

\[\theta=\frac{\beta_{X_1}}{\beta_{X_2}}.\]

set.seed(42)
n <- 500
B <- 5000

beta_true_md <- c(1, 4, -2)
theta_true   <- beta_true_md[2] / beta_true_md[3]

theta_sim <- numeric(B)

for (b in 1:B) {
  d     <- gera_dados(n, "normal")
  Y_b   <- d$X %*% beta_true_md + rnorm(n)
  b_hat <- solve(t(d$X) %*% d$X) %*% t(d$X) %*% Y_b
  theta_sim[b] <- b_hat[2] / b_hat[3]
}

# Amostra de referência para calcular a variância delta
d_ref   <- gera_dados(n, "normal")
Y_ref   <- d_ref$X %*% beta_true_md + rnorm(n)
mod_ref <- lm(as.numeric(Y_ref) ~ d_ref$X[, 2] + d_ref$X[, 3])

b_ref       <- coef(mod_ref)
V_beta_hat  <- vcov(mod_ref)

# gradiente de g(beta) = beta_X1/beta_X2
grad_g <- c(0, 1 / b_ref[3], -b_ref[2] / b_ref[3]^2)

V_theta_hat    <- as.numeric(t(grad_g) %*% V_beta_hat %*% grad_g)
sd_theta_delta <- sqrt(V_theta_hat)

cat("=== Método Delta: θ = β₁/β₂ ===\n\n")
=== Método Delta: θ = β₁/β₂ ===
cat("θ verdadeiro:       ", theta_true, "\n")
θ verdadeiro:        -2 
cat("Média de θ̂ (sim):  ", round(mean(theta_sim), 4), "\n")
Média de θ̂ (sim):   -2.0015 
cat("DP delta:           ", round(sd_theta_delta, 4), "\n")
DP delta:            0.037 
cat("DP empírico (sim):  ", round(sd(theta_sim), 4), "\n")
DP empírico (sim):   0.0404 

5.5 Estatística de Wald: \(W \to_d \chi^2_q\)

A estatística de Wald pode ser escrita em duas escalas equivalentes:

\[W=(\hat\theta-\theta_0)^\top\widehat{\operatorname{Var}}(\hat\theta)^{-1}(\hat\theta-\theta_0),\]

ou

\[W=n(\hat\theta-\theta_0)^\top\hat{V}_\theta^{-1}(\hat\theta-\theta_0),\]

onde \(\hat{V}_\theta\) estima a variância assintótica de \(\sqrt{n}(\hat\theta-\theta)\). O erro comum é misturar as duas escalas: se \(\widehat{\operatorname{Var}}(\hat\theta)\) já está na escala finita-amostral, não se multiplica por \(n\).

Para \(\theta \in \mathbb{R}^q\), sob \(H_0\):

\[W(\theta_0) = (\hat\theta - \theta_0)^\top \hat{V}_{\hat\theta}^{-1} (\hat\theta - \theta_0) \to_d \chi^2_q.\]

set.seed(42)
n <- 300
B <- 5000
q <- 2

W_sim <- numeric(B)

for (b in 1:B) {
  d     <- gera_dados(n, "chi2")
  Y_b   <- d$X %*% c(1, 2, -1) + (rchisq(n, 2) - 2) / 2
  XtX_b <- t(d$X) %*% d$X
  b_hat <- solve(XtX_b) %*% t(d$X) %*% Y_b
  e_b   <- Y_b - d$X %*% b_hat

  n_b       <- nrow(d$X)
  k_b       <- ncol(d$X)
  XtX_inv_b <- solve(XtX_b)
  Omega     <- t(d$X) %*% diag(as.numeric(e_b)^2) %*% d$X
  V_b       <- (n_b / (n_b - k_b)) * XtX_inv_b %*% Omega %*% XtX_inv_b

  theta_hat <- b_hat[2:3]
  theta_0   <- c(2, -1)
  V_theta_b <- V_b[2:3, 2:3]

  W_sim[b] <- as.numeric(
    t(theta_hat - theta_0) %*% solve(V_theta_b) %*% (theta_hat - theta_0)
  )
}

x_chi <- seq(0, 20, length.out = 300)

ggplot(data.frame(W = W_sim), aes(x = W)) +
  geom_histogram(aes(y = after_stat(density)),
                 bins = 60, fill = "steelblue", alpha = 0.6) +
  geom_line(data = data.frame(x = x_chi, y = dchisq(x_chi, df = q)),
            aes(x = x, y = y), color = "red", linewidth = 1.2) +
  labs(title = paste0("W ~ χ²(", q, ") sob H₀ — Teorema E.20"),
       subtitle = "Erros chi² (não normais) — resultado assintótico",
       x = "W", y = "Densidade") +
  coord_cartesian(xlim = c(0, 15)) +
  theme_minimal()

Distribuição de W sob H₀ vs χ²(q)
cat("Média de W (sim):", round(mean(W_sim), 3),
    " | Esperado χ² com q =", q, ":", q, "\n")
Média de W (sim): 2.051  | Esperado χ² com q = 2 : 2 
cat("Quantil 95% empírico:", round(quantile(W_sim, 0.95), 3), "\n")
Quantil 95% empírico: 6.175 
cat("Quantil 95% χ²(q):   ", round(qchisq(0.95, df = q), 3), "\n")
Quantil 95% χ²(q):    5.991 

5.6 Estimadores consistentes de variância

A normalidade assintótica do MQO tem variância

\[V_\beta = Q_{XX}^{-1}\,\Omega\, Q_{XX}^{-1},\]

onde \(Q_{XX}=\mathbb{E}[XX^\top]\) e \(\Omega=\mathbb{E}[XX^\top e^2]\). Sob homocedasticidade, \(\Omega=\sigma^2 Q_{XX}\), então \(V_\beta^0=\sigma^2 Q_{XX}^{-1}\).

Na prática, substituímos esses objetos por estimadores plug-in. Sob heterocedasticidade, usamos

\[\hat\Omega=\frac{1}{n}\sum_{i=1}^n X_iX_i^\top\hat{e}_i^2 \quad\text{e}\quad \hat{V}_{\beta,HC0} = \hat{Q}_{XX}^{-1}\hat\Omega\hat{Q}_{XX}^{-1}.\]

HC1, HC2 e HC3 têm o mesmo limite assintótico, mas diferem em amostras finitas, especialmente quando há alta alavancagem.

Aqui \(\hat{V}_{\beta,HC0}\) está na escala assintótica, isto é, estima a variância de

\[\sqrt{n}(\hat\beta-\beta).\]

Já a matriz usual retornada por pacotes, como vcovHC(), normalmente está na escala de

\[\operatorname{Var}(\hat\beta).\]

As duas se relacionam por

\[\widehat{\operatorname{Var}}(\hat\beta) = \frac{1}{n}\hat{V}_\beta.\]

Essa distinção é essencial para não errar a escala em estatísticas de Wald.

5.7 Estatística-\(t\) assintótica

Se \(\sqrt{n}(\hat\theta-\theta)\Rightarrow \mathcal{N}(0,V_\theta)\) e \(\hat{V}_\theta\to_p V_\theta\), então

\[T = \frac{\hat\theta-\theta}{s(\hat\theta)} \Rightarrow \mathcal{N}(0,1).\]

A diferença em relação à Aula 4 é importante: aqui a distribuição normal padrão é uma aproximação assintótica, não uma distribuição exata finita-amostral. Por isso, os intervalos e testes baseados em \(1.96\) são aproximados.

Fechamento da Aula 5

A Aula 5 mostra que a inferência do MQO não depende necessariamente da normalidade exata dos erros. Sob condições de momentos, amostragem i.i.d. e posto adequado de \(Q_{XX}\), temos consistência \(\hat\beta\to_p\beta\) e normalidade assintótica:

\[\sqrt{n}(\hat\beta-\beta)\Rightarrow \mathcal{N}(0,V_\beta), \qquad V_\beta=Q_{XX}^{-1}\Omega Q_{XX}^{-1}.\]

A matriz \(V_\beta\) depende de \(\Omega=\mathbb{E}[XX^\top e^2]\), permitindo heterocedasticidade. Por isso, erros-padrão robustos HC são fundamentais para inferência assintótica válida quando a variância dos erros não é constante. A aula também mostra como usar o Método Delta para funções de parâmetros e como construir estatísticas de Wald para hipóteses conjuntas.

Aula 6 — Testes de Hipóteses e Monte Carlo

A Aula 6 organiza a inferência econométrica em forma de testes de hipóteses. Nas aulas anteriores, construímos estimadores, erros-padrão e distribuições exatas ou assintóticas. Agora, usamos esses elementos para tomar decisões estatísticas.

A lógica de um teste não é provar que \(H_0\) é verdadeira ou falsa. A lógica é perguntar:

se \(H_0\) fosse verdadeira, o resultado observado seria plausível?

Se a estatística observada fica muito distante do que esperaríamos sob \(H_0\), rejeitamos \(H_0\). Se não fica distante o suficiente, não rejeitamos \(H_0\). O fio condutor da aula é:

\[\text{estimador} + \text{erro-padrão} + \text{distribuição nula} \Rightarrow \text{regra de decisão}.\]

A aula também mostra que testes podem ser avaliados por simulação de Monte Carlo, especialmente quando queremos estudar seu comportamento em amostras finitas.

6.0 Conceitos básicos de testes de hipóteses

O parâmetro de interesse pode ser um coeficiente ou uma função dos coeficientes: \(\theta=r(\beta)\). Exemplos:

\[\theta=\beta_1, \qquad \theta=\beta_1-\beta_2, \qquad \theta=\frac{\beta_1}{\beta_2}.\]

Uma hipótese pontual impõe que \(H_0:\theta=\theta_0\). Quando \(\theta=r(\beta)\), escrevemos \(H_0:r(\beta)=\theta_0\). A hipótese alternativa pode ser bilateral, \(H_1:\theta\neq\theta_0\), ou unilateral, \(H_1:\theta>\theta_0\) ou \(H_1:\theta<\theta_0\).

Um teste é uma regra de decisão que divide as possíveis amostras em duas regiões:

\[S_0=\{\text{amostras em que não rejeitamos }H_0\}, \qquad S_1=\{\text{amostras em que rejeitamos }H_0\}.\]

Na prática, resumimos a amostra por uma estatística \(T\) e rejeitamos quando ela cai na região crítica: rejeitar \(H_0\) se \(T>c\), onde \(c\) é o valor crítico.

6.1 Teste-\(t\): tamanho e poder

Para um parâmetro escalar \(\theta\), com estimador \(\hat\theta\) e erro-padrão \(s(\hat\theta)\), a estatística-\(t\) é

\[T(\theta_0) = \frac{\hat\theta-\theta_0}{s(\hat\theta)}.\]

Para o teste bilateral \(H_0:\theta=\theta_0\) contra \(H_1:\theta\neq\theta_0\), usamos \(|T(\theta_0)|\). Sob aproximação normal assintótica, \(T(\theta_0)\Rightarrow N(0,1)\). Por isso, para um teste bilateral a 5%, a regra usual é rejeitar \(H_0\) se \(|T|>1.96\), pois \(P(|Z|>1.96)=0.05\) com \(Z\sim N(0,1)\).

Nesta seção vamos simular dois conceitos importantes:

  • tamanho do teste: probabilidade de rejeitar \(H_0\) quando \(H_0\) é verdadeira;
  • poder do teste: probabilidade de rejeitar \(H_0\) quando a alternativa é verdadeira.
library(ggplot2)

set.seed(42)

gera_mqo <- function(n, beta_true, sigma2 = 1, dist = "normal") {
  X1 <- rnorm(n); X2 <- 0.5*X1 + rnorm(n)
  X  <- cbind(1, X1, X2)
  e  <- switch(dist,
    "normal" = rnorm(n, sd = sqrt(sigma2)),
    "chi2"   = (rchisq(n, 2) - 2) / sqrt(2),
    "hetero" = (1 + abs(X1)) * rnorm(n, sd = sqrt(sigma2))
  )
  Y       <- X %*% beta_true + e
  XtX_inv <- solve(t(X) %*% X)
  b_hat   <- XtX_inv %*% t(X) %*% Y
  e_hat   <- Y - X %*% b_hat
  s2      <- sum(e_hat^2) / (n - ncol(X))
  se_hom  <- sqrt(s2 * XtX_inv[2, 2])
  n_ <- n; k_ <- ncol(X)
  Om    <- t(X) %*% diag(as.numeric(e_hat)^2) %*% X
  V_hc1 <- (n_/(n_-k_)) * XtX_inv %*% Om %*% XtX_inv
  se_rob <- sqrt(V_hc1[2, 2])
  list(b1 = b_hat[2], se_hom = se_hom, se_rob = se_rob)
}

6.1.1 Testes bilaterais e unilaterais

No teste bilateral \(H_0:\theta=\theta_0\) contra \(H_1:\theta\neq\theta_0\), rejeitamos para valores grandes de \(|T|\). A regra assintótica a 5% é \(|T|>1.96\).

No teste unilateral à direita \(H_0:\theta=\theta_0\) contra \(H_1:\theta>\theta_0\), rejeitamos para valores grandes e positivos de \(T\). A regra a 5% é \(T>1.645\).

No teste unilateral à esquerda \(H_0:\theta=\theta_0\) contra \(H_1:\theta<\theta_0\), rejeitamos para valores muito negativos: \(T<-1.645\).

A escolha entre teste unilateral e bilateral deve ser feita antes de olhar os dados. Caso contrário, o pesquisador pode escolher a alternativa que favorece o resultado observado.

6.1.2 \(p\)-valores

O \(p\)-valor mede quão extremo foi o resultado observado sob \(H_0\). Para testes que rejeitam para valores grandes de \(T\), com distribuição nula assintótica \(G\), o p-valor é \(p=1-G(T)\).

No teste-\(t\) bilateral, usando a normal padrão:

\[p=2(1-\Phi(|t|)).\]

Se usamos a distribuição \(t\) de Student com \(\nu\) graus de liberdade: \(p=2(1-F_{t_\nu}(|t|))\).

A regra via \(p\)-valor é equivalente à regra por valor crítico: \(p<\alpha \Longleftrightarrow\) rejeitar \(H_0\) ao nível \(\alpha\). Importante: um \(p\)-valor pequeno não mede o tamanho do efeito, nem sua relevância econômica. Ele mede evidência estatística contra \(H_0\), dada a escala do erro-padrão.

t_ex <- c(0.5, 1.0, 1.96, 2.5, 3.0)

data.frame(
  t                  = t_ex,
  p_bilateral_normal = 2 * (1 - pnorm(abs(t_ex)))
)
     t p_bilateral_normal
1 0.50        0.617075077
2 1.00        0.317310508
3 1.96        0.049995790
4 2.50        0.012419331
5 3.00        0.002699796

6.2 Tamanho do teste: distorção sob \(H_0\)

O tamanho do teste é \(P(\text{rejeitar }H_0\mid H_0\text{ verdadeira})\). Se o teste é nominalmente de 5%, esperamos que, sob \(H_0\), ele rejeite aproximadamente 5% das vezes.

Nesta simulação, impomos \(\beta_1=0\), então \(H_0:\beta_1=0\) é verdadeira. Geramos erros heterocedásticos e comparamos o teste-\(t\) homocedástico convencional com o teste-\(t\) robusto à heterocedasticidade.

B         <- 3000
ns        <- c(50, 100, 300, 500)
beta_nulo <- c(1, 0, -1)

res_tam <- lapply(ns, function(n) {
  rej_hom <- rej_rob <- numeric(B)
  for (b in 1:B) {
    r          <- gera_mqo(n, beta_nulo, dist = "hetero")
    t_hom      <- abs(r$b1 / r$se_hom)
    t_rob      <- abs(r$b1 / r$se_rob)
    rej_hom[b] <- t_hom > qt(0.975, df = n - 3)
    rej_rob[b] <- t_rob > 1.96
  }
  data.frame(n = n,
             Homocedástico = mean(rej_hom),
             Robusto       = mean(rej_rob))
})

res_tam_df <- do.call(rbind, res_tam)

cat("=== Taxa de rejeição sob H₀ (deveria ser 5%) ===\n")
=== Taxa de rejeição sob H₀ (deveria ser 5%) ===
cat("Erros heterocedásticos: e_i = (1 + |X1_i|) eps_i\n\n")
Erros heterocedásticos: e_i = (1 + |X1_i|) eps_i
cat(sprintf("%-6s  %14s  %8s\n", "n", "Homocedástico", "Robusto"))
n       Homocedástico   Robusto
for (i in 1:nrow(res_tam_df)) {
  cat(sprintf("%-6d  %14.4f  %8.4f\n",
              res_tam_df$n[i],
              res_tam_df$Homocedástico[i],
              res_tam_df$Robusto[i]))
}
50              0.1283    0.0780
100             0.1353    0.0633
300             0.1480    0.0590
500             0.1487    0.0530
tidyr::pivot_longer(res_tam_df, -n,
                    names_to  = "Teste",
                    values_to = "Taxa") |>
  ggplot(aes(x = n, y = Taxa, color = Teste)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 3) +
  geom_hline(yintercept = 0.05, linetype = "dashed", color = "gray40") +
  scale_color_manual(values = c("Homocedástico" = "red",
                                "Robusto"       = "steelblue")) +
  labs(title = "Distorção de tamanho sob heterocedasticidade",
       subtitle = "Linha tracejada = nível nominal 5%",
       x = "n", y = "Taxa de rejeição") +
  theme_minimal()

Taxa de rejeição sob H₀ — distorção de tamanho

O resultado mostra que o teste homocedástico rejeita muito mais do que 5% sob heterocedasticidade — comete erro tipo I em excesso. O teste robusto fica mais próximo do tamanho nominal, especialmente conforme \(n\) aumenta. Essa é exatamente a motivação prática para usar erros-padrão robustos.

6.3 Poder do teste: detectar desvios de \(H_0\)

O poder é \(\pi(\theta)=P(\text{rejeitar }H_0\mid H_1\text{ verdadeira})\). Variamos o valor verdadeiro de \(\beta_1\): quando \(\beta_1=0\) estamos sob \(H_0\); quando \(\beta_1\neq0\), estamos sob alternativas.

n       <- 200
B       <- 3000
desvios <- seq(-1, 1, by = 0.1)

poder_hom <- poder_rob <- numeric(length(desvios))

for (j in seq_along(desvios)) {
  beta_alt <- c(1, desvios[j], -1)
  rh <- rr <- numeric(B)
  for (b in 1:B) {
    r     <- gera_mqo(n, beta_alt, dist = "normal")
    rh[b] <- abs(r$b1 / r$se_hom) > qt(0.975, df = n - 3)
    rr[b] <- abs(r$b1 / r$se_rob) > 1.96
  }
  poder_hom[j] <- mean(rh)
  poder_rob[j] <- mean(rr)
}

df_poder <- data.frame(
  delta         = desvios,
  Homocedástico = poder_hom,
  Robusto       = poder_rob
)

tidyr::pivot_longer(df_poder, -delta,
                    names_to  = "Teste",
                    values_to = "Poder") |>
  ggplot(aes(x = delta, y = Poder, color = Teste)) +
  geom_line(linewidth = 1.2) +
  geom_hline(yintercept = 0.05, linetype = "dashed", color = "gray50") +
  geom_vline(xintercept = 0, linetype = "dotted") +
  scale_color_manual(values = c("Homocedástico" = "red",
                                "Robusto"       = "steelblue")) +
  labs(title = "Curva de poder do teste-t (n = 200)",
       subtitle = "Em delta = 0: taxa deve ser 5% (tamanho)",
       x = "β₁ verdadeiro", y = "P(rejeitar H₀)") +
  theme_minimal()

Curva de poder: probabilidade de rejeitar H₀ quando H₁ é verdadeira

A curva de poder é baixa perto de \(\beta_1=0\), porque ali a hipótese nula é verdadeira ou quase verdadeira. À medida que \(\beta_1\) se afasta de zero, o teste passa a rejeitar com maior probabilidade.

6.4 Teste de Wald — construção manual

O teste de Wald mede a distância entre a estimativa irrestrita e o valor imposto pela hipótese nula. Para uma hipótese vetorial \(H_0:\theta=\theta_0\) com \(\theta=r(\beta)\in\mathbb{R}^q\), a estatística é

\[W = (\hat\theta-\theta_0)^\top \widehat{\operatorname{Var}}(\hat\theta)^{-1} (\hat\theta-\theta_0).\]

Sob \(H_0\), \(W\Rightarrow\chi_q^2\). No caso de restrições lineares \(\theta=R\beta\), temos \(\hat\theta=R\hat\beta\) e \(\widehat{\operatorname{Var}}(\hat\theta)=R\widehat{\operatorname{Var}}(\hat\beta)R^\top\). Quando \(q=1\), o Wald é simplesmente o quadrado da estatística-\(t\): \(W=T^2\).

set.seed(123)
n  <- 300
X1 <- rnorm(n); X2 <- 0.5*X1 + rnorm(n)
X  <- cbind(1, X1, X2)
beta_true <- c(1, 2, -1)
Y  <- X %*% beta_true + rnorm(n)

XtX_inv   <- solve(t(X) %*% X)
b_hat     <- XtX_inv %*% t(X) %*% Y
e_hat     <- Y - X %*% b_hat
s2        <- sum(e_hat^2) / (n - 3)

R         <- matrix(c(0,1,0, 0,0,1), nrow = 2, byrow = TRUE)
theta0    <- c(2, -1)
theta_hat <- R %*% b_hat
V_hat     <- s2 * XtX_inv
V_theta   <- R %*% V_hat %*% t(R)

W0      <- t(theta_hat - theta0) %*% solve(V_theta) %*% (theta_hat - theta0)
pval_W0 <- pchisq(as.numeric(W0), df = 2, lower.tail = FALSE)

F_stat <- as.numeric(W0) / 2
pval_F <- pf(F_stat, df1 = 2, df2 = n - 3, lower.tail = FALSE)

cat("=== Teste de Wald (H₀ verdadeira) ===\n\n")
=== Teste de Wald (H₀ verdadeira) ===
cat("W (Wald):     ", round(W0, 4), "\n")
W (Wald):      1.1506 
cat("p-valor (χ²): ", round(pval_W0, 4), "\n\n")
p-valor (χ²):  0.5625 
cat("F = W/q:      ", round(F_stat, 4), "\n")
F = W/q:       0.5753 
cat("p-valor (F):  ", round(pval_F, 4), "\n")
p-valor (F):   0.5632 
cat("\n→ Não rejeitamos H₀ — correto, pois H₀ é verdadeira.\n")

→ Não rejeitamos H₀ — correto, pois H₀ é verdadeira.
cat("\nVerificação: W = q × F? ", round(W0, 6), "=", round(2 * F_stat, 6), "\n")

Verificação: W = q × F?  1.150641 = 1.150641 

6.4.1 Teste-\(F\): comparação entre modelo restrito e irrestrito

O teste-\(F\) é especialmente útil para hipóteses lineares conjuntas. A estatística é

\[F = \frac{(SSE_R-SSE_U)/q}{SSE_U/(n-k)}.\]

O numerador mede quanto o ajuste piora ao impor as restrições. O denominador mede o ruído residual médio do modelo irrestrito. Para hipóteses lineares sob homocedasticidade, \(F=W^0/q\). Em amostra finita normal, usa-se \(F_{q,n-k}\). Assintoticamente, \(F\Rightarrow\chi_q^2/q\).

k     <- 3
mod_u <- lm(as.numeric(Y) ~ X1 + X2)
SSE_u <- sum(resid(mod_u)^2)

Y_rest <- as.numeric(Y) - 2 * X1 + 1 * X2
mod_r  <- lm(Y_rest ~ 1)
SSE_r  <- sum(resid(mod_r)^2)

q          <- 2
F_sse      <- ((SSE_r - SSE_u) / q) / (SSE_u / (n - k))
pval_F_sse <- pf(F_sse, df1 = q, df2 = n - k, lower.tail = FALSE)

cat("=== Teste F via SSE restrito e irrestrito ===\n\n")
=== Teste F via SSE restrito e irrestrito ===
cat("SSE restrito:   ", round(SSE_r, 4), "\n")
SSE restrito:    319.3385 
cat("SSE irrestrito: ", round(SSE_u, 4), "\n")
SSE irrestrito:  318.1061 
cat("F via SSE:      ", round(F_sse, 4), "\n")
F via SSE:       0.5753 
cat("F via Wald/q:   ", round(F_stat, 4), "\n")
F via Wald/q:    0.5753 
cat("p-valor:        ", round(pval_F_sse, 4), "\n")
p-valor:         0.5632 

6.5 Teste de Hausman

O teste de Hausman compara dois estimadores: (1) um eficiente sob \(H_0\) mas inconsistente sob \(H_1\); (2) outro consistente sob \(H_0\) e \(H_1\), mas menos eficiente sob \(H_0\). A lógica é: se \(H_0\) é verdadeira, os dois estimadores devem ser parecidos. Se a diferença é grande demais, rejeitamos \(H_0\).

Exemplo clássico em painel: sob \(H_0\), efeitos aleatórios é consistente e eficiente; efeitos fixos também é consistente, mas menos eficiente; sob \(H_1\), efeitos aleatórios é inconsistente, enquanto efeitos fixos continua consistente. Então rejeitar \(H_0\) sugere preferir efeitos fixos.

Outro exemplo é o teste de endogeneidade Durbin-Wu-Hausman: sob exogeneidade, MQO é consistente e eficiente; sob endogeneidade, MQO é inconsistente; IV pode continuar consistente se os instrumentos forem válidos. Se MQO e IV diferem muito, há evidência contra exogeneidade.

6.6 Teste de score

O teste de score é baseado na inclinação da log-verossimilhança no ponto restrito. A ideia é: se \(H_0\) é verdadeira, o estimador restrito deve estar perto do máximo irrestrito; portanto, o score avaliado no estimador restrito deve ser pequeno. Se \(H_0\) é falsa, o ponto restrito fica longe do máximo, e o score será grande.

A forma geral é

\[S = \left(\frac{\partial \ell_n(\tilde\beta,\tilde\sigma^2)}{\partial \beta}\right)^\top \left(-\frac{\partial^2\ell_n(\tilde\beta,\tilde\sigma^2)}{\partial\beta\partial\beta^\top}\right)^{-1} \left(\frac{\partial \ell_n(\tilde\beta,\tilde\sigma^2)}{\partial \beta}\right).\]

Comparação intuitiva entre os testes: Wald olha a distância entre o estimador irrestrito e a hipótese; Score olha a inclinação no ponto restrito; LR compara valores da log-verossimilhança; \(F\) compara perda de ajuste em soma de quadrados.

6.7 Sensibilidade do Wald a reparametrizações não lineares

A mesma hipótese escrita de formas diferentes pode dar estatísticas de Wald distintas em amostras finitas. Por exemplo, \(H_0:\beta_1/\beta_2=1\) é equivalente a \(H_0:\beta_1-\beta_2=0\) quando \(\beta_2\neq0\). Em população, descrevem o mesmo conjunto nulo. Mas em amostras finitas o Wald pode produzir estatísticas diferentes.

set.seed(42)
n  <- 100
B  <- 3000
beta_true_nl <- c(1, 1, 1)

W_razao <- W_linear <- numeric(B)

for (b in 1:B) {
  X1b <- rnorm(n); X2b <- rnorm(n)
  Xb  <- cbind(1, X1b, X2b)
  Yb  <- Xb %*% beta_true_nl + rnorm(n)

  XtXb_inv <- solve(t(Xb) %*% Xb)
  b_h      <- XtXb_inv %*% t(Xb) %*% Yb
  s2b      <- sum((Yb - Xb %*% b_h)^2) / (n - 3)
  Vb       <- s2b * XtXb_inv

  r_lin       <- matrix(c(0, 1, -1), nrow = 1)
  W_lin       <- t(r_lin %*% b_h) %*% solve(r_lin %*% Vb %*% t(r_lin)) %*%
                 (r_lin %*% b_h)
  W_linear[b] <- as.numeric(W_lin)

  theta_r   <- b_h[2] / b_h[3] - 1
  grad_r    <- c(0, 1/b_h[3], -b_h[2]/b_h[3]^2)
  V_theta_r <- t(grad_r) %*% Vb %*% grad_r
  W_razao[b] <- theta_r^2 / as.numeric(V_theta_r)
}

df_wald <- rbind(
  data.frame(W = W_linear, forma = "Linear: β₁ - β₂ = 0"),
  data.frame(W = W_razao,  forma = "Razão: β₁/β₂ = 1")
)

x_chi1 <- seq(0, 15, length.out = 200)

ggplot(df_wald, aes(x = W, fill = forma)) +
  geom_histogram(aes(y = after_stat(density)),
                 bins = 60, alpha = 0.5, position = "identity") +
  geom_line(data = data.frame(x = x_chi1, y = dchisq(x_chi1, 1)),
            aes(x = x, y = y), inherit.aes = FALSE,
            color = "black", linewidth = 1.2, linetype = "dashed") +
  coord_cartesian(xlim = c(0, 12)) +
  scale_fill_manual(values = c("steelblue", "coral")) +
  labs(title = "Sensibilidade do Wald: mesma H₀, duas formas algébricas",
       subtitle = "Tracejado = χ²(1) | n = 100",
       x = "W", y = "Densidade", fill = "") +
  theme_minimal()

Wald em duas parametrizações equivalentes da mesma H₀
cat("Taxa de rejeição a 5% (χ²(1) > 3.84):\n")
Taxa de rejeição a 5% (χ²(1) > 3.84):
cat("Forma linear: ", round(mean(W_linear > qchisq(0.95, 1)), 4), "\n")
Forma linear:  0.0507 
cat("Forma razão:  ", round(mean(W_razao  > qchisq(0.95, 1)), 4), "\n")
Forma razão:   0.047 
cat("\n→ Mesma H₀, mas distorções diferentes em n=100.\n")

→ Mesma H₀, mas distorções diferentes em n=100.
cat("  A forma linear é mais estável (evita divisão por β̂ próximo de zero).\n")
  A forma linear é mais estável (evita divisão por β̂ próximo de zero).

A forma linear costuma ser mais estável, pois evita divisão por \(\hat\beta_2\). Essa é uma das mensagens centrais da Aula 6: para hipóteses não lineares, o teste de Wald pode ser sensível à parametrização.

6.8 Simulação de Monte Carlo

A simulação de Monte Carlo serve para estudar a distribuição finita-amostral de uma estatística quando essa distribuição é desconhecida. O pesquisador escolhe a distribuição dos dados \(F\), o tamanho amostral \(n\), o valor verdadeiro do parâmetro \(\theta\) e o número de repetições \(B\). Em cada réplica \(b\): gera uma amostra artificial de tamanho \(n\), calcula a estatística de interesse \(T_b\) e guarda o resultado.

Após \(B\) repetições, a coleção \(T_1,\ldots,T_B\) aproxima numericamente a distribuição finita-amostral de \(T\). Monte Carlo é útil porque a teoria assintótica pode dizer que \(T\Rightarrow N(0,1)\), mas em amostras pequenas ou médias a distribuição real de \(T\) pode ser bem diferente.

6.8.1 Características estimadas por Monte Carlo

Se queremos estudar o erro de um estimador, definimos em cada réplica \(T_b=\hat\theta_b-\theta\). O viés simulado é

\[\widehat{bias} = \frac{1}{B}\sum_{b=1}^B(\hat\theta_b-\theta).\]

O erro quadrático médio simulado é \(\widehat{MSE} = \frac{1}{B}\sum_{b=1}^B(\hat\theta_b-\theta)^2\), e a variância simulada é \(\widehat{Var} = \widehat{MSE} - \widehat{bias}^2\).

Para testes, a taxa de rejeição simulada é

\[\hat{p} = \frac{1}{B}\sum_{b=1}^B \mathbf{1}\{|T_b|>1.96\}.\]

Se a simulação é feita sob \(H_0\), \(\hat{p}\) estima o erro tipo I finita-amostral. Se é feita sob \(H_1\), \(\hat{p}\) estima o poder.

set.seed(123)
n         <- 100
B         <- 2000
beta_true <- c(1, 2, -1)

beta1_hat <- numeric(B)
for (b in 1:B) {
  r             <- gera_mqo(n, beta_true, dist = "chi2")
  beta1_hat[b]  <- r$b1
}

erro   <- beta1_hat - beta_true[2]
bias_mc <- mean(erro)
mse_mc  <- mean(erro^2)
var_mc  <- mse_mc - bias_mc^2

cat("=== Monte Carlo: viés, MSE e variância de beta1_hat ===\n\n")
=== Monte Carlo: viés, MSE e variância de beta1_hat ===
cat("Viés simulado:      ", round(bias_mc, 5), "\n")
Viés simulado:       -0.00381 
cat("MSE simulado:       ", round(mse_mc, 5), "\n")
MSE simulado:        0.02711 
cat("Variância simulada: ", round(var_mc, 5), "\n")
Variância simulada:  0.02709 
cat("DP simulado:        ", round(sqrt(var_mc), 5), "\n")
DP simulado:         0.16459 

6.8.2 Escolha do número de repetições \(B\)

Monte Carlo também tem erro amostral. Quando calculamos uma taxa simulada de rejeição \(\hat{p}=\frac{1}{B}\sum_{b=1}^B \mathbf{1}\{\text{rejeitou na réplica }b\}\), seu erro-padrão aproximado é

\[SE(\hat{p}) \approx \sqrt{\frac{\hat{p}(1-\hat{p})}{B}}.\]

Logo, maior \(B\) reduz o erro de simulação mas aumenta custo computacional. Por isso, resultados de Monte Carlo devem ser reportados com cuidado: uma diferença pequena entre duas taxas simuladas pode ser apenas ruído de simulação.

p_hat <- 0.05
Bs    <- c(100, 500, 1000, 5000, 10000)

data.frame(
  B     = Bs,
  SE_MC = sqrt(p_hat * (1 - p_hat) / Bs)
)
      B       SE_MC
1   100 0.021794495
2   500 0.009746794
3  1000 0.006892024
4  5000 0.003082207
5 10000 0.002179449

6.8.3 Replicação de resultados de Monte Carlo

Como resultados de Monte Carlo são aleatórios, duas simulações com o mesmo desenho podem gerar resultados diferentes, especialmente quando \(B\) é pequeno. Por exemplo, se um artigo reporta, com \(B=100\), \(\hat{p}_1=0.07\), e uma replicação encontra \(\hat{p}_2=0.03\), a diferença é \(0.04\). Isso parece grande, mas com \(B=100\) o erro de simulação pode ser considerável. Se \(p\approx0.05\),

\[SE(\hat{p}) \approx \sqrt{\frac{0.05\cdot 0.95}{100}} \approx 0.022.\]

Então uma diferença de \(0.04\) não prova automaticamente falha de replicação. É preciso comparar a diferença com o erro-padrão de Monte Carlo.

Fechamento da Aula 6

A Aula 6 transforma a inferência assintótica em regras práticas de decisão. A partir de estimadores, erros-padrão e distribuições nulas, construímos testes-\(t\), testes de Wald, testes-\(F\), Hausman e score.

A estatística-\(t\) é usada para hipóteses escalares. O Wald generaliza essa lógica para hipóteses vetoriais \(H_0:\theta=\theta_0\in\mathbb{R}^q\), com \(W\Rightarrow\chi_q^2\). O teste-\(F\) compara modelos restritos e irrestritos em hipóteses lineares sob homocedasticidade. O Hausman compara dois estimadores com propriedades diferentes sob \(H_0\) e \(H_1\). O score avalia a inclinação da log-verossimilhança no ponto restrito.

A aula também mostra que simulações de Monte Carlo são uma ferramenta fundamental para estudar o comportamento finito-amostral de estimadores, testes e intervalos. Elas permitem avaliar tamanho, poder, viés, MSE, quantis e sensibilidade a hipóteses como heterocedasticidade ou não linearidade.

Aula 7 — Inferência por Reamostragem: Jackknife e Bootstrap

A Aula 7 apresenta métodos de inferência baseados em reamostragem. A ideia central é usar a própria amostra observada para aproximar a distribuição amostral de um estimador.

Se a amostra observada é \(Z_1,\ldots,Z_n\), a distribuição empírica \(\hat{F}_n\) atribui massa \(1/n\) a cada observação. Como a distribuição populacional verdadeira \(F\) é desconhecida, a reamostragem usa \(\hat{F}_n\) como aproximação de \(F\).

O objetivo é aproximar a variabilidade de \(\hat\theta\) recalculando o estimador em amostras modificadas. Há duas estratégias principais:

  • jackknife: remove uma observação, ou cluster, por vez;
  • bootstrap: sorteia novas amostras com reposição da amostra original.

A mensagem principal é:

\[\text{amostra observada} \Rightarrow \text{reamostras} \Rightarrow \text{estimadores reamostrados} \Rightarrow \text{erro-padrão / distribuição aproximada}.\]

7.1 Setup

library(ggplot2)

set.seed(42)
n <- 100
X1 <- rnorm(n); X2 <- 0.5*X1 + rnorm(n)
X  <- cbind(1, X1, X2)
beta_true <- c(1, 2, -1)
Y  <- X %*% beta_true + rnorm(n)

XtX_inv <- solve(t(X) %*% X)
b_hat   <- XtX_inv %*% t(X) %*% Y
e_hat   <- as.numeric(Y - X %*% b_hat)
h_ii    <- diag(X %*% XtX_inv %*% t(X))

cat("Estimativas MQO:\n")
Estimativas MQO:
cat(sprintf("β₀=%.4f  β₁=%.4f  β₂=%.4f\n",
            b_hat[1], b_hat[2], b_hat[3]))
β₀=1.0018  β₁=1.8136  β₂=-0.9147

7.2 Jackknife: ideia geral

O jackknife calcula o estimador várias vezes, sempre removendo uma observação da amostra. Para cada \(i\), define-se

\[\hat\theta_{(-i)} = \hat\theta(Z_1,\ldots,Z_{i-1},Z_{i+1},\ldots,Z_n).\]

A ideia é simples: se retirar uma observação muda muito o estimador, essa observação é influente e o estimador é mais instável. Se retirar qualquer observação quase não muda o resultado, o estimador é mais estável.

O estimador jackknife de variância é

\[\hat{V}^{jack}_{\hat\theta} = \frac{n-1}{n} \sum_{i=1}^n (\hat\theta_{(-i)}-\bar\theta_{jack})(\hat\theta_{(-i)}-\bar\theta_{jack})^\top,\]

onde \(\bar\theta_{jack} = \frac{1}{n}\sum_{i=1}^n\hat\theta_{(-i)}\). O fator \((n-1)/n\) aparece porque os estimadores leave-one-out são calculados com amostras muito parecidas entre si; eles não são \(n\) estimadores independentes.

e_loo <- e_hat / (1 - h_ii)

beta_loo <- matrix(NA, nrow = n, ncol = 3)
for (i in 1:n) {
  beta_loo[i, ] <- b_hat - XtX_inv %*% X[i, ] * e_loo[i]
}

beta_bar <- colMeans(beta_loo)

V_jack <- ((n-1)/n) * t(beta_loo - matrix(beta_bar, n, 3, byrow = TRUE)) %*%
                         (beta_loo - matrix(beta_bar, n, 3, byrow = TRUE))

se_jack <- sqrt(diag(V_jack))

w_HC3     <- e_hat^2 / (1 - h_ii)^2
Omega_HC3 <- t(X) %*% diag(w_HC3) %*% X
V_HC3     <- XtX_inv %*% Omega_HC3 %*% XtX_inv
se_HC3    <- sqrt(diag(V_HC3))

cat("=== Jackknife vs HC3 ===\n\n")
=== Jackknife vs HC3 ===
cat(sprintf("%-12s  %8s  %8s  %8s\n",
            "Parâmetro", "Jackknife", "HC3", "Diferença"))
Parâmetro    Jackknife       HC3  Diferença
nomes <- c("β₀", "β₁", "β₂")
for (j in 1:3) {
  cat(sprintf("%-12s  %8.5f  %8.5f  %8.2e\n",
              nomes[j], se_jack[j], se_HC3[j], se_jack[j]-se_HC3[j]))
}
β₀          0.10286   0.10338  -5.18e-04
β₁          0.12556   0.12620  -6.33e-04
β₂          0.11091   0.11147  -5.62e-04
cat("\n→ Jackknife ≈ HC3 — confirma a equivalência do Teorema da Aula 7.\n")

→ Jackknife ≈ HC3 — confirma a equivalência do Teorema da Aula 7.

O resultado mostra que o jackknife para MQO fica numericamente muito próximo do HC3. Isso acontece porque ambos corrigem a influência de observações com alta alavancagem por meio do termo \((1-h_{ii})^{-2}\).

A intuição é que \(\tilde{e}_i = \hat{e}_i/(1-h_{ii})\) é o erro de previsão leave-one-out. Quando \(h_{ii}\) é alto, o resíduo usual \(\hat{e}_i\) pode subestimar a verdadeira influência da observação. O HC3 e o jackknife corrigem justamente esse problema.

7.2.1 Delete-cluster jackknife

Quando os dados têm clusters, remover uma observação individual pode ser inadequado. Se alunos estão agrupados em escolas, empresas em municípios ou trabalhadores em firmas, observações dentro do mesmo cluster podem compartilhar choques comuns.

Nesse caso, a unidade independente não é necessariamente a observação individual, mas o cluster. Por isso, o jackknife apropriado remove um cluster inteiro por vez.

Se há \(G\) clusters, o estimador delete-cluster é \(\hat\beta_{(-g)}\), obtido estimando o modelo sem o cluster \(g\). A matriz de variância jackknife cluster-robusta é

\[\hat{V}^{jack}_{\hat\beta} = \frac{G-1}{G} \sum_{g=1}^G (\hat\beta_{(-g)}-\bar\beta)(\hat\beta_{(-g)}-\bar\beta)^\top,\]

com \(\bar\beta=\frac{1}{G}\sum_{g=1}^G\hat\beta_{(-g)}\). A validade desse procedimento depende de \(G\) ser suficientemente grande, não apenas de \(n\). Muitos indivíduos em poucos clusters ainda podem gerar inferência frágil.

set.seed(123)
G    <- 40
ng   <- 8
n_cl <- G * ng

cluster <- rep(1:G, each = ng)
X1_cl   <- rnorm(n_cl)
X2_cl   <- rnorm(n_cl)

a_g  <- rnorm(G, sd = 1)
u_cl <- a_g[cluster] + rnorm(n_cl, sd = 1)
Y_cl <- 1 + 2 * X1_cl - 1 * X2_cl + u_cl

dados_cl <- data.frame(Y_cl, X1_cl, X2_cl, cluster)
mod_cl   <- lm(Y_cl ~ X1_cl + X2_cl, data = dados_cl)
b_full   <- coef(mod_cl)

beta_minus_g <- matrix(NA, nrow = G, ncol = length(b_full))
for (g in 1:G) {
  dados_g          <- subset(dados_cl, cluster != g)
  beta_minus_g[g,] <- coef(lm(Y_cl ~ X1_cl + X2_cl, data = dados_g))
}

beta_bar_g <- colMeans(beta_minus_g)

V_jack_cl <- ((G - 1) / G) *
  t(beta_minus_g - matrix(beta_bar_g, G, length(b_full), byrow = TRUE)) %*%
  (beta_minus_g - matrix(beta_bar_g, G, length(b_full), byrow = TRUE))

se_jack_cl <- sqrt(diag(V_jack_cl))

cat("=== Delete-cluster jackknife ===\n\n")
=== Delete-cluster jackknife ===
cat(sprintf("%-12s %10s\n", "Parâmetro", "EP cluster-jack"))
Parâmetro   EP cluster-jack
for (j in 1:length(b_full)) {
  cat(sprintf("%-12s %10.5f\n", names(b_full)[j], se_jack_cl[j]))
}
(Intercept)     0.15503
X1_cl           0.07765
X2_cl           0.07372

7.3 Bootstrap não paramétrico

O bootstrap não paramétrico sorteia amostras de tamanho \(n\), com reposição, da amostra original. Em regressão, cada unidade reamostrada deve ser o par completo \(W_i=(Y_i,X_i)\).

A amostra bootstrap é \(W_1^*,\ldots,W_n^*\sim i.i.d.\ \hat{F}_n\). Em cada amostra bootstrap, recalculamos o estimador \(\hat\theta_b^*=\hat\theta(W_1^*,\ldots,W_n^*)\). Depois de \(B\) repetições, usamos a variabilidade de \(\hat\theta_1^*,\ldots,\hat\theta_B^*\) para estimar erro-padrão, quantis e intervalos.

O sorteio precisa ser com reposição. Se sorteássemos sem reposição uma amostra de tamanho \(n\), apenas embaralharíamos os dados originais, e o estimador não mudaria.

B <- 3000
beta1_boot <- numeric(B)

for (b in 1:B) {
  idx           <- sample(n, n, replace = TRUE)
  X_b           <- X[idx, ]
  Y_b           <- Y[idx]
  b_b           <- solve(t(X_b) %*% X_b) %*% t(X_b) %*% Y_b
  beta1_boot[b] <- b_b[2]
}

se_boot <- sd(beta1_boot)

s2     <- sum(e_hat^2) / (n - 3)
se_hom <- sqrt(s2 * XtX_inv[2, 2])
se_HC1 <- sqrt((n/(n-3)) * (XtX_inv %*%
           (t(X) %*% diag(e_hat^2) %*% X) %*% XtX_inv)[2, 2])

cat("=== Comparação de erros-padrão para β̂₁ ===\n\n")
=== Comparação de erros-padrão para β̂₁ ===
cat(sprintf("%-12s  %8.5f\n", "Homocedást.", se_hom))
Homocedást.   0.11446
cat(sprintf("%-12s  %8.5f\n", "HC1",         se_HC1))
HC1            0.12022
cat(sprintf("%-12s  %8.5f\n", "HC3",         se_HC3[2]))
HC3            0.12620
cat(sprintf("%-12s  %8.5f\n", "Jackknife",   se_jack[2]))
Jackknife      0.12556
cat(sprintf("%-12s  %8.5f\n", "Bootstrap",   se_boot))
Bootstrap      0.12458
x_grid <- seq(min(beta1_boot), max(beta1_boot), length.out = 200)
ggplot(data.frame(b1 = beta1_boot), aes(x = b1)) +
  geom_histogram(aes(y = after_stat(density)),
                 bins = 60, fill = "steelblue", alpha = 0.6) +
  geom_line(data = data.frame(x = x_grid,
                               y = dnorm(x_grid, mean = b_hat[2], sd = se_boot)),
            aes(x = x, y = y), color = "red", linewidth = 1.2) +
  geom_vline(xintercept = b_hat[2], color = "black", linetype = "dashed") +
  labs(title = "Distribuição bootstrap de β̂₁ (B = 3000)",
       subtitle = "Vermelho = Normal com EP bootstrap | Tracejado = β̂₁ observado",
       x = "β̂₁*", y = "Densidade") +
  theme_minimal()

Distribuição bootstrap de β̂₁ vs Normal assintótica

A distribuição bootstrap de \(\hat\beta_1^*\) aproxima a distribuição amostral de \(\hat\beta_1\) usando a amostra observada como se fosse a população. No universo bootstrap, a “verdade” é \(\hat{F}_n\), e o análogo do parâmetro verdadeiro é \(\hat\beta_1\). Por isso, a distribuição relevante é frequentemente \(\hat\beta_1^*-\hat\beta_1\).

7.3.1 Por que cerca de 63,2% das observações aparecem?

Em uma amostra bootstrap de tamanho \(n\), a probabilidade de uma observação específica não ser sorteada em uma retirada é \(1-\frac{1}{n}\). A probabilidade de ela não aparecer em nenhuma das \(n\) retiradas é \(\left(1-\frac{1}{n}\right)^n\). Logo, a probabilidade de aparecer pelo menos uma vez é

\[1-\left(1-\frac{1}{n}\right)^n.\]

Quando \(n\) é grande,

\[1-\left(1-\frac{1}{n}\right)^n \approx 1-e^{-1} \approx 0.632.\]

Portanto, uma amostra bootstrap típica contém cerca de 63,2% das observações originais pelo menos uma vez, e deixa o restante de fora.

prob_aparece <- 1 - (1 - 1/n)^n

cat("Probabilidade aproximada de uma observação aparecer no bootstrap:\n")
Probabilidade aproximada de uma observação aparecer no bootstrap:
cat(round(prob_aparece, 4), "\n")
0.634 
cat("Limite 1 - exp(-1):", round(1 - exp(-1), 4), "\n")
Limite 1 - exp(-1): 0.6321 

7.3.2 Exemplo: salário esperado em nível a partir de regressão em log

Considere o modelo \(\log(sal_i)=\beta_1 educ_i+\beta_2+e_i\). O interesse é \(\mu=\mathbb{E}[sal\mid educ=16]\).

Como \(sal=\exp(16\beta_1+\beta_2+e)\) e, se \(e\sim N(0,\sigma^2)\), temos \(\mathbb{E}[\exp(e)]=\exp(\sigma^2/2)\), então

\[\mu=\exp(16\beta_1+\beta_2+\sigma^2/2).\]

O estimador plug-in é \(\hat\mu=\exp(16\hat\beta_1+\hat\beta_2+\hat\sigma^2/2)\). Esse parâmetro é uma função não linear de \((\hat\beta_1,\hat\beta_2,\hat\sigma^2)\). Poderíamos usar método delta, mas o bootstrap é uma alternativa prática: reamostramos os dados, reestimamos o modelo e recalculamos \(\hat\mu^*\).

7.4 Inferência para parâmetro não linear: ponto de máximo

O exemplo central da Aula 7 é a regressão quadrática em experiência:

\[\log(sal_i) = \beta_0 + \beta_1 educ_i + \beta_2 exper_i + \beta_3 exper_i^2 + u_i.\]

O ponto de máximo da parábola é \(\theta = -\beta_2 / 2\beta_3\), e o estimador plug-in é \(\hat\theta=-\hat\beta_2/2\hat\beta_3\).

Esse exemplo é delicado porque \(\hat\theta\) é uma razão. Se \(\hat\beta_3\) estiver próximo de zero, o estimador pode ficar muito instável. Por isso, para testar \(H_0:\theta=\theta_0\), muitas vezes é mais estável usar a forma linear equivalente

\[H_0:\beta_2+2\theta_0\beta_3=0,\]

em vez de testar diretamente a razão.

set.seed(99)
n2    <- 500
educ  <- sample(8:20, n2, replace = TRUE)
exper <- pmax(0, round(rnorm(n2, 15, 8)))

b2_true    <-  0.08
b3_true    <- -0.0016
theta_true <- -b2_true / (2 * b3_true)

X2   <- cbind(1, educ, exper, exper^2)
Y2   <- X2 %*% c(8, 0.05, b2_true, b3_true) + rnorm(n2, sd = 0.3)
mod2 <- lm(Y2 ~ educ + exper + I(exper^2))
b2   <- coef(mod2)

theta_hat <- -b2[3] / (2 * b2[4])

theta_boot <- numeric(B)
for (b in 1:B) {
  idx2          <- sample(n2, n2, replace = TRUE)
  m_b           <- lm(Y2[idx2] ~ educ[idx2] + exper[idx2] + I(exper[idx2]^2))
  c_b           <- coef(m_b)
  theta_boot[b] <- -c_b[3] / (2 * c_b[4])
}

se_boot_theta <- sd(theta_boot)

grad_theta <- c(0, 0, -1/(2*b2[4]), b2[3]/(2*b2[4]^2))
V_b2       <- vcov(mod2)
se_delta   <- sqrt(as.numeric(t(grad_theta) %*% V_b2 %*% grad_theta))

cat("=== Inferência para θ = -β₂/2β₃ (ponto de máximo) ===\n\n")
=== Inferência para θ = -β₂/2β₃ (ponto de máximo) ===
cat("θ verdadeiro:         ", theta_true, "\n")
θ verdadeiro:          25 
cat("θ̂ estimado:          ", round(theta_hat, 2), "\n\n")
θ̂ estimado:           25.07 
cat("EP (método delta):    ", round(se_delta, 4), "\n")
EP (método delta):     0.9531 
cat("EP (bootstrap):       ", round(se_boot_theta, 4), "\n\n")
EP (bootstrap):        0.9273 
IC_boot <- quantile(theta_boot, c(0.025, 0.975))
cat("IC 95% bootstrap:     [", round(IC_boot[1], 2), ",",
    round(IC_boot[2], 2), "]\n")
IC 95% bootstrap:     [ 23.54 , 27.24 ]
cat("θ verdadeiro no IC?  ", IC_boot[1] <= theta_true &
                              theta_true <= IC_boot[2], "\n")
θ verdadeiro no IC?   TRUE 
ggplot(data.frame(theta = theta_boot), aes(x = theta)) +
  geom_histogram(aes(y = after_stat(density)),
                 bins = 60, fill = "steelblue", alpha = 0.6) +
  geom_vline(xintercept = theta_true, color = "red",
             linewidth = 1.2, linetype = "dashed") +
  geom_vline(xintercept = theta_hat, color = "black", linewidth = 1) +
  geom_vline(xintercept = IC_boot, color = "darkgreen",
             linetype = "dotted", linewidth = 1) +
  labs(title = "Distribuição bootstrap de θ̂ = -β̂₂/2β̂₃",
       subtitle = "Vermelho = θ verdadeiro | Verde = IC 95% bootstrap",
       x = "θ̂* (anos de experiência no máximo salarial)",
       y = "Densidade") +
  theme_minimal()

Distribuição bootstrap de θ̂ (ponto de máximo)

7.4.1 Teste da hipótese sobre o ponto de máximo

Para testar \(H_0:\theta=\theta_0\) com \(\theta=-\beta_2/2\beta_3\), podemos reescrever a hipótese como \(H_0:\beta_2+2\theta_0\beta_3=0\). Essa forma é linear em \(\beta_2\) e \(\beta_3\), e tende a ser mais estável do que trabalhar diretamente com a razão.

theta0  <- theta_true
r_theta <- c(0, 0, 1, 2 * theta0)

R_hat <- as.numeric(r_theta %*% coef(mod2))
se_R  <- sqrt(as.numeric(t(r_theta) %*% vcov(mod2) %*% r_theta))
T_R   <- R_hat / se_R
p_R   <- 2 * (1 - pnorm(abs(T_R)))

cat("=== Teste linear para H0: theta =", theta0, "===\n\n")
=== Teste linear para H0: theta = 25 ===
cat("R(theta0) = β̂₂ + 2θ₀β̂₃:", round(R_hat, 5), "\n")
R(theta0) = β̂₂ + 2θ₀β̂₃: 0.00019 
cat("Erro-padrão de R(theta0): ", round(se_R, 5), "\n")
Erro-padrão de R(theta0):  0.00281 
cat("T:                        ", round(T_R, 4), "\n")
T:                         0.0687 
cat("p-valor:                  ", round(p_R, 4), "\n")
p-valor:                   0.9453 

7.4.2 \(p\)-valor bootstrap para a restrição linear

Também podemos usar o bootstrap para aproximar a distribuição da restrição \(R(\theta_0)=\hat\beta_2+2\theta_0\hat\beta_3\). Em cada réplica bootstrap, calculamos

\[R_b^*(\theta_0)=\hat\beta_{2b}^*+2\theta_0\hat\beta_{3b}^*.\]

Usamos a distribuição de \(R_b^*(\theta_0)-R(\theta_0)\) para construir um \(p\)-valor bootstrap bilateral.

R_boot <- numeric(B)
for (b in 1:B) {
  idx2      <- sample(n2, n2, replace = TRUE)
  m_b       <- lm(Y2[idx2] ~ educ[idx2] + exper[idx2] + I(exper[idx2]^2))
  c_b       <- coef(m_b)
  R_boot[b] <- c_b[3] + 2 * theta0 * c_b[4]
}

p_boot_R <- mean(abs(R_boot - R_hat) >= abs(R_hat))

cat("=== p-valor bootstrap para R(theta0) ===\n\n")
=== p-valor bootstrap para R(theta0) ===
cat("p-valor bootstrap:", round(p_boot_R, 4), "\n")
p-valor bootstrap: 0.9327 

7.5 Cobertura empírica: bootstrap vs método delta

Esta seção é computacionalmente mais pesada e está desativada por padrão (eval: false). Para estudar cobertura de forma adequada, o ideal é gerar novos bancos de dados a partir do processo gerador verdadeiro e, dentro de cada banco, construir os intervalos por método delta e bootstrap.

B_cob <- 500
cob_boot <- cob_delta <- numeric(B_cob)

for (b in 1:B_cob) {
  idx_c <- sample(n2, n2, replace = TRUE)
  m_c   <- lm(Y2[idx_c] ~ educ[idx_c] + exper[idx_c] + I(exper[idx_c]^2))
  c_c   <- coef(m_c)
  th_c  <- -c_c[3] / (2 * c_c[4])

  IC_bb     <- quantile(theta_boot, c(0.025, 0.975))
  cob_boot[b] <- IC_bb[1] <= theta_true & theta_true <= IC_bb[2]

  grad_c <- c(0, 0, -1/(2*c_c[4]), c_c[3]/(2*c_c[4]^2))
  se_c   <- sqrt(as.numeric(t(grad_c) %*% vcov(m_c) %*% grad_c))
  IC_d   <- th_c + c(-1, 1) * 1.96 * se_c
  cob_delta[b] <- IC_d[1] <= theta_true & theta_true <= IC_d[2]
}

cat("=== Cobertura empírica do IC 95% para θ ===\n\n")
=== Cobertura empírica do IC 95% para θ ===
cat("Bootstrap (percentil): ", round(mean(cob_boot),  4), "\n")
Bootstrap (percentil):  1 
cat("Método delta:          ", round(mean(cob_delta), 4), "\n")
Método delta:           0.988 
cat("Nominal:                0.95\n")
Nominal:                0.95

Fechamento da Aula 7

A Aula 7 mostra como usar a própria amostra para aproximar a distribuição amostral de estimadores e estatísticas. O jackknife mede sensibilidade removendo uma observação por vez; no MQO, ele se conecta diretamente aos resíduos leave-one-out, à alavancagem e ao HC3. Em dados agrupados, a remoção deve ser feita por cluster, pois a dependência intracluster torna inadequado remover observações isoladas.

O bootstrap não paramétrico sorteia amostras com reposição da distribuição empírica \(\hat{F}_n\). A distribuição dos estimadores bootstrap aproxima a distribuição amostral do estimador original. No universo bootstrap, a “verdade” é \(\hat{F}_n\), e por isso a distribuição relevante é frequentemente \(\hat\theta^*-\hat\theta\).

A aula também mostra que reamostragem é especialmente útil para parâmetros não lineares, como salários esperados em nível ou pontos de máximo de regressões quadráticas. No entanto, bootstrap não é mágica: sua validade depende de regularidade, momentos adequados e estabilidade da função estimada. Razões, divisões por coeficientes próximos de zero e estimadores na fronteira exigem cuidado.