我正在学习制作神经网络,我已经推导出以下反向传播方程式。这有什么不对,因为我似乎无法接受神经网络训练。我在python中编码,我得到的准确度大约是10(即使我不训练我的网络也能得到这个)。但是,每次迭代的错误都在减少。
另外,我目前正在按尺寸识别矩阵以执行点积,Hadamard积和换位,有点像打击和试用。有一个更好的方法吗?
根据我的理解,我们试图找到合适的权重,以便最大限度地降低成本。因此,为此,我们采用偏导数,它可以衡量一个组件的微小变化将对系统的总体成本产生多大影响。因此,我得出了这个,但我不明白为什么网络没有训练。请帮忙......
它是一个3层神经网络(输入层,1个隐藏层,输出层)。首先,我通过神经网络向前输入输入,然后计算成本,最后使用反向传播来更新权重。这里,x
是输入数据,w
是权重(第1层为w1,第2层为w2),z(a,w)
是从左层到右层的数据传输,{ {1}}是激活函数(使用Sigmoid函数),g(z)
是图层的输出,a(z)
是成本函数(使用的平均误差)。
这是我的神经网络的前馈方程式:
这是权重E(a,y)
,w1
(第1层的偏差),w1b
和w2
(第2层的偏差)的反向传播梯度的推导。
我的python代码:
(我使用w2b
作为列表在序列p
中的函数之间传递权重。此外,我稍后添加了正则化项,因此不包括在派生中。但它遵循相同的部分原则代码是用Jupyter Notebook编写的,每个函数都有自己的块。)
w1,w1b,w2,w2b
以下是我执行所有操作的主体。它已被分解为块以解释块的作用。代码块组合起来形成我的主体,其中所有上述函数都被调用。
alpha=0.12
lmda=1
def feedForward(p,x):
a1=x
z2=np.dot(a1,p[0])+p[1]
a2=g(z2)
z3=np.dot(a2,p[2])+p[3]
a3=g(z3)
return [a1,a2,a3],[z2,z3]
from scipy.special import expit
def g(z):
return expit(z)
def gPrime(z):
s=g(z)
return np.multiply(s,(1-s))
def cost(p,x,y):
[a,z]=feedForward(p,x)
h=a[-1]
lmda_sum=(lmda*0.5/x.shape[0])*(sum(sum(np.square(p[0])))+sum(sum(np.square(p[2])))
return sum(sum(np.square(y-h)))*0.5/x.shape[0]+lmda_sum
def backpropagate(p,x,y):
[a,z]=feedForward(p,x)
h=a[-1]
dz=[]
m=x.shape[0]
dz4=np.divide((-(y-h)),m)
dz3=np.multiply(dz4,gPrime(z[-1]))
dw2=np.dot(a[-2].T,dz3) + np.multiply(lmda/m,p[2])
dw2b=np.sum(dz3,0)
dz2=np.multiply(np.dot(dz3,p[2].T),gPrime(z[-2]))
dw1=np.dot(a[-3].T,dz2) + np.multiply(lmda/m,p[0])
dw1b=np.sum(dz2,0)
return [dw1,dw1b,dw2,dw2b]
def costPrime(p,x,y):
grad=backpropagate(p,x,y)
p[0] =p[0]-np.multiply(alpha,grad[0])
p[1] =p[1]-np.multiply(alpha,grad[1])
p[2] =p[2]-np.multiply(alpha,grad[2])
p[3] =p[3]-np.multiply(alpha,grad[3])
return p
def train(p,x,y,iteration):
E=[]
for i in range(iteration):
E.append(cost(p,x,y))
p=costPrime(p,x,y)
return p,E
def predict(p,x,y):
[pred,z]=feedForward(p,x)
a=pred[-1].argmax(axis=1)
a=np.reshape(a,(y.shape[0],1))
b=np.argmax(y,axis=1) # gets index of max element for every row
return a, np.mean(a==b)*100
# return pred, np.mean(np.sum(pred,0) == np.sum(y,0)) * 100
def randomInitialize(params):
epsilion = 0.12
m=len(params)
for i in range(m):
s=params[i].shape
params[i]=np.multiply(np.random.rand(s[0],s[1]),2*epsilion)-epsilion
return params
在这里,我从matlab导出的矩阵中导入输入和输出数据,并将它们存储在%matplotlib inline
import matplotlib.pyplot as plot
import random
import numpy as np
import scipy.io as io
和X
中。
y
这里将向量data=io.loadmat('ex4data1.mat')
X=data['X']
y=data['y']
(它是一个向量,例如mx1)转换为矩阵(mx10)。每行都将被转换,例如:如果y
,则行中的第3个元素将为y=3
,其余为1
,即0
。对于[0 0 1 0 0 0 0 0 0 0]
,它被映射到第10个索引,即y=0
。
[0 0 0 0 0 0 0 0 0 1]
所有加载的数据都用于训练网络
y_train=np.zeros((y.shape[0],10))
for i in range(1,11):
c=np.zeros((1,10))
if i==10:
c[0][0]=1
else:
c[0][i]=1
y_train[np.where(y==i)[0]] = c
y=y_train
从集xtrain=X
ytrain=y
w1=np.zeros((400,26))
w1b=np.zeros((1,26))
w2=np.zeros((26,10))
w2b=np.zeros((1,10))
p=[w1,w1b,w2,w2b]
p=randomInitialize(p)
[p,E]=train(p,X,y,50)
plot.plot(E)
和X
中随机选择200行,然后使用to作为测试集。我知道不应该这样做,因为所有的数据都用于训练,但我只是想检查一下这个程序是否训练有素。如果它已经成功训练,它将比10更精确。
y
这是我在绘制randList=np.random.randint(X.shape[0],size=(1,200))
xtest=np.reshape(X[randList],(200,-1))
ytest=np.reshape(y[randList],(200,10))
[pred,acc]=predict(p,xtest,ytest)
print acc
返回的E
后得到的费用图。