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 θ.

