MNIST数据集手写数字识别(二)

        上一篇对MNIST数据集有了一些了解,数据集包含着60000张训练图片与标签值和10000张测试图片与标签值的数据集,数据集有了,现在我们来构造神经网络,预测下对这测试的10000张图片的正确识别率,也就是看下手写数字的识别率的情况。

def getTestData():
    """
    获取测试数据
    """
    (x_train,t_train),(x_test,t_test)=load_mnist(normalize=True,flatten=True,one_hot_label=False)
    return x_test,t_test

getTestData()[0].shape
(10000, 784)
getTestData()[1].shape
(10000,) 

获取测试的数据,通过形状可以看到有10000张784(28x28像素)的图片的矩阵和10000张标签值的一维数组!

在构造神经网络过程中,不可或缺的就是权重和偏置,我们读取已预设好的权重和偏置文文件(sample_weight.pkl),在后期的学习中将如何选定参数。

import sys,os,numpy as np
sys.path.append('D:\Anaconda3\TONYTEST')
os.chdir('D:\Anaconda3\TONYTEST\dataset')
from dataset.mnist import load_mnist
import pickle

def getweights():
    """
    获取权重和偏置数据
    """
    with open('sample_weight.pkl','rb') as f:
        wbs=pickle.load(f)
    return wbs

sample_weight.pkl是一个权重和偏置的参数的pkl文件,内容是字典类型保存,分别查看下权重和偏置的形状,我们看到形状对应维度的数量一致,知道可以做点积运算
wb=getweights()
wb['W1'].shape,wb['W2'].shape,wb['W3'].shape
((784, 50), (50, 100), (100, 10))
wb['b1'].shape,wb['b2'].shape,wb['b3'].shape
((50,), (100,), (10,))

def predict(wbs,x):
    """
    以NumPy数组的形式输出各个标签对应的概率
    """
    W1,W2,W3=wbs['W1'],wbs['W2'],wbs['W3']
    b1,b2,b3=wbs['b1'],wbs['b2'],wbs['b3']
    a1=np.dot(x,W1)+b1
    z1=sigmoid(a1)
    a2=np.dot(z1,W2)+b2
    z2=sigmoid(a2)
    a3=np.dot(z2,W3)+b3
    y=softmax(a3)
    return y

现在来看下使用测试数据来查看识别精度,测试识别精度,都使用测试数据,不能使用训练数据

x,t=getTestData()
wb=getweights()
accuracy_cnt=0
for i in range(len(x)):
    y=predict(wb,x[i])
    p=np.argmax(y) #获取概率最高的元素的索引值
    #概率最高的索引值如果和测试的标签值相等就加1
    if p==t[i]:
        accuracy_cnt+=1
print('识别精确率:{:.2%}'.format(accuracy_cnt/len(x)))

识别精确率:93.52%
也就是说10000张测试图片,正确识别了9352张

上面用到的一些公用函数,可以统一写在一个common目录里面的funtions.py

import numpy as np
def sigmoid(x):
    return 1 / (1 + np.exp(-x))    

def softmax(x):
    if x.ndim == 2:
        x = x.T#矩阵转置
        x = x - np.max(x, axis=0)
        y = np.exp(x) / np.sum(np.exp(x), axis=0)
        return y.T 

    x = x - np.max(x) # 溢出对策
    return np.exp(x) / np.sum(np.exp(x))

使用方法跟上一篇文章中的使用dataset一样
from common.functions import sigmoid,softmax

上面的识别精确率,是一张一张处理,现在改进一下做批处理,也就是一次性输入比如100张图片,那10000张图片就100批次搞定,批处理可以大大缩短处理时间。

x,t=getTestData()
wb=getweights()
batch_size=100#每次批处理的数量
accuracy_cnt=0
for i in range(0,len(x),batch_size):
    x_batch=x[i:i+batch_size]
    y_batch=predict(wb,x_batch)
    p=np.argmax(y_batch,axis=1)
    accuracy_cnt+=np.sum(p==t[i:i+batch_size])
print("精确率:{:0.2%}".format(accuracy_cnt/len(x)))

精确率:93.52%

其中axis=1表示沿着第一维方向(第一维为轴),或者我是这么理解它,axis=0代表列,axis=1代表行,如下

q=np.array([[1,2,3],[22,39,1],[10,9,12],[0.9,0.1,8]])
'''
array([[  1. ,   2. ,   3. ],
       [ 22. ,  39. ,   1. ],
       [ 10. ,   9. ,  12. ],
       [  0.9,   0.1,   8. ]])
'''
a0=np.argmax(q,axis=0)
array([1, 1, 2], dtype=int64)


a1=np.argmax(q,axis=1)
array([2, 1, 2, 2], dtype=int64)

一般来说都是axis=1,因为q.shape是(4,3),4行3列,那么我们取最大值的索引值,也是每行取一个最大值,回到前面的(10000,784)也是这样,10000张图片,每张图片是784列,那么我们肯定也是取10000张标签值,所以每行取一个!

np.max(q,axis=1)

array([  3.,  39.,  12.,   8.])

你可能感兴趣的:(Python,神经网络,机器学习,深度学习)