Я пытаюсь построить нейронную сеть, используя NumPy, и я знаю, что есть тысячи примеров, но я пытаюсь только с теорией, которую я прочитал из курса Coursera Machine Learning от Andrew Ng. Сначала я попробовал векторизованную реализацию и подумал, что я ее неправильно кодировал, но потом я попытался снова закодировать ее с помощью векторизации и получил ту же проблему, функция стоимости начинает расти, иногда нет, но прогнозы даже близко не соответствуют учиться. Я использовал градиентную проверку и обнаружил, что проблема действительно в обратном распространении, поэтому я хотел спросить, может ли кто-нибудь сказать мне, не понимаю ли я теорию или плохо ее кодирую! Вот код (я знаю, что моя реализация ужасна, но это для обучения, хуже всего - проверка градиента ...), Эндрю не объяснил, что делать с производными от терминов смещения, но мой вывод был Суммируйте условия ошибок, умноженные на веса:
import numpy as np
def sigmoid(z):
return 1/(1+np.exp(-z))
class NeuralNetwork:
def __init__(self,arch_):
self.arch = arch_
self.layers = arch_.size
self.w, self.b = self.random_initialization(arch_)
self.lamb = 0
self.epochs = 1000
self.alpha = 0.01
def random_initialization(self,arch):
w = [np.random.randn(arch[1],arch[0])*np.sqrt(2/arch[0])]
b = np.array([np.random.randn(self.arch[i+1])*np.sqrt(2/arch[i]) for i in range(1,self.arch.size-1)])
for i in range(1,arch.size-1):
w.append(np.random.randn(arch[i+1],arch[i])*np.sqrt(2/arch[i]))
return np.array(w), b
def forward_propagation(self,x):
a = sigmoid(np.dot(self.w[0],x))
a_m = [x,a]
for i in range(1,self.layers-1):
a = sigmoid(np.dot(self.w[i],a)+self.b[i-1])
a_m.append(a)
return a_m
def cost_function(self,x,y):
h = np.array([self.forward_propagation(i)[-1] for i in x])
reg = np.square(self.w[0]).sum()
for i in range(1,self.layers-1):
reg += np.square(self.w[i][:,1:]).sum()
return -1/y.shape[0]*(np.log(1-h)*(1-y) + np.log(h)*y).sum() + self.lamb/(2*y.shape[0])*reg
def backward_propagation(self,nabla_w,nabla_b,a,y):
d_l = a[-1] - y
d = [d_l]
for i in range(1,self.layers-1)[::-1]:
nabla_b[i-1] += (d_l * self.b[i-1])
d_l = np.dot(d_l,self.w[i])*a[i]*(1-a[i])
d.insert(0,d_l)
for i in range(len(d))[::-1]:
nabla_w[i] += (d[i][None,:] * a[i][None,:].T).T
def gradient(self,x,y):
nabla_w = []
for i in range(self.arch.size-1):
nabla_w.append(np.zeros((self.arch[i+1],self.arch[i])))
nabla_b = np.array([np.zeros(self.arch[i+1]) for i in range(1,self.arch.size-1)])
for i in range(x.shape[0]):
self.backward_propagation(nabla_w,nabla_b,self.forward_propagation(x[i]),y[i])
delta = []
for i in range(self.w.size):
delta.append(nabla_w[i]+self.lamb*self.w[i])
return ((1/y.size)*np.array(delta)),(1/(y.size)*nabla_b)
def train(self,x,y):
for i in range(self.epochs):
d_w, d_b = self.gradient(x,y)
self.w -= self.alpha * d_w
self.b -= self.alpha * d_b
def gradient_checking(self,x,y):
e = 10**-6
g_1 = []
for i in range(self.w.shape[0]):
g_2 = []
for j in range(self.w[i].shape[0]):
g_3 = []
for k in range(self.w[i][j].shape[0]):
self.w[i][j][k] += e
m = self.cost_function(x,y)
self.w[i][j][k] -= 2*e
n = self.cost_function(x,y)
self.w[i][j][k] += e
g_3.append((m-n)/(2*e))
g_2.append(np.array(g_3))
g_1.append(np.array(g_2))
b_1 = []
for i in range(self.b.shape[0]):
b_2 = []
for j in range(self.b[i].shape[0]):
self.b[i][j] += e
m = self.cost_function(x,y)
self.b[i][j] -= 2*e
n = self.cost_function(x,y)
self.b[i][j] += e
b_2.append((m-n)/(2*e))
b_1.append(np.array(b_2))
return np.array(g_1), np.array(b_1)
x = np.array([[1,4],[4,3],[8,9],[12,5],[12,7],[15,9]])
y = np.array([[1,0],[1,0],[0,1],[0,1],[0,1],[0,1]])
k = NeuralNetwork(np.array([2,3,2]))
k.train(x,y)