对于深度学习来说,手写数字识别和编程语言第一程式打印hello word应该属于一个级别的了,下面先看下手写数字识别的网络会是什么样子,然后以此学习几个概念。
MNIST 数据集见上文深度学习入门初探——hello word式的手写数字识别一
2 手写数字识别的推理处理推理处理呢也称为神经网络的前向传播,这里假设训练已经结束,神经网络是个现成的,存储在sample_weight.pkl这个文件中。来看看这个网络是个什么样子哈。
数据的加载上一节已经介绍过了,现在来看看sample_weight.pkl这个网络所呈现的样子:
a、输入数据是是28*28像素的灰度图,shape成一维的就是784个数据。
b、输入层的神经元和数据一致,784个神经元。产生了50个特征,这个50是可以设计的。
c、接下来的一层为了和输入层产生的输出,这个就必须是50个神经元了,产生了100个特征,也是可以设计的。
d、输出层就只能是100个神经元了,因为这一层就要输出最终结果了,只能是10了,意即0-9共10个类别。
关于激活每一层的激活函数以及最后的softmax函数可参见下面两节的实现,独热码在这里利于概率化的输出:
深度学习入门初探——简单的激活函数
深度学习入门初探——多层感知机的神经网络式实现
# coding: utf-8
import sys, os
sys.path.append(os.pardir)
import numpy as np
import pickle
from common.functions import sigmoid, softmax
def _change_one_hot_label(X):
T = np.zeros((X.size, 10))
for idx, row in enumerate(T):
row[X[idx]] = 1
return T
def load_mnist(normalize=True, flatten=True, one_hot_label=False):
"""读入MNIST数据集
Parameters
----------
normalize : 将图像的像素值正规化为0.0~1.0
one_hot_label :
one_hot_label为True的情况下,标签作为one-hot数组返回
one-hot数组是指[0,0,1,0,0,0,0,0,0,0]这样的数组
flatten : 是否将图像展开为一维数组
Returns
-------
(训练图像, 训练标签), (测试图像, 测试标签)
"""
with open("mnist.pkl", 'rb') as f:
dataset = pickle.load(f)
if normalize:
for key in ('train_img', 'test_img'):
dataset[key] = dataset[key].astype(np.float32)
dataset[key] /= 255.0
if one_hot_label:
dataset['train_label'] = _change_one_hot_label(dataset['train_label'])
dataset['test_label'] = _change_one_hot_label(dataset['test_label'])
if not flatten:
for key in ('train_img', 'test_img'):
dataset[key] = dataset[key].reshape(-1, 1, 28, 28)
return (dataset['train_img'], dataset['train_label']), (dataset['test_img'], dataset['test_label'])
def get_data():
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
return x_test, t_test
def init_network():
with open("sample_weight.pkl", 'rb') as f:
network = pickle.load(f)
return network
def predict(network, x):
W1, W2, W3 = network['W1'], network['W2'], network['W3']
b1, b2, b3 = network['b1'], network['b2'], network['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
np.set_printoptions(formatter={'float': '{: 0.9f}'.format})
x, t = get_data()
network = init_network()
print("\n\n输入数据的维度 :",x[0].shape, "\n")
print("输入层的神经元 w b :",network['W1'].shape, " ",network['b1'].shape, "\n")
print("隐藏层的神经元 w b :",network['W2'].shape, " ",network['b2'].shape, "\n")
print("输出层的神经元 w b :",network['W3'].shape, " ",network['b3'].shape, "\n")
y = predict(network, x[0])
print("预测的输出softmax概率:\n",y, "\n")
p= np.argmax(y)
print("预测的结果: ",p, "\n", "\n", "\n")
3 批处理
神经网络的输入不是一个个图像了,而是多个图像,上图中输入数据的维度就是[batch_size,784],矩阵乘法的规则这个batch_size是一直传递下去的,这里注意下,结果数据在取最大值索引时的维度即可。
这个批的大小跟在计算机系统的内存和算力很大关系,同时在训练的过程中批处理也有很多好处的,这个后面遇到了再学习。
# coding: utf-8
import sys, os
sys.path.append(os.pardir)
import numpy as np
import pickle
from common.functions import sigmoid, softmax
def _change_one_hot_label(X):
T = np.zeros((X.size, 10))
for idx, row in enumerate(T):
row[X[idx]] = 1
return T
def load_mnist(normalize=True, flatten=True, one_hot_label=False):
with open("mnist.pkl", 'rb') as f:
dataset = pickle.load(f)
if normalize:
for key in ('train_img', 'test_img'):
dataset[key] = dataset[key].astype(np.float32)
dataset[key] /= 255.0
if one_hot_label:
dataset['train_label'] = _change_one_hot_label(dataset['train_label'])
dataset['test_label'] = _change_one_hot_label(dataset['test_label'])
if not flatten:
for key in ('train_img', 'test_img'):
dataset[key] = dataset[key].reshape(-1, 1, 28, 28)
return (dataset['train_img'], dataset['train_label']), (dataset['test_img'], dataset['test_label'])
def get_data():
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
return x_test, t_test
def init_network():
with open("sample_weight.pkl", 'rb') as f:
network = pickle.load(f)
return network
def predict(network, x):
w1, w2, w3 = network['W1'], network['W2'], network['W3']
b1, b2, b3 = network['b1'], network['b2'], network['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 = get_data()
network = init_network()
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(network, x_batch)
p = np.argmax(y_batch, axis=1)
accuracy_cnt = np.sum(p == t[i:i batch_size])
print("Accuracy:" str(float(accuracy_cnt) / len(x)))