Почему мое обратное распространение не работает?(Попытка кодирования нейронной сети с 2 слоями с нуля для распознавания цифр) - PullRequest
0 голосов
/ 11 июня 2018

Моя проблема в том, что мой NN не тренируется, и я не могу понять, почему.Кто-нибудь может помочь?Вот мой код, я могу описать больше, если вы чего-то не понимаете.Спасибо !

Итак, прежде всего, я импортирую базу данных распознавания цифр и разделяю ее для обучения и тестирования.

import numpy as np
import matplotlib.pyplot as plt

from sklearn.datasets import load_digits
digits = load_digits()
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(digits.data, digits.target, test_size=0.25, random_state=0)

Я хочу, чтобы мои метки были векторами размера 10, здесь мойметки - это просто цифра, которую представляет изображение.Поэтому я должен выполнить преобразование, чтобы моя матрица меток имела «1» в каждом столбце в координате, соответствующей объекту.Если элемент X_1 равен «3», то во 2-й координате столбца 1 матрицы будет «1», а все остальные координаты будут «0».

y_train1 = np.zeros((10,y_train.shape[0]))

  for i in range(0,y_train.shape[0]):
     y_train1[ y_train[i]  , i ] = 1    

x_train1 = np.transpose(x_train)

Затем я создаю активациюфункции:

def sigmoid(Z):

   A = 1/(1+np.exp(-Z))
   cache = Z

   return A, cache

def relu(Z):

   A = np.maximum(0,Z)

   assert(A.shape == Z.shape)

   cache = Z 
   return A, cache

Функция, которая инициализирует параметры с хорошими размерами:

def init (n_x, n_h, n_y):

   ##Initialisation aléatoire des poids et biais pour un réseau à 1 couche cachée##
   W1 = np.random.randn(n_h,n_x)*0.01
   b1 = np.zeros((n_h,1))
   W2 = np.random.randn(n_y,n_h)*0.01
   b2 = np.zeros((n_y,1))

   assert(W1.shape == (n_h, n_x))
   assert(b1.shape == (n_h, 1))
   assert(W2.shape == (n_y, n_h))
   assert(b2.shape == (n_y, 1))


   parameters = {"W1": W1,
              "b1": b1,
              "W2": W2,
              "b2": b2}

   return parameters

функции для линейной активации вперед:

def propa_avant(A,W,b):
   Z = np.dot(W,A) + b 
   assert(Z.shape == (W.shape[0], A.shape[1]))
   cache = (A,W,b)

   return Z, cache

def propa_avant_activ(A_prev, W, b, activation): 

   if activation =="sigmoid" : 
       Z, linear_cache = propa_avant(A_prev,W,b)
       A, activation_cache = sigmoid(Z)

   if activation =="relu":
       Z, linear_cache = propa_avant(A_prev,W,b)
       A, activation_cache = relu(Z)

   assert (A.shape == (W.shape[0], A_prev.shape[1]))

   cache = (linear_cache, activation_cache)

   return A, cache

Стоимость перекрестной энтропиифункция:

def fonction_cout(AL,Y): 

   m = Y.shape[1]
   cost = (-1/m)*np.sum(Y*np.log(AL)+(1-Y)*np.log(1-AL))

   cost = np.squeeze(cost)      
   assert(cost.shape == ())

   return cost

Производные функций активации:

def relu_backward(dA, cache):

   Z = cache
   dZ = np.array(dA, copy=True) 


   dZ[Z <= 0] = 0

   assert (dZ.shape == Z.shape)

   return dZ

def sigmoid_backward(dA, cache):

   Z = cache

   s = 1/(1+np.exp(-Z))
   dZ = dA * s * (1-s)

   assert (dZ.shape == Z.shape)

   return dZ

Функции для линейной обратной активации:

def propa_arriere(dZ, cache):


   A_prev, W, b = cache
   m = A_prev.shape[1]


   dW = (1/2)*np.dot(dZ,A_prev.T)
   db = (1/2)*np.sum(dZ, axis=1, keepdims=True)
   dA_prev = np.dot(W.T,dZ)


   assert (dA_prev.shape == A_prev.shape)
   assert (dW.shape == W.shape)
   assert (db.shape == b.shape)

   return dA_prev, dW, db

def propa_arriere_activ(dA, cache, activation):

   linear_cache, activation_cache = cache

   if activation == "relu":

      dZ = relu_backward(dA, activation_cache)
      dA_prev, dW, db = propa_arriere(dZ, linear_cache)


   elif activation == "sigmoid":

      dZ = sigmoid_backward(dA, activation_cache)
      dA_prev, dW, db = propa_arriere(dZ, linear_cache)


   return dA_prev, dW, db

Функция для обновления параметров:

def update_parameters(parameters, grads, learning_rate):


   L = len(parameters) // 2 


   for i in reversed(range(1, L-1)): 
       parameters["W"+str(i)]=parameters["W"+str(i)] - learning_rate*grads["W"+str(i)]
       parameters["b"+str(i)]=parameters["b"+str(i)] - learning_rate*grads["b"+str(i)]
       parameters["A"+str(i)]=parameters["A"+str(i)] - learning_rate*grads["A"+str(i)]




   return parameters

Функция нейронной сети:

def two_layer_model(X, Y, layers_dims, learning_rate = 0.05, num_iterations = 2000, print_cost=False):



   grads = {}
   costs = []                              # to keep track of the cost
   m = X.shape[1]                           # number of examples
   (n_x, n_h, n_y) = layers_dims


   parameters = init(n_x, n_h, n_y)



   W1 = parameters["W1"]
   b1 = parameters["b1"]
   W2 = parameters["W2"]
   b2 = parameters["b2"]



   for i in range(0, num_iterations):


       A1, cache1 = propa_avant_activ(X, W1, b1, activation = "relu")
       A2, cache2 = propa_avant_activ(A1, W2, b2, activation = "sigmoid")



       cost = fonction_cout(A2, Y)



       dA2 = (1/m)* (- (np.divide(Y, A2) - np.divide(1 - Y, 1 - A2)))


       dA1, dW2, db2 = propa_arriere_activ(dA2, cache2, activation="sigmoid")
       dA0, dW1, db1 = propa_arriere_activ(dA1, cache1, activation="relu")



       grads['dW1'] = dW1
       grads['db1'] = db1
       grads['dW2'] = dW2
       grads['db2'] = db2


       parameters = update_parameters(parameters, grads, learning_rate)



       W1 = parameters["W1"]
       b1 = parameters["b1"]
       W2 = parameters["W2"]
       b2 = parameters["b2"]


       if print_cost and i % 100 == 0:
           print("Cost after iteration {}: {}".format(i, np.squeeze(cost)))
       if print_cost and i % 100 == 0:
           costs.append(cost)



   plt.plot(np.squeeze(costs))
   plt.ylabel('cost')
   plt.xlabel('iterations (per tens)')
   plt.title("Learning rate =" + str(learning_rate))
   plt.show()

   return parameters

Затем я вычисляю эту строку кода для запуска нейронной сети с входной формой 64, скрытым слоем формы 20 и выходомформа 10:

parameters = two_layer_model(x_train1, y_train1, layers_dims = (x_train1.shape[0], 20, 10), num_iterations = 2000, print_cost=True)

И я получаю это:

Cost after iteration 0: 6.962808001140989
Cost after iteration 100: 6.962808001140989
Cost after iteration 200: 6.962808001140989
Cost after iteration 300: 6.962808001140989
Cost after iteration 400: 6.962808001140989
Cost after iteration 500: 6.962808001140989
Cost after iteration 600: 6.962808001140989
Cost after iteration 700: 6.962808001140989
Cost after iteration 800: 6.962808001140989
Cost after iteration 900: 6.962808001140989
Cost after iteration 1000: 6.962808001140989
Cost after iteration 1100: 6.962808001140989
Cost after iteration 1200: 6.962808001140989
Cost after iteration 1300: 6.962808001140989
Cost after iteration 1400: 6.962808001140989
Cost after iteration 1500: 6.962808001140989
Cost after iteration 1600: 6.962808001140989
Cost after iteration 1700: 6.962808001140989
Cost after iteration 1800: 6.962808001140989
Cost after iteration 1900: 6.962808001140989

И этот график:

Cost after iteration

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...