Neurônios juntos formam uma camada
Agora já se sabe como se constitui um neurônio. Implementemos de novo.
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)
E já se sabe como se usa esse neurônio, que vai receber uma entrada, um vetor de números que representa algum dado, e vai dar como resultado um número.
x = [2.0, 4.0] # uma entrada de exemplo.
n = Neuron(2) # instanciação de um neurônio que espera uma entrada com dois números.
n(x) # quando se usa o neurônio, passa o exemplo e a resposta será um número.
A resposta do neurônio, como já vimos, será simplesmente uma soma ponderada.
As redes neurais usam esse neurônio, seja lá qual seja a rede a que se refira, de uma rede convolucional ao ChatGPT, ou os agentes como Codex. Esse é o princípio básico: simples neurônio que realiza soma ponderada.
Bom, outro conceito das redes neurais são as camadas. Os neurônios podem ser organizados juntos e compõem uma camada.
Seria a instanciação de mais de um neurônio e a resposta da camada seria do tamanho da quantidade neurônio que existe na camada.
Um neurônio retorna um número.
Uma camada com dois neurônios retorna dois números.
Uma camada com três neurônios retorna três números.
Simples assim.
Então, a implementação da camada consideraria ainda o tamanho da entrada e, além disso, a quantidade de neurônios para formar essa camada.
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
Bom, simples, a camada, como podemos observar no código considera a entrada em termos do número de elementos do vetor e o número de respostas que ela vai dar, que seria basicamente o número de neurônios, cada neurônio contribuindo com uma resposta, como vimos.
Para o método que é ativado quando se usa a camada, temos que cada neurônio é usado e o resultado é uma lista com as respostas, cada uma de um neurônio.
Vejamos então como seria o uso da camada.
x = [2.0, 4.0] # exemplo de entrada com dois elementos.
l = Layer(2, 4) # criação da camada que espera exemplo com 2 elementos e que possui 4 neurônios.
l(x) # uso do neurônio que ativa o método __call__ e que calcula a resposta de cada neurônio e retorna a lista com as respostas.
Percebemos que tanto o neurônio quanto a camada processam a entrada e fornecem um número ou uma lista de números. Eles estão processando os dados e gerando uma outra representação.
Quando se está treinando as redes, a ideia é que se encontre uma representação que mapeie a entrada para um resultado desejado. Isso seria o aprendizado supervisionado.
Mas, foquemos apenas no mecanismo básico.
O importante agora seria entender o neurônio artificial que realiza soma ponderada com do número do viés e, agora, como vimos aqui, a camada, que seria apenas mais de um neurônio juntos.