[Python] Hey guys,trying to buid a Convolutional Neural Network using python from scratch

Discussão em 'Python' iniciado por Stack, Fevereiro 14, 2025.

  1. Stack

    Stack Membro Participativo

    import numpy as np
    import matplotlib.pyplot as plt

    def OneHot(y):
    return np.eye(np.max(y.astype(int)) + 1)[y.astype(int)]

    def CE(Y, Y_hat):
    epsilon = 1e-10
    Y_hat = np.clip(Y_hat, epsilon, 1 - epsilon)
    return -np.mean(np.sum(Y * np.log(Y_hat), axis=0))

    def CE_prime(Y, Y_hat):
    return Y_hat - Y

    class Dense:
    def __init__(self, n_inputs, n_outputs):
    self.weights = np.random.randn(n_outputs, n_inputs) * 0.01
    self.biases = np.zeros((n_outputs, 1))

    def forward(self, X):
    self.X = X
    self.Z = np.dot(self.weights, X) + self.biases
    return self.Z

    def backward(self, grad, lr):
    dZ = grad
    dW = np.dot(dZ, self.X.T) / self.X.shape[1]
    db = np.sum(dZ, axis=1, keepdims=True) / self.X.shape[1]
    dX = np.dot(self.weights.T, dZ)

    self.weights -= lr * dW
    self.biases -= lr * db

    return dX

    class Conv2D:
    def __init__(self, kernel_size, input_channels, input_shape):
    self.kernel_size = kernel_size
    self.input_channels = input_channels
    self.input_shape = input_shape
    self.weights = np.random.randn(input_channels, kernel_size, kernel_size) * 0.01
    self.biases = np.zeros(1)

    def forward(self, X):
    self.X = X
    batch_size,_, H, W = X.shape
    output_H = H - self.kernel_size + 1
    output_W = W - self.kernel_size + 1
    self.Z = np.zeros((batch_size,output_H, output_W))

    for b in range(batch_size):
    for i in range(output_H):
    for j in range(output_W):
    patch = X[b, :, i:i+self.kernel_size, j:j+self.kernel_size]
    self.Z[b, i, j] = np.sum(self.weights * patch) + self.biases
    return self.Z

    def backward(self, grad, lr):
    batch_size, output_H, output_W = grad.shape
    _, _, H, W = self.X.shape
    kernel_size = self.kernel_size

    dW = np.zeros_like(self.weights)
    db = np.sum(grad) / batch_size
    dX = np.zeros_like(self.X)

    for b in range(batch_size):
    for i in range(output_H):
    for j in range(output_W):
    patch = self.X[b, :, i:i+kernel_size, j:j+kernel_size]
    dW += grad[b, i, j] * patch / batch_size
    dX[b, :, i:i+kernel_size, j:j+kernel_size] += self.weights * grad[b, i, j]

    self.weights -= lr * dW
    self.biases -= lr * db

    return dX

    class MaxPool2D:
    def __init__(self, pool_size):
    self.pool_size = pool_size

    def forward(self, X):
    self.X = X
    batch_size, H, W = X.shape
    output_H = H // self.pool_size
    output_W = W // self.pool_size
    self.Z = np.zeros((batch_size, output_H, output_W))
    self.max_indices = []

    for b in range(batch_size):
    for i in range(output_H):
    for j in range(output_W):
    h_start = i * self.pool_size
    h_end = h_start + self.pool_size
    w_start = j * self.pool_size
    w_end = w_start + self.pool_size
    patch = X[b, h_start:h_end, w_start:w_end]
    max_val = np.max(patch)
    self.Z[b, i, j] = max_val
    max_idx = np.unravel_index(np.argmax(patch), patch.shape)
    self.max_indices.append((b, h_start + max_idx[0], w_start + max_idx[1]))

    return self.Z

    def backward(self, grad,lr):
    dX = np.zeros_like(self.X)
    grad_flat = grad.flatten()
    for idx, (b, h, w) in enumerate(self.max_indices):
    dX[b, h, w] += grad_flat[idx]
    return dX

    class Flatten:
    def forward(self, X):
    self.input_shape = X.shape
    batch_size = X.shape[0]
    return X.reshape(batch_size, -1).T

    def backward(self, grad, lr):
    return grad.T.reshape(self.input_shape)

    class Relu:
    def forward(self, X):
    self.X = X
    return np.maximum(X, 0)

    def backward(self, grad, lr):
    return grad * (self.X > 0)

    class Softmax:
    def forward(self, X):
    exp_X = np.exp(X - np.max(X, axis=0, keepdims=True))
    self.output = exp_X / np.sum(exp_X, axis=0, keepdims=True)
    return self.output

    def backward(self, grad, lr):
    return grad

    class NeuralNetwork:
    def __init__(self, layers=[]):
    self.layers = layers

    def add(self, layer):
    self.layers.append(layer)

    def train(self, epochs, X, Y, lr, batch_size=32):
    num_samples = X.shape[1]
    for epoch in range(epochs):
    permutation = np.random.permutation(num_samples)
    X_shuffled = X[:, permutation]
    Y_shuffled = Y[:, permutation]

    for i in range(0, num_samples, batch_size):
    X_batch = X_shuffled[:, i:i+batch_size]
    Y_batch = Y_shuffled[:, i:i+batch_size]

    Y_hat = X_batch
    for layer in self.layers:
    Y_hat = layer.forward(Y_hat)

    loss = CE(Y_batch, Y_hat)
    grad = CE_prime(Y_batch, Y_hat)

    for layer in reversed(self.layers):
    grad = layer.backward(grad, lr)

    if epoch % 1 == 0:
    print(f"Epoch [{epoch}/{epochs}] Loss: {loss:.5f}")

    def score(self, X, Y):
    Y_hat = self.predict(X)
    Y_true = np.argmax(Y, axis=0)
    return np.mean(Y_hat == Y_true) * 100

    def predict(self, X):
    Y_hat = X
    for layer in self.layers:
    Y_hat = layer.forward(Y_hat)
    return np.argmax(Y_hat, axis=0)


    from sklearn.model_selection import train_test_split
    from sklearn.datasets import load_digits
    import numpy as np

    digits = load_digits()
    X = digits.images
    y = digits.target

    X = X

    X = X.reshape(-1, 1, 8, 8)

    Y = OneHot(y)

    X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)
    Y_train, Y_test = Y_train.T , Y_test.T

    nn = NeuralNetwork()
    nn.add(Conv2D(kernel_size=3, input_channels=1, input_shape=(1, 8, 8)))
    nn.add(Relu())
    nn.add(MaxPool2D(pool_size=2))
    nn.add(Flatten())
    nn.add(Dense(9, 24))
    nn.add(Relu())
    nn.add(Dense(24, 10))
    nn.add(Softmax())

    epochs = 5
    learning_rate = 5
    nn.train(epochs, X_train, Y_train, learning_rate, batch_size=1)

    accuracy = round(nn.score(X_test, Y_test),2)
    print(accuracy)


    So this converges really slow with 0.01 and 0.1 learning rate,also i think loss works well and it converges to almost zero.But accuracy is around 10%.Normal Dense layer neural network works fine(like iris dataset).I asked AI's like chatgpt, deepseek and claude but they just make it worse.What should i do?

    Continue reading...

Compartilhe esta Página