O Método dos Mínimos Quadrados consiste em, dado um conjunto de pontos , determinar uma função que melhor se aproxime de . Geralmente, escrevemos a função como uma combinação linear de funções , tal que: .
Primeiramente vamos definir o método para o caso básico no qual a função é uma combinação linear de funções e , após isso vamos generalizar o método para qualquer número de funções.
Duas variáveis
O problema de quadrados mínimos lineares discreto de duas variáveis consiste em, dadas duas funções e , determinar duas constantes reais e tais que a função esteja o mais próximo possível dos pontos conhecidos. Naturalmente, para determinar o quão próximas são as aproximações é necessário definir o erro, que pode ser definido como . Dessa forma, é possível transformar o problema em um problema de otimização da forma:
Resolvendo esse problema de otimização, obtém-se o seguinte sistema linear, que permite encontrar os valores das constantes e que minimizam o erro da estimativa para a função :
Esse método pode ser facilmente implementado da seguinte forma:
import numpy as np
x = [-0.6975, -0.6762, 0.0176, 0.4512, 0.7559]
fx = [2.0840, 2.0330, 0.8472, 0.6773, 0.4318]
def g1(x):
return 1
# return np.sin(x)
def g2(x):
return np.exp(-x)
# return np.cos(x)
def a11(x):
n = 0
for i in range(len(x)):
n = n + (g1(x[i]) ** 2)
return n
def a12(x):
n = 0
for i in range(len(x)):
n = n + (g1(x[i]) * g2(x[i]))
return n
def a22(x):
n = 0
for i in range(len(x)):
n = n + (g2(x[i]) ** 2)
return n
def y1(x, fx):
n = 0
for i in range(len(x)):
n = n + (g1(x[i]) * fx[i])
return n
def y2(x, fx):
n = 0
for i in range(len(x)):
n = n + (g2(x[i]) * fx[i])
return n
A = [[a11(x), a12(x)], [a12(x), a22(x)]]
b = [y1(x, fx), y2(x, fx)]
print("A = ", A)
print("b = ", b)
result = np.linalg.solve(A, b)
print("a1 = ", result[0])
print("a2 = ", result[1])
Caso geral
No caso geral, o problema de quadrados mínimos consiste em obter coeficientes que minimizem a seguinte função:
sendo a função definida como:
Resolvendo esse problema de otimização através de derivadas parciais, obtém-se equações (as derivadas parciais igualadas a ). Manipulando as equações, é possível obter o seguinte sistema linear, que permite encontrar o valor dos coeficientes :
A implementação desse método consiste na construção e resolução deste sistema linear, como pode ser verificado a seguir:
import numpy as np
import csv
def termoA(x, g, i, j, m):
num = 0
for k in range(0, m):
num = num + (g[i](x[k]) * g[j](x[k]))
return num
def termoB(x, fx, g, i, m):
num = 0
for k in range(0, m):
num = num + (fx[k] * g[i](x[k]))
return num
def matrizAumentada(x, fx, g, n):
m = len(x)
A = np.empty((n, n))
b = np.empty((n))
for i in range(0, n):
for j in range(i, n):
A[i][j] = termoA(x, g, i, j, m)
if i != j:
A[j][i] = A[i][j]
b[i] = termoB(x, fx, g, i, m)
return A, b
x = [-1, -0.5, 0, 0.5, 1]
fx = [8.4, 2.7, 2.6, 2.8, 5.6]
g = [lambda x: 1, lambda x: np.sin(np.pi * x), lambda x: x * np.cos(np.pi * x)]
n = len(g)
A, b = matrizAumentada(x, fx, g, n)
a = np.linalg.solve(A, b)
print("A: ", A)
print("b: ", b)
print("Coeficientes: ", a)