Вопрос или проблема
Я совсем новичок в нейронных сетях и науке о данных в целом и хотел попробовать создать простую нейронную сеть на 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
Мне кажется, здесь можно использовать скалярное произведение.
Ответ или решение
Конечно, давайте рассмотрим вашу задачу более подробно.
Вы столкнулись с проблемой, когда ваш нейронная сеть не обучается при наличии более чем одного обучающего примера. Это довольно распространенная проблема для новичков в области машинного обучения, и решать её необходимо систематично.
Анализ проблемы
-
Формирование обучающей выборки:
Ваш текущий код генерирует x в диапазоне от -5 до 5. Это хорошо, однако, код, который используетrandom.uniform(-5,5,size=(10,1))
позволит вам создать набор данных из 10 элементов сразу, что предпочтительнее для обучения модели. -
Модель сети:
У вас сеть из трех слоев. Это стандартная архитектура для простых задач регрессии, но есть несколько моментов, которые стоит уточнить.- Убедитесь, что ваша функция активации и обратное распространение оптимизированы. Функция активации ReLU приведена правильно, но в корректировке весов и смещений (bias) могут быть недочеты.
- Переменная
self.targetprevX
в коде может требовать доточного пересмотра. Попробуйте улучшить использование матричных операций, заменив циклы на более оптимизированные функции из библиотеки NumPy.
-
Процесс обучения:
- Каждый шаг обучения должен включать в себя: прямое распространение (forward), обратное распространение ошибки (backpropagation) и обновление параметров сети.
- Ваша скорост обучения (
Lrate = 0.001
) может быть слишком мала для данной задачи, попробуйте увеличить её, например, до 0.01 или 0.1 и понаблюдайте за изменениями.
-
Проверка ошибок:
- Важно убедиться, что ошибки, возникающие в процессе выполнения не игнорируются. Простой вывод значений ошибки (
print
) не всегда помогает; целесообразно использовать визуализацию метрик или более детально разбирать возникающие ошибки. - Выражение, определяющее ошибку, должно учитывать диверсификацию входных данных. Если проблема продолжает существовать, попробуйте изначально работать с отдельным набором данных и увеличивать сложность шаг за шагом.
- Важно убедиться, что ошибки, возникающие в процессе выполнения не игнорируются. Простой вывод значений ошибки (
-
Оптимизация:
- Постарайтесь использовать библиотеки для автоматического вычисления градиента, такие как TensorFlow или PyTorch. Это позволит сократить время, потраченное на вычисление градиентов вручную и снизит вероятность ошибок.
Заключение
Проблема, с которой вы столкнулись, может быть решена с помощью корректной настройки обучающего процесса и вниманием к деталям в коде. Со временем, и с внедрением вышеприведенных рекомендаций, вы сможете наладить процесс обучения вашей нейронной сети. Не бойтесь экспериментировать и анализировать промежуточные результаты; именно так учатся большому числу концепций в области машинного обучения.
Если вам необходимы дальнейшие объяснения или помощь, не стесняйтесь обращаться с более конкретными вопросами. Удачи в обучении!