学长给的作业,但是在搜索的时候发现好像没有很多已有的资料是在做无框架实现人工神经网络的,而对于MNIST的识别也是使用Tensorflow居多。做出来的是比较差的模型,没有进行正则化,然后在1000次训练之后大概有88%左右的正确率。一共是三层网络,第一层是数据集的输入,在这里没有用卷积,只是把28x28的灰度图片展开成784维的向量输入模型,第一层到第二层所使用的是tanh激活函数,第二层到第三层用的是softmax。但是第一层到第二层的tanh可能有些许梯度消失的问题(已经对数据进行归一化处理,可是这个现象还是存在),本来想是换成softmax函数的,但是奈何资料匮乏,数学能力有限所以并不能自己求导,所以现在暂时是tanh+softmax这样的组合。关于梯度下降,本来用的是吴恩达老师在机器学习教程里面教的累积梯度下降,即在遍历一遍数据集后进行一次梯度下降。但是因为效果不好,又查阅了周志华老师的《机器学习》中神经网络的相关章节之后发现其实累积梯度下降在数据量大的时候可能要比标准梯度下降的效果差些,所以这里采用的是标准的梯度下降。关于正则化,在代码里面实现了以后发现lambda的值变化以后下降的效果并不是很好,而且lambda在取很大的书的时候会抛出警告甚至错误,所以在代码里面把lambda设为0。这是一个效果很差的模型,发出来只是希望能帮到有需要无框架实现人工神经网络的同学。如果有知道正则化方法或者是发现我代码中的错误和可以改进的地方的朋友,请告诉我qwq
代码如下:
import numpy as np
import os
import struct
import random
def softmax(X):
X=X-np.max(X)
expX=np.exp(X)
softmaxX=expX/np.sum(expX)
return softmaxX
def Normalization(X):
X=X-np.average(X)
X=X/X.max()
return X
def LoadData(path,kind):
labelPath=os.path.join(path,'%s-labels.idx1-ubyte'%kind)
imagePath=os.path.join(path,'%s-images.idx3-ubyte'%kind)
with open(labelPath,'rb') as lb:
magic,n=struct.unpack('>II',lb.read(8))
labels=np.fromfile(lb,dtype=np.uint8)
with open(imagePath,'rb') as ib:
magic, num, rows, cols = struct.unpack('>IIII',ib.read(16))
images = np.fromfile(ib,dtype=np.uint8).reshape(len(labels), 784)
labelsResult=[]
for i in range(labels.shape[0]):
y = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
y[labels[i]]=1
labelsResult.append(y)
labelsResult=np.array(labelsResult)
images=Normalization(images)
return images,labelsResult
def RandomInitial(x,y):
w=np.random.rand(x,y)
b=random.random()
b=b*np.ones((1,y))
return w,b
def Learning(X_train,y_train,learningRate,learningTimes,mylambda):
w1,b1=RandomInitial(784,50)
w2,b2=RandomInitial(50,10)
num=y_train.shape[0]
for times in range(learningTimes):
DW1 = np.zeros((784, 50))
DW2 = np.zeros((50, 10))
DB1 = np.zeros((1, 50))
DB2 = np.zeros((1, 10))
cost = 0
for i in range(num):
X=X_train[i].reshape(1,784)
y=y_train[i]
#FB
z2=np.dot(X,w1)+b1
a2=np.tanh(z2)
z3=np.dot(a2,w2)+b2
h=softmax(z3)
#BP
delta3=h-y
DW2=np.dot(a2.T,delta3)/num+mylambda*w2
DB2=delta3.sum()/num
delta2=np.multiply(np.dot(delta3,w2.T),np.power(a2,2))
DW1=np.dot(X.T,delta2)/num+mylambda*w1
DB1=delta2.sum()/num
#标准梯度下降
w2=w2-learningRate*DW2
w1=w1-learningRate*DW1
b1=b1-learningRate*DB1
b2=b2-learningRate*DB2
#Cost
J=np.multiply(-y,np.log(h)).sum()/num
cost=cost+J
print('Cost:',times+1,cost)
#累积梯度下降
#w2=w2-learningRate*DW2
#w1=w1-learningRate*DW1
#b1=b1-learningRate*DB1
#b2=b2-learningRate*DB2
return w1,w2,b1,b2
def HProcess(X):
max=X[0][0]
index=0
for i in range(X.shape[1]):
if max