1.MNIST手写数字图像数据集:
MNIST手写数字图像数据集是机器学习领域最有名的数据集之一,经常作为实验用的数据集出现,相当于机器学习领域的“Hello World”。
MNIST数据集是由0到9的手写数字图像组成,其中6万张训练图像、1万张测试图像,每张图像是28像素*28像素
的灰度图像(channel=1),各个像素的取值为0-255
。
1.1 数据集的获取及图像显示
from keras.datasets import mnist
from PIL import Image
import numpy as np
# mnist数据集已经预先加载在keras库中,也可以直接在数据集网站上下载
# 数据以(训练图像,训练标签),(测试图像,测试标签)的数据形式返回
(train_images,train_labels),(test_images,test_labels) = mnist.load_data()
# 取出其中一个图像
img = train_images[0]
label = train_labels[0]
print(img.shape)
print(label)
# 定义图像显示函数
def img_show(img):
pil_img = Image.fromarray(np.uint8(img))
pil_img.show()
img_show(img)
2.神经网络的前向传播实现:
这次我们构建一个3层神经网络,其中输入层有784个神经元(将图像展平28*28=784
),输出层有10个神经元(因为每种图片为0-9共10个类别其中之一)。
此外,神经网络还有两个隐藏层,第1个隐藏层有50个神经元,第2个隐藏层有100个神经元(这两个数字可以随意设置)。
因为现在神经网络还不能自己学习参数,所以这里前向传播中的参数均来自现有文件读取(通过python中的pickle功能读取现有的pkl文件中的参数信息)。
from keras.datasets import mnist
import numpy as np
import pickle
# 定义sigmoid函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 定义softmax函数
def softmax(x):
c = np.max(x)
exp_x = np.exp(x - c) # 防止溢出策略
sum_exp_x = np.sum(exp_x)
y = exp_x / sum_exp_x
return y
# 获取数据的函数
def get_data():
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
# 这里需要对数据进行正规化(归一化)处理,否则运行的时候sigmoid函数会报溢出错误
test_images = test_images.reshape(-1, 784).astype('float32')/255
return test_images, test_labels
# 读取pkl文件中的权重参数的函数
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
# 评价识别精度accuracy
x, t = get_data()
network = init_network()
acc = 0
for i in range(len(x)):
y = predict(network, x[i])
# np.argmax()方法获取值最大的元素的索引
p = np.argmax(y)
if p == t[i]:
acc += 1
print('Accuracy为:' + str(acc / len(x)))
运行结果
Accuracy为:0.9352
上面代码中我们对返回的图像做了一些处理,也就是将图像中的各个像素值除以了255,使得数据的值在0.1!1.0之间,想这样吧数据限定在某个范围内的处理称为正规化(normalization),属于数据预处理方法的一种。
3.批处理:
现在我们考虑打包输入多张图像的操作,比如,我们想用上面的predict()
函数一次性打包处理100张图片。
这种打包式的输入数据称为批(batch),这种操作方式称为批处理。
批处理对计算机的运算大有益处,可以大幅缩短每张图像的处理时间,也就是说批处理一次性计算大型数组要比分开逐步计算各个小型数组的速度要快。
from keras.datasets import mnist
import numpy as np
import pickle
# 定义sigmoid函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 定义softmax函数
def softmax(x):
c = np.max(x)
exp_x = np.exp(x - c) # 防止溢出策略
sum_exp_x = np.sum(exp_x)
y = exp_x / sum_exp_x
return y
def get_data():
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
test_images = test_images.reshape(-1, 784).astype('float32')/255
return test_images, test_labels
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
# 评价识别精度accuracy
x, t = get_data()
network = init_network()
# 批数量
batch_size = 100
acc = 0
for i in range(0,len(x),batch_size):
x_batch = x[i:i+batch_size]
y_batch = predict(network, x_batch)
# np.argmax()方法获取第1维(axis=1)上值最大的元素的索引,即为预测结果
p = np.argmax(y_batch, axis=1)
# numpy数组之间使用比较运算符生成布尔型数组,然后通过np.sum()方法计算True的个数,即为预测正确的个数
acc += np.sum(p == t[i:i+batch_size])
print('Accuracy为:' + str(acc / len(x)))
运行结果
Accuracy为:0.9352
Reference:
《Deep Learning from Scratch》