Pular para o conteúdo principal

Tutorial: equação normal para regressão linear

Entenda o que é a equação normal e como usá-la para construir modelos de machine learning.
· 8 min leer

Explore com IA

A maioria dos problemas que enfrentamos pode ser resolvida de várias formas. Por exemplo, se quisermos ir de um lado a outro de uma sala, podemos dar a volta caminhando até chegar ao lado oposto — ou simplesmente atravessar em linha reta.

A equação normal reforça exatamente esse conceito. É só mais uma maneira de resolver um problema. Que problema? Vamos explicar no restante deste artigo. Por ora, tudo que você precisa saber é que é uma abordagem eficaz que pode economizar muito tempo ao implementar regressão linear em certas condições.

Vamos aprofundar…

O que é a equação normal?

A equação normal é uma solução em forma fechada usada para encontrar o valor de θ que minimiza a função de custo na regressão linear por mínimos quadrados ordinários (OLS). Outra forma de descrevê-la é como uma abordagem analítica para encontrar os coeficientes que minimizam a função de perda. As duas descrições funcionam, mas o que isso significa na prática? 

A regressão linear faz uma previsão, y_hat, calculando a soma ponderada das features de entrada mais um termo de viés (bias). Em termos matemáticos, podemos representar assim:

Onde θ representa os parâmetros e n é o número de features.

Essencialmente, o que ocorre na equação acima é o produto escalar de θ e x sendo somado. Assim, uma forma mais concisa de representar isso é usar a forma vetorizada:

h(θ) é a função hipótese.

A partir dessa função-alvo aproximada, podemos usar o modelo para fazer previsões. Para saber se o modelo aprendeu bem, é importante medir seu desempenho nos dados de treino. Para isso, calculamos uma função de perda. O objetivo do treinamento é encontrar os valores de theta (θ) que minimizam essa função.

Veja como podemos representar a função de perda matematicamente:

Na equação acima, theta (θ) é um vetor de dimensão n + 1, e nossa função de perda é função desse vetor. Consequentemente, a derivada parcial da função de perda, J, precisa ser tomada em relação a cada parâmetro θ_j. Todas devem ser iguais a zero. Seguindo esse processo e resolvendo todos os valores de θ de θ_0 a θ_n, obtemos os valores de θ que minimizam a perda.

Resolver os parâmetros de θ_0 a θ_n pelo processo descrito acima leva a uma dedução bem trabalhosa. Existe, de fato, uma solução mais rápida.

Veja a fórmula da equação normal:

Onde:

θ → os parâmetros que minimizam a função de perda X → os valores das features de entrada para cada instância y → o vetor de valores de saída para cada instância

Equação normal vs. gradient descent

Embora ambos os métodos busquem encontrar os parâmetros theta (θ) que minimizam a função de perda, a forma de chegar lá é bem diferente em cada caso.

Como já vimos como funciona a equação normal na seção anterior, vamos passar rapidamente pelo gradient descent e depois destacar em que os dois diferem.

Gradient descent

O gradient descent é um dos algoritmos mais usados em machine learning. Ele é aplicado para, iterativamente, encontrar os parâmetros theta (θ) que minimizam a função de perda.

O processo começa avaliando o desempenho do modelo. Em seguida, calcula-se a derivada parcial da função de perda, que indica a inclinação no ponto atual. Por fim, damos passos proporcionais ao gradiente negativo para descer até o mínimo da função de perda, atualizando o conjunto corrente de parâmetros — veja a fórmula abaixo.

Esse processo se repete até a convergência no mínimo da função de perda.

Em que eles diferem?

A diferença mais clara é que a equação normal é analítica. Já o gradient descent é iterativo, ou seja, os parâmetros são ajustados gradualmente até a convergência. Uma diferença adicional embutida nisso é que o gradient descent exige definir uma taxa de aprendizado, que controla o tamanho dos passos rumo ao mínimo da perda. A equação normal dispensa taxa de aprendizado porque não há etapas iterativas — obtemos o resultado diretamente.

Além disso, o escalonamento de features não é necessário quando usamos a equação normal; normalmente fazemos esse escalonamento para garantir que as features tenham faixas de valores semelhantes, pois o gradient descent é sensível às escalas dos dados. Se não normalizarmos as features ao usar gradient descent, podemos introduzir distorções no contorno da função de perda — problema do qual a equação normal não sofre.

Quando usar a equação normal

A melhor forma de decidir se você deve usar a equação normal em vez do gradient descent é entender suas desvantagens.

Calcular a equação normal se torna pesado quando o número de features do dataset é grande. Isso porque, para resolver os parâmetros θ, é preciso computar o termo (X’ X)^-1. O produto X’ X gera uma matriz n x n e, em muitas implementações, a inversão de matriz cresce aproximadamente com o cubo da dimensão. Ou seja, a operação de inversão roda com complexidade O(n^3), o que torna a equação normal muito lenta quando n é muito grande — saiba mais sobre complexidade de tempo.

Assim, é melhor usar gradient descent quando o número de features é grande. Andrew Ng, referência em machine learning e IA, recomenda considerar gradient descent quando o número de features, n, for maior que 10.000. Para 10.000 ou menos, pode valer a pena usar uma abordagem analítica como a equação normal, já que você não precisa escolher uma taxa de aprendizado — ou seja, é um hiperparâmetro a menos para ajustar. No entanto, vale dizer que linguagens como R ou Python geralmente usam decomposição QR para encontrar os coeficientes na regressão linear OLS, pois a decomposição QR é numericamente mais estável e eficiente do que a equação normal. 

Equação normal do zero em Python

Vamos gerar um problema de regressão para testar a equação:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_regression

# Gera um problema de regressão
X, y = make_regression(
    n_samples=100,
    n_features=2,
    n_informative=2,
    noise = 10,
    random_state=25
    )

# Visualiza a feature no índice 1 vs. o alvo
plt.subplots(figsize=(8, 5))
plt.scatter(X[:, 1], y, marker='o')
plt.xlabel("Feature no índice 1")
plt.ylabel("Alvo")
plt.show()

Agora vamos implementar a equação normal:

# adiciona x0 = 1 a cada instância
X_b = np.concatenate([np.ones((len(X), 1)), X], axis=1)
# calcula a equação normal
theta_best = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)
# melhores valores para theta
intercept, *coef = theta_best
print(f"Intercepto: {intercept}\n\
Coeficientes: {coef}")

Intercept: 0.35921242677977794
Coefficients: [6.129199175400593, 96.44309685893134]

Vamos colocar o modelo à prova fazendo uma previsão:

# criando uma nova amostra
new_sample = np.array([[-2, 0.25]])
# adicionando o termo de bias à instância
new_sample_b = np.concatenate([np.ones((len(new_sample), 1)), new_sample], axis=1)
# prevendo o valor da nova amostra
new_sample_pred = new_sample_b.dot(theta_best)
print(f"Previsão: {new_sample_pred}")
Prediction: [12.21158829]

Sempre que você implementar um algoritmo de machine learning do zero, é útil ter um método para validar sua solução; a Scikit-learn é uma das bibliotecas de machine learning mais populares em Python. Ela oferece diversas implementações de algoritmos, incluindo regressão linear, que usaremos para validar nossa equação normal.

from sklearn.linear_model import LinearRegression

lr = LinearRegression()
lr.fit(X, y)

print(f"Intercepto: {lr.intercept_}\n\
Coeficientes: {lr.coef_}")
print(f"Previsão: {lr.predict(new_sample)}")

Intercept: 0.3592124267797807
Coefficients: [ 6.12919918 96.44309686]
Prediction: [12.21158829]

As soluções são aproximadamente iguais, então podemos confirmar que nossa implementação está correta.

Perguntas frequentes (FAQs)

O que é a equação normal em machine learning?

A equação normal é uma forma analítica de encontrar o valor de θ que minimiza a função de perda sem precisar iterar.

Quando devo usar a equação normal em vez de gradient descent?

É melhor usar a equação normal quando temos poucas variáveis (features). Calcular a equação normal se torna computacionalmente desafiador quando o número de features do conjunto de dados é grande.

A equação normal pode ser usada para regressão logística?

Infelizmente, não. Existe apenas um modelo condicional na teoria de classificação com solução em forma fechada — a regressão linear.

Qual é a diferença entre a equação normal e o gradient descent?

A diferença óbvia entre a equação normal e o gradient descent é que a equação normal usa uma abordagem analítica para encontrar o mínimo da função de perda, enquanto o gradient descent usa uma abordagem iterativa. Outra diferença é que você não precisa ajustar a taxa de aprendizado para calcular a equação normal, já que apenas um passo é necessário para encontrar os parâmetros θ.

Temas

Relacionado

Tutorial

Tutorial de regressão linear no R