Construindo e treinando um modelo de rede neural com python (iniciante)
Introdução
Neste artigo, vamos explorar como construir e treinar um modelo de rede neural simples usando Python. Utilizaremos bibliotecas populares como numpy
, pandas
, matplotlib
e sklearn
para manipulação e visualização de dados, além de implementar uma rede neural do zero. Vamos começar!
Configuração do Ambiente
Primeiro, vamos importar as bibliotecas necessárias e configurar o ambiente:
import pickle
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import sklearn.datasets as datasets
plt.rcParams['figure.figsize'] = [10, 6]
plt.style.use('dark_background')
Gerando e Visualizando os Dados
Vamos usar o sklearn
para gerar um conjunto de dados em forma de lua crescente e visualizá-lo:
x, y = datasets.make_moons(n_samples=500, noise=0.05)
print(f'{x.shape= }, {y.shape= }')
# Criando um DataFrame para visualização
df = pd.DataFrame({'x_1': x[:, 0], 'x_2': x[:, 1], 'y': y})# Contando os rótulos
unique = np.unique(y, return_counts=True)
for label, qt_label in zip(unique[0], unique[1]):
print(f'Label: {label}\t Counts: {qt_label= }')# Plotando os dados
plt.scatter(x[:, 0], x[:, 1], c=y, s=50, alpha=0.5, cmap='cool')
plt.show()
Implementando a Rede Neural
Agora, vamos implementar uma classe para nossa rede neural. Esta classe incluirá métodos para a inicialização dos pesos, a propagação para frente, a função de perda e a retropropagação.
class NnModel:
def __init__(self, x: np.ndarray, y: np.ndarray, hidden_neurons: int = 10, output_neurons: int = 2):
np.random.seed(8)
self.x = x
self.y = y
self.hidden_neurons = hidden_neurons
self.output_neurons = output_neurons
self.input_neurons = self.x.shape[1]
# Inicializando pesos e bias com Xavier Initialization
self.W1 = np.random.randn(self.input_neurons, self.hidden_neurons) / np.sqrt(self.input_neurons)
self.B1 = np.zeros((1, self.hidden_neurons))
self.W2 = np.random.randn(self.hidden_neurons, self.output_neurons) / np.sqrt(self.hidden_neurons)
self.B2 = np.zeros((1, self.output_neurons))
self.model_dict = {'W1': self.W1, 'B1': self.B1, 'W2': self.W2, 'B2': self.B2}
self.z1 = 0
self.f1 = 0
def forward(self, x: np.ndarray) -> np.ndarray:
self.z1 = x.dot(self.W1) + self.B1
self.f1 = np.tanh(self.z1)
z2 = self.f1.dot(self.W2) + self.B2
exp_values = np.exp(z2)
softmax = exp_values / np.sum(exp_values, axis=1, keepdims=True)
return softmax def loss(self, softmax):
predictions = np.zeros(self.y.shape[0])
for i, correct_index in enumerate(self.y):
predicted = softmax[i][correct_index]
predictions[i] = predicted
log_probs = -np.log(predictions)
return log_probs / self.y.shape[0]
def backpropagation(self, softmax: np.ndarray, learning_rate: float) -> None:
delta2 = np.copy(softmax)
delta2[range(self.x.shape[0]), self.y] -= 1
dW2 = (self.f1.T).dot(delta2)
dB2 = np.sum(delta2, axis=0, keepdims=True)
delta1 = delta2.dot(self.W2.T) * (1 - np.power(np.tanh(self.z1), 2))
dW1 = (self.x.T).dot(delta1)
dB1 = np.sum(delta1, axis=0, keepdims=True)
# Atualizando pesos e bias
self.W1 -= learning_rate * dW1
self.W2 -= learning_rate * dW2
self.B1 -= learning_rate * dB1
self.B2 -= learning_rate * dB2
def show_plot(self, predictions):
if self.x.shape[1] == 2:
plt.scatter(self.x[:, 0], self.x[:, 1], c=predictions, s=50, alpha=0.7, cmap='cool')
plt.show()
elif self.x.shape[1] == 3:
ax = plt.axes(projection='3d')
ax.scatter3D(self.x[:, 0], self.x[:, 1], self.x[:, 2], c=predictions, s=40, alpha=0.7, cmap='cool')
plt.show()
def fit(self, epochs: int, lr: float, show_plot: bool = False):
for epoch in range(epochs):
outputs = self.forward(self.x)
loss = self.loss(outputs)
self.backpropagation(outputs, lr)
predictions = np.argmax(outputs, axis=1)
correct = (predictions == self.y).sum()
accuracy = correct / self.y.shape[0]
self.show_plot(predictions)
if int((epoch + 1) % (epochs / 10)) == 0:
print(f'Epoch: {epoch + 1}/{epochs} - Loss: {loss.mean()} - Accuracy: {accuracy:.3f}')
if show_plot:
self.show_plot(predictions)
return predictions
Treinando o Modelo
Finalmente, vamos treinar nosso modelo com os parâmetros definidos:
hidden_neurons = 10
output_neurons = 2
learning_rate = 0.001
epochs = 100
model = NnModel(x, y, hidden_neurons=hidden_neurons, output_neurons=output_neurons)
result = model.fit(epochs, learning_rate)
Conclusão
Neste artigo, construímos e treinamos uma rede neural simples do zero usando Python. Exploramos a geração de dados, a visualização e a implementação de uma rede neural com propagação para frente, função de perda e retropropagação. Este é um ótimo ponto de partida para quem deseja entender os fundamentos das redes neurais e como implementá-las.
Segue o repositório com o código caso tenham alguma dúvida.