| | | | |

2.1 Unidade de Processamento

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

A unidade básica de processamento (neurônio artificial) que exploramos nestas notas é baseada no perceptron (Fig. 2.1). Consiste na composição de uma função de ativação f: com a pré-ativação

z :=𝒘𝒙+b (2.1)
=w1x1+w2x2++wnxn+b (2.2)

onde, 𝒙n é o vetor de entrada, 𝒘n é o vetor de pesos e b é o bias. Escolhida uma função de ativação, a saída do neurônio é dada por

y =𝒩(𝒙;(𝒘,b)) (2.3)
:=f(z)=f(𝒘𝒙+b) (2.4)
Refer to caption
Figura 2.1: Esquema de um perceptron: unidade de processamento.

O treinamento (calibração) consiste em determinar os parâmetros (𝒘,b) de forma que o neurônio forneça as saídas y esperadas com base em um critério predeterminado.

Uma das vantagens deste modelo de neurônio é sua generalidade, i.e. pode ser aplicado a diferentes problemas. Na sequência, vamos aplicá-lo na resolução de um problema de classificação e noutro de regressão.

2.1.1 Um problema de classificação

Vamos desenvolver um perceptron que emule a operação (e-lógico). I.e, receba como entrada dois valores lógicos A1 e A2 (V, verdadeiro ou F, falso) e forneça como saída o valor lógico R=A1A2. Segue a tabela verdade do :

A1 A2 R
V V V
V F F
F V F
F F F

Modelo

Nosso modelo de neurônio será um perceptron com duas entradas 𝒙{1,1}2 e a função sinal

f(z)=sign(z)={1,z>00,z=01,z<0 (2.5)

como função de ativação, i.e.

y =𝒩(𝒙;(𝒘,b)), (2.6)
=sign(𝒘𝒙+b), (2.7)

onde 𝒘2 e b são parâmetros a determinar.

Pré-processamento

Uma vez que nosso modelo recebe valores 𝒙{1,1}2 e retorna y{1,1}, precisamos (pre)processar os dados do problema de forma a utilizá-los. Uma forma, é assumir que todo valor negativo está associado ao valor lógico F (falso) e positivo ao valor lógico V (verdadeiro). Desta forma, os dados podem ser interpretados como na tabela abaixo.

x1 x2 y
1 1 1
1 -1 -1
-1 1 -1
-1 -1 -1

Treinamento

Agora, nos falta treinar nosso neurônio para fornecer o valor de y esperado para cada dada entrada 𝒙. Isso consiste em um método para escolhermos os parâmetros (𝒘,b) que sejam adequados para esta tarefa. Vamos explorar mais sobre isso na sequência do texto e, aqui, apenas escolhemos

𝒘=(1,1), (2.8)
b=1. (2.9)

Com isso, nosso perceptron é

𝒩(𝒙)=sign(x1+x21) (2.10)

Verifique que ele satisfaz a tabela verdade acima!

Implementação

Código 1: perceptron.py
1import torch
2
3# modelo
4class Perceptron(torch.nn.Module):
5    def __init__(self):
6        super().__init__()
7        self.linear = torch.nn.Linear(2,1)
8
9    def forward(self, x):
10        z =  self.linear(x)
11        y = torch.sign(z)
12        return y
13
14model = Perceptron()
15W = torch.Tensor([[1., 1.]])
16b = torch.Tensor([-1.])
17with torch.no_grad():
18    model.linear.weight = torch.nn.Parameter(W)
19    model.linear.bias = torch.nn.Parameter(b)
20
21# dados de entrada
22X = torch.tensor([[1., 1.],
23                  [1., -1.],
24                  [-1., 1.],
25                  [-1., -1.]])
26
27print(f"\nDados de entrada\n{X}")
28
29
30# forward (aplicação do modelo)
31y = model(X)
32
33print(f"Valores estimados\n{y}")

Interpretação geométrica

Empregamos o seguinte modelo de neurônio

𝒩(𝒙;(𝒘,b))=sign(w1x1+w2x2+b) (2.11)

Observamos que

w1x1+w2x2+b=0 (2.12)

corresponde à equação geral de uma reta no plano τ:x1×x2. Esta reta divide o plano em dois semiplanos

τ+={𝒙2:w1x1+w2x2+b>0} (2.13)
τ={𝒙2:w1x1+w2x2+b<0} (2.14)

O primeiro está na direção do vetor normal à reta 𝒏=(w1,w2) e o segundo no sentido oposto. Com isso, o problema de treinar nosso neurônio para o problema de classificação consiste em encontrar a reta

w1x1+w2x2+b=0 (2.15)

de forma que o ponto (1,1) esteja no semiplano positivo τ+ e os demais pontos no semiplano negativo τ. Consultamos a Figura 2.2.

Refer to caption
Figura 2.2: Interpretação geométrica do perceptron aplicado ao problema de classificação relacionado à operação lógica (e-lógico).

Algoritmo de treinamento: perceptron

O algoritmo de treinamento perceptron permite calibrar os pesos de um neurônio para fazer a classificação de dados linearmente separáveis. Trata-se de um algoritmo para o treinamento supervisionado de um neurônio, i.e. a calibração dos pesos é feita com base em um dado conjunto de amostras de treinamento.

Seja dado um conjunto de treinamento {𝒙(s),y(s)}s=1ns, onde ns é o número de amostras. O algoritmo consiste no seguinte:

  1. 1.

    𝒘𝟎, b0.

  2. 2.

    Para e1,,ne:

    1. (a)

      Para s1,,ns:

      1. i.

        Se y(s)𝒩(𝒙(s))0:

        1. A.

          𝒘𝒘+y(s)𝒙(s)

        2. B.

          bb+y(s)

onde, ne é um dado número de épocas11endnote: 1Número de vezes que as amostrar serão percorridas para realizar a correção dos pesos..

Código 2: perceptron_train.py
1import torch
2
3# modelo
4
5class Perceptron(torch.nn.Module):
6    def __init__(self):
7        super().__init__()
8        self.linear = torch.nn.Linear(2,1)
9
10    def forward(self, x):
11        z =  self.linear(x)
12        y = torch.sign(z)
13        return y
14
15model = Perceptron()
16with torch.no_grad():
17    W = model.linear.weight
18    b = model.linear.bias
19
20# dados de treinamento
21X_train = torch.tensor([[1., 1.],
22                  [1., -1.],
23                  [-1., 1.],
24                  [-1., -1.]])
25y_train = torch.tensor([1., -1., -1., -1.]).reshape(-1,1)
26
27## número de amostras
28ns = y_train.size(0)
29
30print("\nDados de treinamento")
31print("X_train =")
32print(X_train)
33print("y_train = ")
34print(y_train)
35
36# treinamento
37
38## num max épocas
39nepochs = 100
40
41for epoch in range(nepochs):
42
43    # update
44    not_updated = True
45    for s in range(ns):
46        y_est = model(X_train[s:s+1,:])
47        if (y_est*y_train[s] <= 0.):
48            with torch.no_grad():
49                W += y_train[s]*X_train[s,:]
50                b += y_train[s]
51                not_updated = False
52
53    if (not_updated):
54        print('Training ended.')
55        break
56
57
58# verificação
59print(f'W =\n{W}')
60print(f'b =\n{b}')
61y = model(X_train)
62print(f'y =\n{y}')

2.1.2 Problema de regressão

Vamos treinar um perceptron para resolver o problema de regressão linear para os seguintes dados

s x(s) y(s)
1 0.5 1.2
2 1.0 2.1
3 1.5 2.6
4 2.0 3.6

Modelo

Vamos determinar o perceptron22endnote: 2Escolhendo f(z)=z como função de ativação.

y~=𝒩(x;(w,b))=wx+b (2.16)

que melhor se ajusta a este conjunto de dados {(x(s),y(s))}s=1ns, ns=4.

Treinamento

A ideia é que o perceptron seja tal que minimize o erro quadrático médio (MSE, do inglês, Mean Squared Error), i.e.

minw,b1nss=1ns(y~(s)y(s))2 (2.17)

Vamos denotar a função erro (em inglês, loss function) por

ε(w,b) :=1nss=1ns(y~(s)y(s))2 (2.18)
=1nss=1ns(wx(s)+by(s))2 (2.19)

Observamos que o problema (2.17) é equivalente a um problema linear de mínimos quadrados. A solução é obtida resolvendo-se a equação normal33endnote: 3Consulte o Exercício 2.1.4.

MTM𝒄=MT𝒚, (2.20)

onde 𝒄=(w,p) é o vetor dos parâmetros a determinar e M é a matriz ns×2 dada por

M=[𝒙𝟏] (2.21)

Implementação

Código 3: perceptron_mq.py
1import torch
2
3# modelo
4class Perceptron(torch.nn.Module):
5    def __init__(self):
6        super().__init__()
7        self.linear = torch.nn.Linear(1,1)
8
9    def forward(self, x):
10        z =  self.linear(x)
11        return z
12
13model = Perceptron()
14with torch.no_grad():
15    W = model.linear.weight
16    b = model.linear.bias
17
18# dados de treinamento
19X_train = torch.tensor([0.5,
20                        1.0,
21                        1.5,
22                        2.0]).reshape(-1,1)
23y_train = torch.tensor([1.2,
24                        2.1,
25                        2.6,
26                        3.6]).reshape(-1,1)
27
28## número de amostras
29ns = y_train.size(0)
30
31print("\nDados de treinamento")
32print("X_train =")
33print(X_train)
34print("y_train = ")
35print(y_train)
36
37# treinamento
38
39## matriz
40M = torch.hstack((X_train,
41                  torch.ones((ns,1))))
42## solucão M.Q.
43c = torch.linalg.lstsq(M, y_train)[0]
44with torch.no_grad():
45    W = c[0]
46    b = c[1]
47
48# verificação
49print(f'W =\n{W}')
50print(f'b =\n{b}')
51y = model(X_train)
52print(f'y =\n{y}')

Resultado

Nosso perceptron corresponde ao modelo

𝒩(x;(w,b))=wx+b (2.22)

com pesos treinados w=1.54 e b=0.45. Ele corresponde à reta que melhor se ajusta ao conjunto de dados de {x(s),y(s)}s=14 dado na tabela acima. Consultamos a Figura 2.3.

Refer to caption
Figura 2.3: Interpretação geométrica do perceptron aplicado ao problema de regressão linear.

2.1.3 Exercícios

E. 2.1.1.

Crie um perceptron que emule a operação lógica do (ou-lógico).

A1 A2 A1A2
V V V
V F V
F V V
F F F
E. 2.1.2.

Busque criar um perceptron que emule a operação lógica do xor.

A1 A2 A1 xor A2
V V F
V F V
F V V
F F F

É possível? Justifique sua resposta.

E. 2.1.3.

Assumindo o modelo de neurônio (2.16), mostre que (2.18) é função convexa.

Resposta.

Dica: verifique que sua matriz hessiana é positiva definida.

E. 2.1.4.

Mostre que a solução do problema (2.17) é dada por (2.20).

Resposta.
E. 2.1.5.

Crie um perceptron com função de ativação f(x)=tanh(x) que melhor se ajuste ao seguinte conjunto de dados:

s x(s) y(s)
1 -1,0 -0,8
2 -0,7 -0,7
3 -0,3 -0,5
4 0,0 -0,4
5 0,2 -0,2
6 0,5 0,0
7 1,0 0,3

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!