Нейронная сеть не обучается, когда предоставлено более одной обучающей выборки.

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

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

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

Вот мой код, он довольно грязный.

import numpy as np
import matplotlib.pyplot as plt
import random

class Layer: # формат: входные данные умноженные на веса
    def __init__(self,n_inputs,n_neurons):
        self.n_inputs = n_inputs
        self.n_neurons = n_neurons
        self.weights = np.random.randn(n_inputs,n_neurons)
        self.biases = np.zeros((1,n_neurons))

    def forward(self, inputs):
        self.prevX = np.array(inputs)
        self.output = np.dot(inputs,self.weights)+self.biases
        self.ReLU = np.maximum(0,self.output)

    def Correction(self,target,Lrate,ReLUTrue = True):
        if ReLUTrue:
            output = self.ReLU.copy()
        else:
            output = self.output.copy()
        self.biases += 2*(target-output)*Lrate
        dWeights = np.dot(self.prevX.T,2*(target-output))
        dX = np.zeros((1,self.n_inputs))
        for j in range(self.n_neurons):
            dX += 2*(target[0][j]-output[0][j])*self.weights.T[j]
        self.targetprevX = self.prevX + dX*Lrate/self.n_neurons
        self.weights += dWeights*Lrate

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

    def appendLayer(self,layerObject):
        self.layers.append(layerObject)

    def forward(self,inputs):
        for i in range(0,len(self.layers)-1):
            self.layers[i].forward(inputs)
            inputs = self.layers[i].ReLU.copy()
        self.layers[-1].forward(inputs)

    def backProp(self,target,Lrate):
        for i in range(-1,-len(self.layers)-1,-1):
            self.layers[i].Correction(target,Lrate)
            target = self.layers[i].targetprevX.copy()

    def UpdateLayers(self):
        for layer in self.layers:
            layer.Update()

    def Output(self):
        return self.layers[-1].output

neunetwork = Network()
neunetwork.appendLayer(Layer(1,8))
neunetwork.appendLayer(Layer(8,8))
neunetwork.appendLayer(Layer(8,1))

for iter in range(0,100):
    X = random.uniform(-5,5)
    Y = X**2
    neunetwork.forward([[X]])
    print("ошибка:",neunetwork.Output()-Y)
    neunetwork.backProp([[Y]],0.001)

plotXs=[]
plotYs=[]
for points in range(0,100):
    X=random.uniform(-5,5)
    neunetwork.forward([[X]])
    Y=neunetwork.Output()[0][0]
    plotXs.append(X)
    plotYs.append(Y)
plt.plot(plotXs,plotYs,'ok')
plt.show()

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

Спасибо за ваше время.

Входные данные имеют следующую форму:

X = random.uniform(-5,5)
neunetwork.forward([[X]])

print(np.array([[X]]).shape) # == (1,1)

Вы можете использовать numpy для генерации X и y:

X = random.uniform(-5,5,size=(10,1)
Y = X**2

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

Процесс forward/backprop кажется правильным в плане накопления градиентов. Однако я не уверен в следующем коде:

dX = np.zeros((1,self.n_inputs))
for j in range(self.n_neurons):
        dX += 2*(target[0][j]-output[0][j])*self.weights.T[j]
self.targetprevX = self.prevX + dX*Lrate/self.n_neurons

Мне кажется, здесь можно использовать скалярное произведение.

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

Конечно, давайте рассмотрим вашу задачу более подробно.

Вы столкнулись с проблемой, когда ваш нейронная сеть не обучается при наличии более чем одного обучающего примера. Это довольно распространенная проблема для новичков в области машинного обучения, и решать её необходимо систематично.

Анализ проблемы

  1. Формирование обучающей выборки:
    Ваш текущий код генерирует x в диапазоне от -5 до 5. Это хорошо, однако, код, который использует random.uniform(-5,5,size=(10,1)) позволит вам создать набор данных из 10 элементов сразу, что предпочтительнее для обучения модели.

  2. Модель сети:
    У вас сеть из трех слоев. Это стандартная архитектура для простых задач регрессии, но есть несколько моментов, которые стоит уточнить.

    • Убедитесь, что ваша функция активации и обратное распространение оптимизированы. Функция активации ReLU приведена правильно, но в корректировке весов и смещений (bias) могут быть недочеты.
    • Переменная self.targetprevX в коде может требовать доточного пересмотра. Попробуйте улучшить использование матричных операций, заменив циклы на более оптимизированные функции из библиотеки NumPy.
  3. Процесс обучения:

    • Каждый шаг обучения должен включать в себя: прямое распространение (forward), обратное распространение ошибки (backpropagation) и обновление параметров сети.
    • Ваша скорост обучения (Lrate = 0.001) может быть слишком мала для данной задачи, попробуйте увеличить её, например, до 0.01 или 0.1 и понаблюдайте за изменениями.
  4. Проверка ошибок:

    • Важно убедиться, что ошибки, возникающие в процессе выполнения не игнорируются. Простой вывод значений ошибки (print) не всегда помогает; целесообразно использовать визуализацию метрик или более детально разбирать возникающие ошибки.
    • Выражение, определяющее ошибку, должно учитывать диверсификацию входных данных. Если проблема продолжает существовать, попробуйте изначально работать с отдельным набором данных и увеличивать сложность шаг за шагом.
  5. Оптимизация:

    • Постарайтесь использовать библиотеки для автоматического вычисления градиента, такие как TensorFlow или PyTorch. Это позволит сократить время, потраченное на вычисление градиентов вручную и снизит вероятность ошибок.

Заключение

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

Если вам необходимы дальнейшие объяснения или помощь, не стесняйтесь обращаться с более конкретными вопросами. Удачи в обучении!

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

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