| | | |

Deep Learning para Equações Diferenciais Parciais

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

3.2 Aplicação: Aproximação de funções

Em revisão

Redes Perceptron Multicamadas (MLPs) são aproximadoras universais e vamos aplicá-las na aproximação de funções uni- e bidimensionais.

3.2.1 Teorema da aproximação universal

O teorema da aproximação universal pode ser visto como uma extensão do teorema de Weierstrass222Karl Theodor Wilhelm Weierstrass, 1815 - 1897, matemático alemão. Fonte: Wikipédia: Karl Weierstrass. para redes neurais. Ele afirma que uma MLP com uma camada oculta e uma função de ativação não linear pode aproximar qualquer função contínua em um espaço compacto, com precisão arbitrária, desde que a rede tenha um número suficiente de neurônios na camada oculta.

Teorema 3.2.1.(Aproximação universal)

Seja φ: uma função contínua monotonicamente crescente e limitada. Sejam In=[0,1]n e fC(In;) uma dada função contínua de In em . Então, para todo ϵ>0, existe um m e um conjunto de constantes reais αi, bi e 𝒘i,j, i=1,2,,m, tais que a função

F(𝒙)=i=1mαiφ(j=1nwi,jxj+bi),𝒙In, (3.12)

é uma aproximação de f em In no sentido de que

|F(𝒙)f(𝒙)|<ϵ,𝒙In. (3.13)
Demonstração.

Consulte [3] para o caso de funções de ativação sigmoidal e [8] para o caso de funções de ativação mais gerais. ∎

O Teorema 3.2.1 é diretamente aplicável a uma rede MLP com uma camada escondida, tangente hiperbólica como função de ativação e uma camada de saída com função de ativação identidade. Ele garante que, para qualquer função contínua f em um espaço compacto, existe uma MLP com essa arquitetura que pode aproximar f com precisão arbitrária, desde que a camada escondida tenha um número suficiente de neurônios. A extensão do teorema para a aproximação de funções multivariadas é direta.

Redes MLP com função de ativação ReLU não se encaixam no Teorema 3.2.1. Entretanto, resultados teóricos sobre a aproximação de funções com tais redes também estão disponíveis. Consulte, por exemplo, [4].

O Teorema 3.2.1 é um resultado teórico importante, pois estabelece a capacidade de aproximação das MLPs. No entanto, ele não fornece uma maneira prática de determinar o número de neurônios necessários na camada escondida para alcançar uma determinada precisão, nem garante que o processo de treinamento da rede encontrará os pesos e biases adequados para realizar a aproximação desejada. Ainda, o teorema não estabelece que redes com apenas uma camada escondida sejam as melhores para a aproximação de funções, e sim que elas são suficientes. Na prática, redes com múltiplas camadas escondidas (redes profundas) podem ser mais eficientes para aproximar funções complexas.

3.2.2 Função unidimensional

Vamos criar uma MLP para aproximar a função

y=sen(πx), (3.14)

para x[1,1].

Refer to caption
Figura 3.2: Aproximação MLP da função y=sen(πx).
Código 6: mlp_apfun_1d
1import torch
2import matplotlib.pyplot as plt
3
4# modelo
5
6model = torch.nn.Sequential()
7model.add_module('layer_1', torch.nn.Linear(1,25))
8model.add_module('fun_1', torch.nn.Tanh())
9model.add_module('layer_2', torch.nn.Linear(25,25))
10model.add_module('fun_2', torch.nn.Tanh())
11model.add_module('layer_3', torch.nn.Linear(25,1))
12
13# treinamento
14
15## fun obj
16fun = lambda x: torch.sin(torch.pi*x)
17a = -1.
18b = 1.
19
20## optimizador
21optim = torch.optim.SGD(model.parameters(),
22 lr=1e-1, momentum=0.9)
23
24## num de amostras por época
25ns = 100
26## num max épocas
27nepochs = 5000
28## tolerância
29tol = 1e-5
30
31## amostras de validação
32X_val = torch.linspace(a, b, steps=100).reshape(-1,1)
33y_vest = fun(X_val)
34
35for epoch in range(nepochs):
36
37 # amostras
38 X_train = (a - b) * torch.rand((ns,1)) + b
39 y_train = fun(X_train)
40
41 # forward
42 y_est = model(X_train)
43
44 # erro
45 loss = torch.mean((y_est - y_train)**2)
46
47 print(f'{epoch}: {loss.item():.4e}')
48
49 # backward
50 optim.zero_grad()
51 loss.backward()
52 optim.step()
53
54 # validação
55 y_val = model(X_val)
56 loss_val = torch.mean((y_val - y_vest)**2)
57 print(f"\tloss_val = {loss_val.item():.4e}")
58
59 # critério de parada
60 if (loss_val.item() < tol):
61 break
62
63
64# verificação
65fig = plt.figure()
66ax = fig.add_subplot()
67
68x = torch.linspace(a, b,
69 steps=100).reshape(-1,1)
70
71y_esp = fun(x)
72ax.plot(x, y_esp, label='fun')
73
74y_est = model(x)
75ax.plot(x, y_est.detach(), label='model')
76
77ax.legend()
78ax.grid()
79ax.set_xlabel('x')
80ax.set_ylabel('y')
81plt.show()

3.2.3 Função bidimensional

Vamos criar uma MLP para aproximar a função bidimensional

y=sen(πx1)sen(πx2), (3.15)

para (x1,x2)𝒟:=[1,1]2.

Vamos usar uma arquitetura de rede 2nn×31 (duas entradas, 3 camadas escondidas com nn neurônios e uma saída). Nas nh=3 camadas escondidas, vamos usar a tangente hiperbólica como função de ativação.

Para o treinamento, vamos usar o erro médio quadrático como função erro

ε=1nss=1ns|y~(s)y(s)|2, (3.16)

onde, a cada época, ns pontos randômicos333Em uma distribuição uniforme. {𝒙(s)}𝒟 são usados para gerar o conjunto de treinamento {(𝒙(s),y(s))}s=1ns.

Refer to caption
Figura 3.3: Aproximação MLP da função y=sen(πx1)sen(πx2). Linhas: isolinhas da função. Mapa de cores: MLP. Estrelas: pontos de treinamentos na última época.
Código 7: mlp_apfun_2d
1 import torch
2
3 # modelo
4 nn = 50
5 model = torch.nn.Sequential()
6 model.add_module('layer_1', torch.nn.Linear(2,nn))
7 model.add_module('fun_1', torch.nn.Tanh())
8 model.add_module('layer_2', torch.nn.Linear(nn,nn))
9 model.add_module('fun_2', torch.nn.Tanh())
10 model.add_module('layer_3', torch.nn.Linear(nn,nn))
11 model.add_module('fun_3', torch.nn.Tanh())
12 model.add_module(f'layer_4', torch.nn.Linear(nn,1))
13
14 # treinamento
15
16 ## fun obj
17 def fun(x1, x2):
18 return torch.sin(torch.pi*x1) * \
19 torch.sin(torch.pi*x2)
20
21 x1_a = -1.
22 x1_b = 1
23
24 x2_a = -1.
25 x2_b = 1.
26
27
28 ## optimizador
29 optim = torch.optim.SGD(model.parameters(),
30 lr=1e-1, momentum=0.9)
31
32 ## num de amostras por época
33 ns = 20
34 ## num max épocas
35 nepochs = 50000
36 ## tolerância
37 tol = 1e-4
38
39 ## amostras de validação
40 n_val = 50
41 x1 = torch.linspace(x1_a, x1_b, steps=n_val)
42 x2 = torch.linspace(x2_a, x2_b, steps=n_val)
43 X1_val, X2_val = torch.meshgrid(x1, x2, indexing='ij')
44 X_val = torch.hstack((X1_val.reshape(n_val**2,1),
45 X2_val.reshape(n_val**2,1)))
46 Y_vest = fun(X1_val, X2_val).reshape(-1,1)
47
48 for epoch in range(nepochs):
49
50 # amostras
51 X1 = (x1_b - x1_a) * torch.rand(ns**2, 1) + x1_a
52 X2 = (x2_b - x2_a) * torch.rand(ns**2, 1) + x2_a
53 # X1, X2 = torch.meshgrid(x1, x2, indexing='ij')
54 X_train = torch.hstack((X1, X2))
55 Y_train = fun(X1, X2).reshape(-1,1)
56
57
58 # forward
59 Y_est = model(X_train)
60
61 # erro
62 loss = torch.mean((Y_est - Y_train)**2)
63
64 if (epoch % 100 == 0):
65 print(f'{epoch}: {loss.item():.4e}')
66
67 # backward
68 optim.zero_grad()
69 loss.backward()
70 optim.step()
71
72 # validação
73 if (epoch % 100 == 0):
74 Y_val = model(X_val)
75 loss_val = torch.mean((Y_val - Y_vest)**2)
76
77 print(f"\tloss_val = {loss_val.item():.4e}")
78
79 # critério de parada
80 if (loss_val.item() < tol):
81 break

3.2.4 Exercícios

E. 3.2.1.

Crie uma MLP para aproximar a função gaussiana

y=ex2 (3.17)

para x[1,1].

E. 3.2.2.

Crie uma MLP para aproximar a função y=sin(x) para x[π,π].

E. 3.2.3.

Crie uma MLP para aproximar a função y=sin(x)+cos(x) para x[0,2π].

E. 3.2.4.

Crie uma MLP para aproximar a função gaussiana

z=e(x2+y2) (3.18)

para (x,y)[1,1]2.

E. 3.2.5.

Crie uma MLP para aproximar a função y=sin(x1)cos(x2) para (x1,x2)[0,π]×[π,0].

E. 3.2.6.

Crie uma MLP para aproximar a função y=sin(x1)+cos(x2) para (x1,x2)[2π,2π].


Envie seu comentário

Aproveito para agradecer a todas/os que de forma assídua ou esporádica contribuem enviando correções, sugestões e críticas!

Opcional. Preencha seu nome para que eu possa lhe contatar.
Opcional. Preencha seu e-mail para que eu possa lhe contatar.
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.

Licença Creative Commons
Este texto é disponibilizado nos termos da Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional. Ícones e elementos gráficos podem estar sujeitos a condições adicionais.

Pedro H A Konzen
| | | |