Breno

Implementação da famosa rede neural MLP

Quando estudamos redes neurais, um termo bastante difundido é o MLP. Ele significa o acrônimo para Multi-Layer Perceptron. Seria um Perceptron de Múltiplas Camadas.

Seguindo com o nosso estudo seria a junção de muitas camadas, que, assim, formam uma rede neural.

Implementemos de novo o neurônio.

class Neuron:
  def __init__(self, n_in):
    self.w = [random.uniform(-1, 1) for _ in range(n_in)]
    self.b = random.uniform(-1, 1)

  def __call__(self, x):
    return sum(wi * xi for wi, xi in zip(self.w, x), self.b)

Simples.

Os neurônios juntos formam uma camada, a próxima abstração. Implementemos.

class Layer:
  def __init__(self, n_in, n_res):
    self.neurons = [Neuron(n_in) for _ in range(n_res)]

  def __call__(self, x):
    results = [n(x) for n in self.neurons]
    return results

Muito simples. Depois podemos discutir alguns detalhes, mas o conceito seria esse.

O neurônio com os parâmetros que realizam a soma ponderada e a camada apenas como uma lista de neurônios e assim, somas ponderadas se realizam nela.

Bom, com esses dois conceitos, conseguimos agora implementar a rede neural MLP.

Seguindo a mesma lógica e pela estrutura de uma rede neural, ela vai então agora usar o conceito de camada. Vejamos o código, depois discutimos.

class MLP:
  def __init__(self, n_in, n_res):
    sz = [n_in] + n_res
    self.layers = [Layer(sz[i], sz[i+1]) for i in range(n_res)]

  def __call__(self, x):
    for layer in self.layers:
      x = layer(x)
    return x

Bom, alguns detalhes específicos da MLP.

Observem que a MLP seria formada por camadas, então a entrada continua a mesma, para o nosso exemplo x como [2.0, 4.0], então o n_in seria ainda o 2. Mas, agora, distinto da camada, que recebia apenas um número, que significava número de neurônios, agora temos dentro da MLP as camadas. Como a rede possui uma estrutura sequencial, a composição de camadas se dá com o resultado como entrada para outra, excepto para a primeira camada, que possui como entrada o dado de entrada em si.

Então, desse jeito, a MLP recebe uma lista de números, que indicam quantos neurônios tem em cada camada.

Vejamos o exemplo.

x = [2.0, 3.0]
n = MLP(2, [2, 4, 1])
n(x)

No exemplo, temos o x com tamanho 2, então, o primeiro parâmetro instanciando a MLP seria 2. O segundo parâmetro, como observamos, seria uma lista.

A lista [2, 4, 1] indica que a rede neural possui 3 camadas. A primeira com 2 neurônios, a segunda com 4 neurônios e a última camada com 1 neurônio. O resultado final então seria apenas um número.

Na implementação, cada camada se cria considerando o par. Olhem que criamos uma lista sz e iteramos por ela na criação de cada Layer para a obtenção de self.layers. Itera-se com os pares na ordem. Então a primeira camada possui entrada 2, tamanho da entrada de dados e resposta 2 com os 2 neurônios. A segunda camada recebe então o resultado 2 e responde com 4 neurônios. A terceira camada, por fim, recebe 4 números, cada um dos 4 neurônios, e responde com um número, do seu único neurônio.

E assim tem-se a rede neural de modo simples.