Нейронная сеть с нуля (отладка)

#python-3.x #neural-network

#python-3.x #нейронная сеть

Вопрос:

Я пытался создать базовую нейронную сеть с нуля на Python. Это то, что я придумал.

Функции активации и производные

 def sigmoid(Z):
    return 1 / (1   np.exp(-Z))

def relu(Z):
    return np.maximum(0, Z)

# derivatives
def d_relu(Z):
    return (Z > 0) * 1

def d_sigmoid(Z):
    return sigmoid(Z) * (1 - sigmoid(Z))
  

Инициализация параметров

 def initialize_params(layer_dims):
    W, b = {}, {}
    L = len(layer_dims)
    
    for l in range(1, L):
        W[l] = np.random.randn(layer_dims[l], layer_dims[l - 1]) * 0.01
        b[l] = np.zeros((layer_dims[l], 1))
    
    return W, b
  

Прямое распространение

 def forward_prop(X, W, b, activation_func='relu'):
    Z = np.dot(W, X)   b
    
    if activation_func == 'relu':
        A = relu(Z)
    elif activation_func == 'sigmoid':
        A = sigmoid(Z)
    elif activation_func == 'tanh':
        A = tanh(Z)
        
    return Z, A
  

Стоимость

 def compute_cost(A_L, Y):
    m = Y.shape[1]
    cost = -np.sum(Y * np.log(A_L)   (1 - Y) * np.log(1 - A_L), axis=1, keepdims=True) / m
    
    return np.squeeze(cost)
  

Обратное распространение

 def backward_prop(dA, A_prev, Z, W, activation_func):
    if activation_func == 'relu':
        dZ = dA * d_relu(Z)
    elif activation_func == 'sigmoid':
        dZ = dA * d_sigmoid(Z)
    elif activation_func == 'tanh':
        dZ = dA * d_tanh(Z)
    
    m = A_prev.shape[1]
    
    dW = np.dot(dZ, A_prev.T) / m
    db = np.sum(dZ, axis=1, keepdims=True) / m
    
    dA_prev = np.dot(W.T, dZ)
    
    return dA_prev, dW, db
  

Обновить параметры

 def update_params(W, b, dW, db, learning_rate):
    L = len(W)
    for l in range(1, L):
        W[l] -= learning_rate * dW[l]
        b[l] -= learning_rate * db[l]
        
    return W, b
  

Neural Network Class

 class LLayerNeuralNet:
    def __init__(self, layer_dims, activation_funcs):
        self.layer_dims = layer_dims
        self.activation_funcs = activation_funcs
        self.L = len(layer_dims)
        
        # initalize W and b
        self.W, self.b = initialize_params(layer_dims)
        
    def train(self, X, Y, num_iter=1000, learning_rate=0.01, print_costs=True):
        self.Z, self.A = {}, {}
        self.dZ, self.dA, self.dW, self.db = {}, {}, {}, {}
        self.costs = []
        self.learning_rate = learning_rate
        self.A[0] = X
        
        for i in range(1, num_iter 1):
            # forward propagation
            for l in range(1, self.L):
                self.Z[l], self.A[l] = forward_prop(self.A[l-1], self.W[l], self.b[l], self.activation_funcs[l])

            # compute cost
            if i % 100 == 0:
                cost = compute_cost(self.A[self.L-1], Y)
                self.costs.append(cost)
                if print_costs:
                    print('Cost after %d: %f' %(i, cost))

            # backward propagation
            self.dA[self.L-1] = - np.divide(Y, self.A[self.L-1])   np.divide(1 - Y, 1 - self.A[self.L-1])
            
            for l in reversed(range(1, self.L)):
                self.dA[l-1], self.dW[l], self.db[l] = backward_prop(self.dA[l], self.A[l-1], self.Z[l], self.W[l], self.activation_funcs[l])
            
            # update parameters
            for l in range(1, self.L):
                self.W[l] -= learning_rate * self.dW[l]
                self.b[l] -= learning_rate * self.db[l]
    
    def predict(X_pred):
        A_pred = {}
        A_pred[0] = X_pred
        for i in range(num_iter):
            for l in range(1, self.L 1):
                _, A_pred[l] = forward_prop(A_pred[l-1], self.W[l], self.b[l], self.activation_funcs[l])
        
        return (A_pred[self.L] > 0.5) * 1.0
  

Создание модели и ее обучение

 layer_dims = [12288, 20, 7, 5, 1]
funcs = {1:'relu', 2:'relu', 3:'relu', 4:'sigmoid'}
model = LLayerNeuralNet(layer_dims, funcs)
model.train(train_x, train_y, learning_rate=0.0075)
  

После запуска в течение 1000 эпох затраты составляют:

Стоимость после 100: 0.678129

Стоимость после 200: 0,667676

Стоимость после 300: 0.660471

Стоимость после 400: 0.655489

Стоимость после 500: 0,652033

Стоимость после 600: 0.649628

Стоимость после 700: 0.647949

Стоимость после 800: 0.646774

Стоимость после 900: 0.645949

Стоимость после 1000: 0.645369

Я думаю, что это неверно, потому что стоимость не сильно снижается. Есть ли способ проверить правильность моей реализации?

Комментарии:

1. Кроме того, как следует отлаживать что-то подобное?

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

3. Я не пытался решить какую-либо конкретную проблему. Я узнал о нейронных сетях из deeplearning.ai курс coursera. Я просто пытался создать свою собственную нейронную сеть, просто чтобы убедиться, что я понял теорию (задания по программированию были не такими уж хорошими). Я взял набор данных из последнего задания (классификатор cat против не-cat)

Ответ №1:

Хороший способ убедиться, что ваша реализация функциональна, — начать с более простой задачи, такой как тестирование вашей реализации с помощью XOR. Судя по всему, проблема может быть такой же простой, как увеличение количества параметров в сети. Передача значений из 12288 входных узлов в 20 скрытых узлов является значительным сокращением и может привести к потере информации, необходимой вашей модели для дальнейшего снижения стоимости.