Скорость обучения нейронной сети, ошибка деления, если слишком большая, не улучшение, если слишком маленькая

После написания простой нейронной сети я столкнулся с такой проблемой со скоростью обучения (я думаю, это вызвано lr). Для скорости обучения, меньшей или равной 10e-6, я быстро получаю ошибку "деление с плавающей запятой на ноль" - я предполагаю, что веса обновляются быстро, когда я пытался проверить минимальное значение для y_pred, я получил значение, равное 0 до 5 итераций (возможно, тогда мой код неверен). С другой стороны, как только я поставил скорость обучения равной 10e-7, ошибка с делением исчезла, однако теперь нет роста точности, а также потери меняются очень медленно, начиная с 3, 4 итерации.

Я попытался разделить наборы данных на обучающие / проверочные, также без разделения, но результат все еще очень похож. Найдите мой код ниже и сообщите, если я где-то ошибся или возникла другая проблема:

class Net:

def __init__(self, X, y, neurons, n_epochs):

    self.X = X
    self.y = y
    self.neurons = neurons
    self.n_epochs = n_epochs
    self.learning_rate = 10e-6      

def train_val_split(self, X, y, val_size):
    perm = list(np.random.permutation(X.shape[0]))
    split_index = int(X.shape[0] * val_size)
    val_idxs = perm[:split_index]
    train_idxs = perm[split_index:]

    self.X_train = X[train_idxs]
    self.y_train = y[train_idxs]
    self.X_val = X[val_idxs]
    self.y_val = y[val_idxs]    

def weights(self):
    np.random.seed(42)
    self.weights = np.random.rand(self.neurons, 1)
    self.bias = np.random.rand(1)

def sigmoid(self, x):
    return 1/(1 + np.exp(-x.astype('float64')))

def sigmoid_deriv(self, x):
    return self.sigmoid(x) * (1 - self.sigmoid(x))

def loss(self, y_pred, y):
    nsample = len(y)
    loss = -1/nsample * (np.sum(np.multiply(np.log(y_pred), y) + np.multiply((1 - y), np.log(1 - y_pred))))
    return loss

def forward_step(self, X, y):

    self.X_forward = X
    self.y_forward = y
    layer = self.X_forward.dot(self.weights) + self.bias
    y_pred = self.sigmoid(layer)
    loss = self.loss(y_pred, self.y_forward)
    return y_pred, loss

def backpropagation_step(self, y_pred):
    dloss_dy_pred = - (np.divide(self.y_forward, y_pred) - np.divide((1 - self.y_forward), (1 - y_pred)))
    dy_pred_dlayer = self.sigmoid_deriv(y_pred)
    dloss_dlayer = dloss_dy_pred.dot(dy_pred_dlayer)
    X_T = self.X_forward.T
    self.weights = self.weights - self.learning_rate * np.dot(X_T, dloss_dlayer)   
    self.bias = self.bias - self.learning_rate * np.sum(dloss_dlayer, axis=0)

def predict(self, X):
    val_layer = X.dot(self.weights) + self.bias
    val_y_pred = self.sigmoid(val_layer)
    return val_y_pred

def train(self):
    self.acc_sum = []
    self.loss_sum = []
    self.weights()

    self.train_val_split(self.X, self.y, .1)  

    for i in range(self.n_epochs):
        self.corr = []   
        y_pred, loss = self.forward_step(self.X_train, self.y_train)
        self.backpropagation_step(y_pred)
        self.loss_sum.append(loss)

        self.pred = self.predict(self.X_val)
        for j in range(len(self.pred)):
            if np.round(self.pred)[j] == self.y_val[j]:
                self.corr.append(1)

        self.acc = str(np.round(np.sum(self.corr) / len(self.y_val)  * 100, 2)) + "%"
        if i % 10 == 0:
            print("Epoch:", i, ", loss equal to:", loss, ". Accuracy: ", self.acc)   

После 100 итераций я получил, например:

Epoch: 0 , loss equal to: 1029.0477736265436 . Accuracy:  69.12%
Epoch: 10 , loss equal to: 405.3760319047782 . Accuracy:  69.12%
Epoch: 20 , loss equal to: 402.94596804012343 . Accuracy:  69.12%
Epoch: 30 , loss equal to: 401.5770287877523 . Accuracy:  69.12%
Epoch: 40 , loss equal to: 400.77963764085007 . Accuracy:  69.12%
Epoch: 50 , loss equal to: 400.3190949247666 . Accuracy:  69.12%
Epoch: 60 , loss equal to: 400.05193343787334 . Accuracy:  69.12%
Epoch: 70 , loss equal to: 399.8951929684591 . Accuracy:  69.12%
Epoch: 80 , loss equal to: 399.80154758461305 . Accuracy:  69.12%
Epoch: 90 , loss equal to: 399.74405181305343 . Accuracy:  69.12%

или:

Epoch: 0 , loss equal to: 739.883461574974 . Accuracy:  92.65%
Epoch: 10 , loss equal to: 405.4500566401914 . Accuracy:  73.53%
Epoch: 20 , loss equal to: 401.95904155878173 . Accuracy:  70.59%
Epoch: 30 , loss equal to: 401.3946991504089 . Accuracy:  70.59%
Epoch: 40 , loss equal to: 401.09437273541636 . Accuracy:  70.59%

Я потратил несколько часов, чтобы найти решение, но не нашел. Я пробовал также библиотеки:

from fraction import Fraction
from decimal import *

чтобы справиться с меньшими темпами обучения, но они требуют числа в качестве аргумента, а не массива, поэтому я тоже потерпел неудачу.

Буду рад любым советам,

Заранее спасибо!

0 ответов

Другие вопросы по тегам