Как обновить веса первого слоя?

Вопрос или проблема

Я пытаюсь создать нейронную сеть без использования какой-либо библиотеки глубокого обучения, которая распознает числа из базы данных mnist. Ее структура: 784 входных нейрона (для 784 пикселей на изображениях чисел), 10 скрытых нейронов (только 1 скрытый слой) и 10 выходных нейронов. Есть 10 смещений для скрытого слоя.

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

Вот код:

#прямое распространение
def forward(inp, w1, w2, biases):
    hidsRes = []
    outRes = []

    for i in range(len(w1)):
        n = np.dot(inp, w1[i])

        n += biases[i]
        n = relu(n)

        hidsRes.append(n)

    for i in range(len(w2)):
        n = np.dot(hidsRes, w2[i])

        outRes.append(n)

    return softmax(outRes)

#обратное распространение
def back(avgResult, w1, w2, lr):
    for i, w in enumerate(w2):
        w2[i] += lr * avgResult[i] #Я обновляю только последний слой, основываясь на среднем ошибке каждого нейрона

def train(inps, hids, outs, randomWeightDiff, batchs, gens, lr):
    w1, w2, b = initNn(inps, hids, outs, randomWeightDiff)

    # загрузка набора данных mnist
    x_train, x_test, y_train, y_test = getData()

    for gen in range(gens):
        errors = []

        x_train, y_train = shuffle(x_train, y_train)
        
        for batch in range(batchs):  
            prediction = forward(tolist(x_train[batch].tolist()), w1, w2, b)
            y = y_train[batch]

            target = [0 if i != y else 1 for i in range(10)]

            errors.append([prediction[i] - target[i] for i in range(10)])

        print(errors)

        avg = [sum([errors[i][j] for j in range(len(errors))]) / 10 for i in range(10)]

        back(avg, w1, w2, lr)
        print("Поколение {gen} \n" + f"{avg}")

train(784, 10, 10, 2, 100, 1000, 0.01)

Я пробовал симулировать множество нейронных сетей и мутировать лучшие из них, но это было слишком медленно и не работало.

Кстати, я еще не изучалadvanced math.

Я думаю, что ваша самая большая ошибка – это обновление весов с использованием ошибки модели, а не производных ошибки. Это не обратное распространение. Чтобы обновить параметр сети, вы должны вычислить производную ошибки по отношению к параметру (с использованием правила цепи для более глубоких слоев) и применить ее к весу, используя метод градиентного спуска.

Минимизация ошибки немного похожа на спуск с холма. Градиенты сообщают вам, куда вы должны сделать следующий шаг, чтобы максимально быстро спуститься. Вам нужна информация о склоне пути вокруг вас. Использование средней ошибки можно сравнить с поиском пути вниз, зная только высоту, это не очень полезно.

Я держу кулачки за ваши дальнейшие шаги 🙂

Ответ или решение

Обновление весов первого слоя в нейронной сети представляет собой ключевую задачу при обучении модели. Давайте рассмотрим, как это сделать, основываясь на описании вашей сети и учете некоторых принципов обратного распространения ошибок.

Основные принципы

  1. Обратное распространение ошибки: Для обновления весов нейронной сети необходимо не только знать среднюю ошибку на выходе модели, но и вычислить градиенты этих ошибок по отношению к каждому весу. Это достигается с помощью метода обратного распространения, который использует правило цепочки.

  2. Градиентный спуск: Обновление весов осуществляется с использованием градиентного спуска, который предполагает перемещение весов в направлении, противоположном направлению градиента функции потерь, для минимизации ошибки.

Алгоритм обновления весов первого слоя

Давайте пошагово разберемся, как обновить веса первого слоя и смещения (bias) в вашей модели.

  1. Вычисление градиента ошибки для выходного слоя:

    • На выходном слое ваша ошибка, обозначаемая как avg, используется для вычисления градиента:
      [
      \delta^{(2)} = (y{\text{pred}} – y{\text{true}}) \cdot \text{softmax}'(z^{(2)})
      ]
      где ( z^{(2)} ) – это выходные активации перед функцией softmax.
  2. Обновление весов второго слоя:

    • Чтобы обновить веса второго слоя, вам нужно использовать градиент ошибки:
      for i in range(len(w2)):
      w2[i] -= lr * np.outer(hidsRes, delta2) # где delta2 - это градиент для второго слоя
  3. Вычисление градиента для скрытого слоя:

    • Далее, вам необходимо вычислить δ(1) для скрытого слоя:
      [
      \delta^{(1)} = \delta^{(2)} \cdot w^{(2)} \cdot \text{relu}'(z^{(1)})
      ]
      Здесь ( z^{(1)} ) – это активации скрытого слоя, а relu' – производная функции активации ReLU (которая равна 1 для положительных значений и 0 для отрицательных).
  4. Обновление весов первого слоя:

    • Обновление весов первого слоя производится аналогично:
      for i in range(len(w1)):
      w1[i] -= lr * np.outer(X, delta1) # где delta1 - это градиент для скрытого слоя
  5. Обновление смещений (bias):

    • Смещения также следует обновлять с использованием вычисленных градиентов:
      biases[i] -= lr * delta1  # Для каждого нейрона в скрытом слое

Полный код

Обновление функции back может выглядеть следующим образом:

def back(y_true, y_pred, w1, w2, hidsRes, inp, lr):
    delta2 = y_pred - y_true  # ошибка в выходном слое
    for i in range(len(w2)):
        w2[i] -= lr * np.outer(hidsRes, delta2)  # обновление весов второго слоя

    # Обратное распространение для скрытого слоя
    delta1 = np.dot(delta2, w2) * relu_derivative(hidsRes)  # вычисление градиента для скрытого слоя
    for i in range(len(w1)):
        w1[i] -= lr * np.outer(inp, delta1)  # обновление весов первого слоя

    # Обновление смещений
    b -= lr * delta1  # аналогично для всех смещений

Заключение

Обновление весов первого слоя требует тщательного выполнения шагов обратного распространения. При этом важно правильно вычислять производные и использовать их для корректного обновления весов и смещений. Постепенно совершенствуя вашу реализацию, вы сможете достигать более высоких результатов в распознавании символов из данных MNIST. Успехов в обучении нейронных сетей!

Оцените материал
Добавить комментарий

Капча загружается...