Otimização/Método de gradientes conjugados

De testwiki
Ir para a navegação Ir para a procura


Predefinição:Wikipedia

Algumas considerações históricas

  • Este método foi originalmente proposto por Hestenes e Stiefel, em 1952.
  • Seu objetivo inicial foi a resolução de problemas quadráticos sem restrições, mas logo o mesmo foi estendido para casos mais gerais.

O método

Este método pode ser considerado sob dois pontos de vista:

  • Como um método de descida, com busca linear exata;
  • Como um método de resolução de sistema linear, baseado em um processo de ortogonalização.

Predefinição:Definição

Exemplos de conjuntos convexos e côncavos


Predefinição:Definição

Predefinição:Definição

Predefinição:Exercício Predefinição:Resolução


Nota: Uma matriz é definida positiva se, e somente se, todos os seus autovalores são positivos.

Tem-se:

∇f:ℝn↦ℝ
∇2f:ℝn↦(ℝn)2

Sendo f(x)=12x⊤Ax+a⊤x+α, segue em particular que ∇f=Ax+a e ∇2f=A=P⊤ΛP, onde Λ é uma matriz diagonal cujos elementos da diagonal são os autovalores de A e P é uma matriz onde as colunas são os autovetores correspondentes aos autovalores.

Note que A é uma matriz simétrica, pois é a matriz Hessiana de uma função com segundas derivadas parciais contínuas, e consequentemente vale ∂2f∂x∂y=∂2f∂y∂x.

Para introduzir o método de direções conjugadas, serão consideradas somente funções quadráticas.

Uma condição necessária de primeira ordem para que x seja um ponto de mínimo para a função f é que ∇f(x)=0. Para o presente caso, a função f é convexa, então, a condição necessária ∇f(x)=0 também é suficiente.

Predefinição:Exercício Predefinição:Resolução

No caso de uma função quadrática, tem-se ∇f(x)=0⇔Ax+a=0, ou seja, x é solução do sistema linear Ax=−a.

A resolução de um sistema linear nem sempre pode ser feita numericamente de forma eficiente. Por exemplo, se a matriz do sistema é:

A=[10−20111020+1]

A solução do sistema linear corresponde à interseção entre duas retas quase paralelas, e os erros de truncamento podem causar imprecisão na solução obtida computacionalmente.

Analiticamente, o sistema Ax=−a tem x=−A−1a como solução. Então alguém poderia se perguntar: qual o problema em resolver esse sistema linear, se basta calcular a inversa da matriz A e multiplicar pelo vetor −a? A resposta é que o calculo da inversa de uma matriz em geral é impraticável computacionalmente, por ter custo muito alto. Por isso, nas situações práticas, onde as matrizes tem ordem bem maior do que 2 (digamos 1000), o cálculo de matrizes inversas não é uma opção.

Assim, com o intuito de desenvolver um método computacional para o cálculo de minimizadores, é preciso utilizar outras técnicas. Considere o seguinte:

Em um método de descida tem-se sempre uma sequencia {xk,tk,dk}∈ℕ, com xk+1=xk+tkdk e tk é um minimizador de f(xk+tdk):t∈ℝ

∇f(x)=Ax+a

e

0=∇f(xk+1)=Axk+1+a=A(xk+tkdk)+a=Axk+tkAdk+a

Logo, tkAdk=−(Axk+a) e multiplicando por dk⊤ obtem-se tkdk⊤Adk=−(dk⊤Axk+dk⊤a). Consequentemente, o valor de tk é dado por

tk=−(dk⊤Axk+a⊤dk)dk⊤Adk

Deste modo, o método consistirá de escolher em cada etapa k uma direção dk, e calcular o coeficiente tk pela fórmula anterior, para gerar o próximo ponto xk+1. Mas como escolher a direção dk?

Dado xk e escolhido dk, defina θ:R↦ℝ como θ(t)=f(xk+tdk), ou seja, θ é a restrição da função f à reta que passa pelo ponto xk e que tem direção dk. Logo, derivando a expressão de θ em relação a t, obtem-se

θ′(t)=∇f(xk+tdk)⊤dk

Então, no ponto de mínimo, xk+1, tem-se

0=∇f(xk+1)⊤dk

Ou seja, a direção dk a ser seguida a partir do ponto xk é ortogonal ao gradiente da função f, no ponto xk+1.

Esquema do método de descida

xk+1=xk+tkdk=(xk−1+tk−1dk−1)+tkdk=…=x1+t1d1+…+tkdk=x1+∑i=1ktidi

Seja x¯ o minimizador da função f. Tem-se

xk+1−x¯=x1−x¯+∑i=1ktidi

Mas 0=∇f(x¯)=Ax¯+a implica que a=−Ax¯, logo

∇f(x)=Ax+a=Ax−Ax¯=A(x−x¯)

e consequentemente

A(xk+1−x¯)=A(x1−x¯)+∑i=1ktiAdi

Donde ∇f(xk+1)=∇f(x1)+∑i=1ktiAdi. Portanto 0=∇f(xk+1)⊤dk=∇f(x1)⊤dk+∑i=1ktidi⊤Adk.

Predefinição:Exercício Predefinição:Resolução

Usando o resultado desse exercício, tem-se ainda que 0=∇f(xk+1)⊤dk=∇f(x1)⊤dk+∑i=1kti(Bdi)⊤(Bdk)

Fazendo δ=Bd, o método do gradiente conjugado escolhe as direções de descida tais que δi⊤dj=0,∀i≠j. Mas quando i≠j, tem-se na expressão apresentada anteriormente apenas 0=∇f(x1)⊤dk+tk(Bdk)⊤(Bdk)=∇f(x1)⊤dk+tkdkAdk

Finalmente, tem-se o algoritmo para este método.

Algoritmo de Hestenes-Stiefel

Uma comparação da convergência do método de descida do gradiente com tamanho de passo ótimo (em verde) e o método do gradiente conjugado (em vermelho) para a minimização da forma quadrática com um sistema linear dado. O gradiente conjugado, assumindo aritmética exata, converge em no máximo n passos onde n é o tamanho da matriz do sistema (no exemplo, n=2).
Primeiro passo: Escolha x0∈ℝn
  Se ∇f(x0)=0, então pare: x¯=x0
  Senão: d0=−∇f(x0)=−Ax0−a
  Calcular t0=‖∇f(x0)‖2d0⊤Ad0
  x1=x0+t0d0


Passo iterativo k: Dado xk∈ℝn
  Se ∇f(xk)=0, então pare: x¯=xk
  Senão: dk=−∇f(xk)+∇f(xk)⊤Adkdk⊤Adkdk
  tk=‖∇2f(xk)‖2dk⊤Adk
  xk+1=xk+tkdk

Pode-se verificar facilmente que dk+1⊥dk. De fato, como dk+1=−∇f(xk+1)+∇f(xk+1)⊤Adkdk⊤Adkdk, tem-se Adk+1=−A∇f(xk+1)+∇f(xk+1)⊤Adkdk⊤AdkAdk. Logo, dk⊤Adk+1=−∇f(xk+1)⊤Adk+∇f(xk+1)⊤Adkdk⊤Adkdk⊤Adk=−∇f(xk+1)⊤Adk+∇f(xk+1)⊤Adk=0.

Predefinição:Exercício Predefinição:Resolução


Exemplos

Considere f:ℝ2↦ℝ definida por f(x,y)=12(x2+y2)=12[xy][1001][xy]. Em outros termos, tomando u=[xy], tem-se f(u)=12u⊤Au, onde A=[1001]=I2×2.

Pode-se aplicar o método de direções conjugadas ao seguinte problema

(P){minf(u)u∈ℝ2

Note, desde já, que o conjunto solução é S={[00]}.

Inicio
  • Toma-se x0 arbitrário, por exemplo, x0=[21].
  • Avalia-se o gradiente da função f neste ponto inicial: ∇f(x0)=Ax0=I2×2x0=x0
Iteração 1
  • d0=−∇f(x0)=[−2−1]
  • t0=‖∇f(x0)‖2d0⊤Ad0=55=1
  • x1=x0+t0d0=[21]+1[−2−1]=[00]

A seguir, verifica-se se o gradiente se anula no novo ponto x1:

  • ∇f(x1)=A[00]=[00]

Como o gradiente já é nulo, não é preciso fazer a segunda iteração, e o ponto x1 é o (único) minimizador global de f.


Em um caso mais geral, considerando f:ℝ2↦ℝ definida por f(x,y)=λ2(x2+y2)=12[xy][λ00λ][xy], tem-se cálculos muito parecidos em cada passo.

O conjunto solução continua sendo S={[00]}.

Inicio
  • Considere x0 como no primeiro exemplo, ou seja, x0=[21].
  • Avalia-se o gradiente da função f neste ponto inicial: ∇f(x0)=Ax0=λx0
Iteração 1
  • d0=−∇f(x0)=λ[−2−1]
  • t0=‖∇f(x0)‖2d0⊤Ad0=5λ25λ3=1λ
  • x1=x0+1λλd0=[2λλ]+1[−2λ−λ]=[00]

A seguir, verifica-se se o gradiente se anula no novo ponto x1:

  • ∇f(x1)=A[00]=λ[00]=[00]

Novamente, o gradiente se anula já na primeira iteração, de modo que x1 é o minimizador global de f.


Predefinição:Exercício

Um terceiro exemplo pode ser dado tomando A=[2−1−12] e f:ℝ2↦ℝ definida por f(u)=12u⊤Au. Observe que tal matriz é simétrica e definida positiva:

det⁡(A−λI)=(2−λ)(3−λ)−1=λ2−4λ−3=(λ−3)(λ−1)

Logo, os autovalores de A são λ=1 e λ=3. Isso também implica que a função é fortemente convexa.

Aplicando o método:

Início
  • Toma-se um ponto arbitrário no plano, por exemplo x0=[1020];
  • Verifica-se se tal ponto é o minimizador global, avaliando nele o gradiente da função:
∇f(x0)=[2−1−12][1020]=[030]≠[00].
  • Já que o gradiente não se anulou no chute inicial, é preciso escolher uma direção e um comprimento de passo para determinar a próxima aproximação:
Iteração 1
d0=−∇f(x0)=[0−30]
t0=‖[030]‖2[0−30][2−1−12][0−30]=900[0−30][−30−60]=9001800=12

Feitos esses cálculos, o próximo ponto é dado por

x1=x0+t0d0=[1020]+12[0−30]=[1020]+[0−15]=[105]

Para saber se será necessária uma nova iteração, ou se o minimizador foi encontrado, calcula-se o gradiente da função no ponto:

∇f(x1)=[2−1−12][105]=[150]≠[00].

Novamente, será preciso calcular uma nova direção e um novo comprimento de passo:

Iteração 2
d0=[−150]+β[0−30]=[−15−30β]

onde β, no algoritmo de Hestenes é dado por:

β=[150][2−1−12][0−30][0−30][2−1−12][0−30]=[150][30−60][0−30][30−60]=15×30(−30)×(−60)=14

Portanto

d0=−15[11/2]

Além disso, o tamanho do passo é dado por

t1=‖∇f(x1)‖2d0⊤Ad0=152152[11/2][2−1−12][11/2]=1[11/2][3/20]=13/2=23

Portanto

x2=x1+t1d1=[105]−1523[11/2]=[105]−10[11/2]=[00]

Obviamente, este é o minimizador procurado (pois o método tem a propriedade de convergência quadrática, ou seja utiliza no máximo n iterações para chegar a solução quando aplicado a funções quadráticas definidas em ℝn)

Predefinição:Exercício

Predefinição:Exercício

Implementação em Scilab

Abaixo é apresentada uma implementação deste algoritmo na linguagem de programação utilizada pelo Scilab.

A = [2 1; 1 2];

function [x] = min_gradiente_conjugado(xk)
  //Entrada: xk em R^n, qualquer "chute inicial"
  //  Saída: x, o ponto em que f assume o valor mínimo
  
  k        = 0        //Indica quantos loops já foram feitos
  epsilon  = 0.01
  n        = size(xk,1)
  g        = df(xk)
  seq      = zeros(n,n+1)
  seq(:,1) = xk
  while (norm(g) > epsilon) & (k <= n)
    if (k == 0)
      d = -g
    else
      d = Hestenes(g,d,A)
    end
    t  = busca_linear(g,d,A)
    xk = xk + t*d
    k  = k+1
    seq(:,k+1) = xk
    g  = df(xk)
  end
  plot(seq(1,:),seq(2,:))
  x = xk  
endfunction


function [fu] = f(u)
  fu=(1/2)*(u'*A*u)
endfunction


function [grf] = df(u)
  grf = A*u
endfunction


function [d] = Hestenes(g,d,A)
  d=-g + ((g'*A*d)/(d'*A*d))*d
endfunction


function [t] = busca_linear(g,d,A)
  t=(g'*g)/(d'*A*d)
endfunction

Para facilitar a compreensão do método, pode ser útil exibir as curvas de nível da função. Uma forma de implementar uma função com esse propósito é a seguinte:

function plotar_curvas
  qtd=101
  tam=max(seq)
  x=linspace(-tam,tam,qtd)
  y=x
  z=zeros(qtd,qtd)
  for i=1:qtd
    for j=1:qtd
      z(i,j)=f([x(i);y(j)])
    end
  end
  contour2d(x,y,z,10)
  a=gca();
  a.x_location = "middle"; 
  a.y_location = "middle"; 
endfunction

Algoritmo de Fletcher-Reeves

Predefinição:Tarefa


Esta versão é na verdade uma extensão do algoritmo anterior, permitindo a aplicação no caso de funções que não são quadráticas.

Primeiro passo: Escolha x0∈ℝn
 Se ∇f(x0)=0, então pare: x¯=x0
 Senão: d0=−∇f(x0) (como em todo método de descida)
 Calcular t0, através de uma busca linear
 x1=x0+t0d0
Passo iterativo:
 Se ∇f(xk)=0, então pare: x¯=xk
 Senão: dk=−∇f(xk)+‖∇f(xk)‖2‖∇f(xk−1)‖2dk−1
 Calcular tk, através de uma busca linear
 xk+1=xk+tkdk
 k=k+1

Predefinição:Tarefa

Algoritmo de Polak-Ribière

Predefinição:Tarefa

Uma outra versão é a seguinte:

Primeiro passo: Tomar x0∈ℝn
 Se ∇f(x0)=0, então pare: x¯=x0
 Senão: d0=−∇f(x0) (como em todo método de descida)
 Calcular t0, através de uma busca linear
 x1=x0+t0d0
 k=1
Passo iterativo:
 Se ∇f(xk)=0, então pare: x¯=xk
 Senão: dk=−∇f(xk)+∇f(xk)⊤(∇f(xk)−∇f(xk−1))‖∇f(xk−1)‖2dk−1
 Calcular tk, através de uma busca linear
 xk+1=xk+tkdk
 k=k+1

Predefinição:Tarefa

Predefinição:Exercício Predefinição:Exercício

Algoritmo auxiliar

Para o caso de funções não quadráticas, é preciso usar algum método de busca linear para a implementação do método dos gradientes conjugados, seja a versão de Fletcher-Reeves ou a de Polak-Ribière. Uma possibilidade é a busca de linear de Armijo (ver Izmailov & Solodov (2007), vol 2, pag. 65), cujo algoritmo é esboçado a seguir:

function busca_linear_Armijo (f, theta, alpha, delta, t0)
  while (alpha * pred > ared)
    t = d * t
  end
endfunction

com:

  • pred=−tθ
  • θ(t)=f(x+td)
  • θ′(t)=∇f(x+td)⊤d

Predefinição:Tarefa

Predefinição:AutoCat