| | | | |

3.4 Diferenciação Automática

Ajude a manter o site livre, gratuito e sem propagandas. Colabore!

Diferenciação automática é um conjunto de técnicas para a computação de derivadas numéricas em um programa de computador. Explora-se o fato de que um programa computacional executa uma sequência de operações aritméticas e funções elementares, podendo-se computar a derivada por aplicações da regra da cadeia.

PyTorch computa o gradiente (derivada) de uma função f:n a partir de seu grafo computacional. Os gradientes são computados por retropropagação. Por exemplo, para a computação do gradiente

𝒙f(𝒙𝟎)=dfd𝒙|𝒙=𝒙𝟎, (3.19)

primeiramente, propaga-se a entrada 𝒙𝟎 pela função computacional f, obtendo-se y=f(𝒙𝟎). Então, o gradiente é computado por retropropagação.

Exemplo 3.4.1.

Consideramos a função f(x)=sen(πx) e vamos computar

f(x0)=dfdx|x=0 (3.20)

por diferenciação automática.

Antes, observamos que, pela regra da cadeia, denotamos u=πx e calculamos

dfdx =ddusen(u)dudx (3.21)
=cos(u)π (3.22)
=πcos(πx) (3.23)
Refer to caption
Figura 3.6: Grafo computacional da diferenciação automática de f(x)=sen(πx).

Agora, observamos que a computação de f(x) pode ser representada pelo grafo de propagação mostrado na Figura 3.6. Para a computação do gradiente, adicionamos uma variável fictícia z=y. Na retropropagação, computamos

𝒂.dzdy=1 (3.24a)
𝒃.dzdu=dydudzdy
=ddu[sen(u)]1
=cos(u) (3.24b)
𝒄.dzdx=dudxdzdu (3.24c)
=ddx[πx]cos(u) (3.24d)
=πcos(πx)=dydx. (3.24e)
Refer to caption
Figura 3.7: Comparação entre as diferenciações analítica (f) e automática (autograd).
Código 10: mlp_autograd_df1d
1import torch
2
3# input
4x = torch.linspace(-1., 1., steps=50).reshape(-1,1)
5# requires grad
6x.requires_grad = True
7
8# output
9y = torch.sin(torch.pi*x)
10
11# compute gradients
12y.backward(gradient=torch.ones_like(y))
13
14# dy/dx
15dydx = x.grad

A computação do gradiente também acaba por construir um novo grafo (consulte Figura 3.6). Este, por sua vez, pode ser usado para a computação da diferenciação automática de segunda ordem, i.e. para a derivação de segunda ordem.

Exemplo 3.4.2.

Consideramos a função y=sen(πx). No exemplo anterior, computamos dy/dx=πcos(πx) por diferenciação automática. No Código 10, os gradientes foram computados com o comando

1y.backward(gradient=torch.ones_like(y))
2dudx = x.grad

Alternativamente, podemos usar

1dydx = torch.autograd.grad(
2    y, x,
3    grad_outputs=torch.ones_like(y),
4    retain_graph=True,
5    create_graph=True)[0]

Este comando computa dy/dx, mas avisa o PyTorch que os grafos computacionais sejam mantidos e que um novo grafo seja gerado da retropropagação. Com isso, podemos computar o gradiente do gradiente, como no código abaixo.

Refer to caption
Figura 3.8: Comparação entre as diferenciações analítica (f, f′′) e automática (dydx, d2ydx2).
Código 11: mlp_autograd_d2f1d
1import torch
2
3# input
4x = torch.linspace(-1., 1., steps=50).reshape(-1,1)
5# requires grad
6x.requires_grad = True
7
8# output
9y = torch.sin(torch.pi*x)
10
11# compute gradients
12dydx = torch.autograd.grad(
13    y, x,
14    grad_outputs=torch.ones_like(y),
15    retain_graph=True,
16    create_graph=True)[0]
17
18d2ydx2 = torch.autograd.grad(
19    dydx, x,
20    grad_outputs=torch.ones_like(dydx))[0]

3.4.1 Autograd MLP

Os conceitos de diferenciação automática (autograd) são diretamente estendidos para redes do tipo Perceptron Multicamadas (MLP, do inglês, Multilayer Perceptron). Uma MLP é uma composição de funções definidas por parâmetros (pesos e biases). Seu treinamento ocorre em duas etapas99endnote: 9Para mais detalhes, consulte a Subseção 3.1.1.:

  1. 1.

    Propagação (forward): os dados de entrada são propagados para todas as funções da rede, produzindo a saída estimada.

  2. 2.

    Retropropagação (backward): a computação do gradiente do erro1010endnote: 10Medida da diferença entre o valor estimado e o valor esperado. em relação aos parâmetros da rede é realizado coletando as derivadas (gradientes) das funções da rede. Pela regra da cadeia, essa coleta é feita a partir da camada de saída em direção a camada de entrada da rede.

No seguinte exemplo, exploramos o fato de MLPs serem aproximadoras universais e avaliamos a derivada de uma MLP na aproximação de uma função.

Exemplo 3.4.3.

Vamos criar uma MLP

y~=𝒩(x;(W(l),𝒃(l),f(l))l=1n), (3.25)

que aproxima a função

y=sen(πx),x[1,1]. (3.26)

Em seguida, computamos, por diferenciação automática, o gradiente

dy~dx=x𝒩(x) (3.27)

e comparamos com o resultado esperado

dydx=πcos(πx). (3.28)
Refer to caption
Figura 3.9: Comparação da diferenciação automática da MLP com a derivada analítica f(x)=πcos(πx).
Código 12: mlp_autograd_apfun1d.py
1import torch
2from torch import nn
3from torch import autograd
4
5# modelo
6
7model = torch.nn.Sequential()
8model.add_module('layer_1', torch.nn.Linear(1,25))
9model.add_module('fun_1', torch.nn.Tanh())
10model.add_module('layer_2', torch.nn.Linear(25,25))
11model.add_module('fun_2', torch.nn.Tanh())
12model.add_module('layer_3', torch.nn.Linear(25,1))
13
14# treinamento
15
16## fun obj
17fun = lambda x: torch.sin(torch.pi*x)
18a = -1.
19b = 1.
20
21## optimizador
22optim = torch.optim.SGD(model.parameters(),
23                        lr=1e-1, momentum=0.9)
24
25## num de amostras por época
26ns = 100
27## num max épocas
28nepochs = 5000
29## tolerância
30tol = 1e-5
31
32## amostras de validação
33X_val = torch.linspace(a, b, steps=100).reshape(-1,1)
34y_vest = fun(X_val)
35
36for epoch in range(nepochs):
37
38    # amostras
39    X_train = (a - b) * torch.rand((ns,1)) + b
40    y_train = fun(X_train)
41
42    # forward
43    y_est = model(X_train)
44
45    # erro
46    loss = torch.mean((y_est - y_train)**2)
47
48    print(f'{epoch}: {loss.item():.4e}')
49
50    # backward
51    optim.zero_grad()
52    loss.backward()
53    optim.step()
54
55    # validação
56    y_val = model(X_val)
57    loss_val = torch.mean((y_val - y_vest)**2)
58    print(f"\tloss_val = {loss_val.item():.4e}")
59
60    # critério de parada
61    if (loss_val.item() < tol):
62        break
63
64# autograd MLP
65X_val.requires_grad = True
66# forward
67y_val = model(X_val)
68# gradient
69dydx = autograd.grad(
70    y_val, X_val,
71    grad_outputs=torch.ones_like(y_val))[0]

3.4.2 Exercícios

E. 3.4.1.

Por diferenciação automática, compute o gradiente (a derivada) das seguintes funções

  1. a)

    f(x)=x22x+1 para valores x[2,2].

  2. b)

    g(x)=cos2(x) para valores x[0,2π].

  3. c)

    h(x)=ln(x1) para valores x(1,2].

  4. d)

    u(t)=et2sen(t) para valores t[π,π].

Em cada caso, compare os valores computados com os valores esperados.

E. 3.4.2.

Em cada item do Exercício 3.4.1, faça um fluxograma dos grafos computacionais da propagação e da retropropagação na computação dos gradientes.

E. 3.4.3.

Em cada item do Exercício 3.4.1, compute a derivada de segunda ordem da função indicada. Compare os valores computados com os valores esperados.

E. 3.4.4.

Por diferenciação automática, compute os gradientes das seguintes funções:

  1. a)

    f(x,y)=x2+y2 para valores (x,y)[1,1]2.

  2. b)

    g(x,y)=exsen(xy) para valores (x,y)(1,2)×(0,π).

Em cada caso, compare os valores computados com os valores esperados.

E. 3.4.5.

Para as funções de cada item do Exercício 3.4.6, compute:

  1. a)

    2x2.

  2. b)

    2xy.

  3. c)

    2y2.

Compare os valores computados com os valores esperados.

E. 3.4.6.

Em cada item do Exercício 3.4.6, compute o laplacino Δ=(2x2+2y2) da função indicada. Compare os valores computados com os valores esperados.

E. 3.4.7.

Seja a função 𝒇:22 definida por

𝒇(x,y)=[xy2x2y+6x+x2y37] (3.29)

no domínio 𝒟=[1,2]×[1,3]. Por diferenciação automática e para valores no domínio da função, compute:

  1. a)

    f1(x,y).

  2. b)

    f2(x,y).

  3. c)

    2f1x2.

  4. d)

    2f1xy.

  5. e)

    2f1y2.

  6. f)

    2f2x2.

  7. g)

    2f2xy.

  8. h)

    2f2y2.


Envie seu comentário

As informações preenchidas são enviadas por e-mail para o desenvolvedor do site e tratadas de forma privada. Consulte a Política de Uso de Dados para mais informações. Aproveito para agradecer a todas/os que de forma assídua ou esporádica contribuem enviando correções, sugestões e críticas!