神经网络手写数字识别

Posted by RAIS on 2020-01-06

聊了几天理论,是该弄一个 Hello World 了,在人工智能领域,或者说深度学习领域,Hello World 程序就是手写数字识别,今天我们就来看看手写数字识别的程序怎么写。不愿意看代码吗,那我就说一说这段代码干了点什么:先通过 keras 内置的数据集下载测试数据,是 60000 长手写图片的训练集和 10000 张测试集,随后定义了一个神经网络的模型,设置网络中的层参数,随后配置训练网络的参数,包括损失函数和评测模型,设置迭代次数,启动训练网络,最后将测试数据喂给网络,得出训练效果是否有效。还是建议看仔细看一下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/env python3
from keras import layers
from keras import models
from keras.datasets import mnist
from keras.utils import to_categorical

def hello_world():
# 下载手写数字数据集, https://s3.amazonaws.com/img-datasets/mnist.npz
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

print('训练集:', train_images.shape) # (60000, 28, 28)
print('训练集:', len(train_labels)) # 60000
print('训练集:', train_labels) # [5 0 4 ... 5 6 8]

print()
print('测试集:', test_images.shape) # (10000, 28, 28)
print('测试集:', len(test_labels)) # 10000
print('测试集:', test_labels) # [7 2 1 ... 4 5 6]

# 模型,可以理解为就是前文说的黑盒子
network = models.Sequential()
# 神经网络的核心就是 layer,是真正用来加工处理数据的,Dense 是定义网络层的基础方法
# 512 定义神经元个数,activation 定义激活函数,input_shape 定义输入尺寸
network.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
network.add(layers.Dense(10, activation='softmax'))

# 配置训练模型,optimizer 优化器名,loss 损失函数,metrics 模型评估标准
network.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])

# 不改变数组内容,改变数组格式
train_images = train_images.reshape((60000, 28 * 28))
# 数据类型转换
train_images = train_images.astype('float32') / 255

test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255

# 转换成二进制
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

# 在数据集上进行迭代
network.fit(train_images, train_labels, epochs=5, batch_size=128, callbacks=[TensorBoard(log_dir='./log')])
# 测试模式下损失值和指标值
test_loss, test_acc = network.evaluate(test_images, test_labels)

print('test_loss', test_loss, ', test_acc:', test_acc)

if __name__ == "__main__":
hello_world()

TensorFlow 作为其运行引擎,输出数据集格式:

image

这是运行过程简图,可以看出准确率随着迭代次数,越来越高,训练后模型在测试集上运行识别准确率差不多为 98%:

image

image

这里我们思考几个问题:

  1. 这个网络真的好像一个黑盒子,给了一些训练数据,然后就得出了一个模型,但是这个训练过程中,究竟向量间是怎么运算的,究竟特征值是怎么取的,每次运算的结果还不一样,那是不是就没有办法分析这个网络中究竟发生了什么,是不是觉得有点慌。如果一个人工智能指挥的战争,我们是不是都没有办法预测究竟发生了什么,指挥的命令是否符合人类最高价值观,想一想就会觉得有点可怕。

  2. 这个训练过程其实还是挺耗时的,或者说神经网络运行一般都是挺耗时的,因此这个问题怎么去处理,怎么去剪枝,让其可以在有限的时间内就可以得到可以接受的结果。这是不是就对 AlphaGo 有了一点不一样的理解。

  3. 这个网络究竟是怎么训练数据的,似乎也没写什么相关代码呀,好像也可以完成不少的事情,神经网络都这么简单吗?当然不是。在 network.fit 中最后最后一个参数是设置了callback,在控制台用 tensorboard --logdir=log 命令可以查看运行过程图,看不懂没关系,以后我们慢慢分析,截图如下:

image

image

今天,我们写了一个 Hello World,用的是 Keras,其底层内核是 TensorFlow,直观感性的复习一下之前聊过的知识,只看无益,去试一试吧!