EX3:神经网络手写数字识别(多类分类)

EX3:神经网络手写数字识别(多类分类)

之前实现了多类逻辑回归来识别手写数字。 然而,逻辑回归不能形成更复杂的假设,因为它只是一个线性分类器。 (虽然可以向其中添加多项式特征,但训练成本可能非常高。)在这部分练习中,将使用与之前相同的训练集实现一个神经网络来识别手写数字。 神经网络将能够表示形成非线性假设的复杂模型。

目标是实现前馈传播算法。

1.数据读取

import numpy as np
from scipy.io import loadmat
data=loadmat('ex3data1.mat')
weights=loadmat('ex3weights.mat')

这里用到的data和ex3逻辑回归练习中是一样的,weights是已经训练好的神经网络权重,我们看一下它长什么样子

print一下可以看到weights中包含‘Theta1’和‘Theta2’两个部分,可以知道本次练习中我们用到的神经网络应当有两层hidden layer。

分别看看这两个权重的维度:

print(weights['Theta1'].shape,weights['Theta2'].shape)#((25,401),(10,26))

根据读取到的权重维度,可以直到网络一共有两层,其中Layer1包含25个neuron,Layer2包含10个neuron,这10个neuron的输出就是神经网络预测的结果。

注意:Layer1的输出在进入Layer2的运算前添加了偏置项。所以Layer2的系数矩阵维度发生变化,为(10,26)。

练习中神经网络架构示意图:
在这里插入图片描述

2.实现神经网络前馈传播计算

现在为神经网络实现前馈传播,实现为每个示例计算并返回相关预测的前馈计算。与一对多分类策略类似,神经网络的预测将是输出最大的标签。

注意到系数矩阵Theta1包含401列,即我们输入的X需要包含偏置列。

首先构造一下要用到的Xy

#构造X,y
X=data['X']
y=data['y']

(X.shape,y.shape)#((5000, 400), (5000, 1))

我们总共有5000个样本,包含400个特征,还包含对应的label,下面我们为X添加偏置列:

ones_col=np.ones(X.shape[0])
X=np.c_[ones_col,X]
X.shape#(5000, 401)

X和y都构造完毕,接下来我们实现神经网络前馈传播算法,该函数将返回神经网络的预测结果。

首先构造激活函数——Sigmoid函数,便于在前馈传播计算中使用。

def sigmoid(z):
    return 1/(1+np.exp(-z))

构造函数前,我们首先分析一下数据在该神经网络中的计算过程:
首先是输入数据X,X与Theta1相乘后经过激活函数生成下一层神经网络的输入:
X : ( 5000 , 401 ) T h e t a 1 : ( 25 , 401 ) z 1 = T h e t a 1. d o t ( X T ) a 1 = g ( z 1 ) : ( 25 , 5000 ) X:(5000,401) \\Theta1:(25,401) \\z1=Theta1.dot(X^T) \\a1=g(z1):(25,5000) X:(5000,401)Theta1:(25,401)z1=Theta1.dot(XT)a1=g(z1):(25,5000)
第一层的计算结果要先添加一行偏置项(全1)再进入下一层的计算,与Theta2相乘以后经过激活函数得到输出:
a 1 : ( 25 , 5000 ) T h e t a 2 : ( 10 , 26 ) a 1 添 加 行 : ( 26 , 5000 ) z 2 = T h e t a 2. d o t ( a 1 ) a 2 = g ( z 2 ) : ( 10 , 5000 ) a1:(25,5000) \\Theta2:(10,26) \\a1添加行:(26,5000) \\z2=Theta2.dot(a1) \\a2=g(z2):(10,5000) a1:(25,5000)Theta2:(10,26)a1:(26,5000)z2=Theta2.dot(a1)a2=g(z2):(10,5000)
每一列都是针对某一个样本的输出结果.

最后我们要输出该神经网络的预测结果,用到numpy库中一个函数argmax,函数说明如下

numpy.argmax(a,axis=0/1)
对二维矩阵a:
若axis=0则沿列方向搜索每一列最大的数并返回其列索引;
若axis=1则沿行方向搜索每一列最大的数并返回其行索引

注意我们的索引范围应当在0-9,而预测的数字为1-10,所以我们要将argmax返回的结果+1再输出。

def predict(Theta1,Theta2,X):
    #layer1
    a1=sigmoid(Theta1.dot(X.T))
    #add bias
    ones_col=np.ones((1,a1.shape[1]))
    a1=np.r_[ones_col,a1]
    #layer2
    a2=sigmoid(Theta2.dot(a1))

    pre_max=np.argmax(a2,axis=0)#搜索每一列最大值并返回列索引
    return pre_max+1

函数构造完毕,我们来输出一下网络预测的准确性:

result=predict(weights['Theta1'],weights['Theta2'],X)
correct=np.array([1 if result[i]==y[i] else 0 for i in range(len(y))])

print("Accuracy:{}%".format(correct.sum()/len(correct)*100))#Accuracy:97.52%

根据练习说明文档中写的“我们将得到accuracy大概97.5%”可知算法正确运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值