卷积网络 CNN 学习笔记之一:我们是怎么认识0的

题图:Airbnb总部 绘于:2020年3月

最近在做人工智能方面的探索的时候,深感能找到的材料中,按照一定步骤编程就能得出结果的信息很多,但大家都把这个过程视为一个黑盒子,常说,这个过程我们就不知道为什么了,反正结果就是计算机有智能了。

我当然不满足于这个答案,于是把YouTube上面关于卷积网络( Convolutional Neural Network )的大量视频看完了以后,依然觉得缺少一些关于“人工智能到底是怎么工作的”这个问题讲清楚的资料。

至于完全不讨论代码,仅仅在很高的层面上大讲人工智能对于人类的影响的书,实在对于我这种希望动手搭建一些东西的人来说,帮助更加有限。

这也就是我想写一些文章,把我的关于人工智能的 “人文方面的思考” 和 “代码实践” 结合在一起来的原因。

最简单的问题

为了回答“人工智能到底是怎么认识事物的”,我们可以从人工智能届的 Hello World 的例子(注①)来开始尝试回答。这个例子,就是 MNIST 的数据集训练识别 0 – 9 的手写数字。

MNIST 数据集

人工智能领域和传统的编程领域很大的一个区别在于数据和代码的占比。想象一下,传统的编程中,估计 90% 的程序内容是代码,而代码中各种常量从存储角度占的比例或许不到 10% 。而人工智能领域,代码比较少,大头是数据。以 Glove 为例,代码只有 100K ,但是训练数据集是来自互联网的 60 亿个单词,训练结果是 1 G 的数据。代码和数据的比例就反过来了,99.999%是数据,0.001% 不到是代码。

人工智能领域很多的数据集都是以数据的来源的机构命名的。MNIST (Modified National Institute of Stands and Technology)就是这么个原始数据集。它包含用于训练的六万个手写的数字的图像,以及图像对应的数字(这个算是正确答案),还包含一万对用来测试准确度的同样结构的图像和正确答案。

这些图像得来的过程很巧妙,是从美国普查局收集的机读卡里面采样的,就是那种高考时用的卡片,上面手写自己的考号,然后把对应的数字旁边的黑色椭圆用2B铅笔涂黑。这样子不就有了一个天然的手写体图像和正确答案的对应的数据吗?有人就把60000个这样的手写体和正确答案打包,供机器学习的研究者使用,并且挑战谁能达到更高的识别率。

上代码,来看一看别人为我们准备好的数据

如下四行 python 代码就能用 tensorflow 从互联网上把这个 11.49M 的数据集下载到本地来。

# 导入著名的 tensorflow。 在命令行下用 pip3 install tensorflow 安装import tensorflow as tf# 从互联网上下载 mnist 数据集到本地 ~/.keras/datasets/mnist.npz# x_train, y_train 分别是是60000个训练图像和答案# x_test, y_test 分别是10000个测试图像和答案# 训练的算是日常习题,测试的才是高考题。为了计算机防止作弊,计算机读书的时候是不能看到高考试卷的(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()# 把第1001个数字的图像打印出来print(x_train[1000])# 把“正确答案”打印出来。结果应该是 0print(y_train[1000])

如果我们好奇这个里面的数据长成什么样子,可以用 print 直接打印出来,得到如下所示(可以左右滑动可以看到全貌)

[[  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0   0   0   0   0   0  36 146 254 255 251  95   6   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0   0   0   0   3  97 234 254 254 232 254 254  35   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0   0   0  89 140 254 254 174  67  33 200 254 190   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0   0 108 253 254 235  51   1   0   0  12 254 253  56   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0  12 216 254 244  55   0   0   0   0   6 213 254  57   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0  25 254 254 132   0   0   0   0   0   0 168 254  57   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0  45 254 243  34   0   0   0   0   0   0 168 254  57   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0 128 254 157   0   0   0   0   0   0   0 168 254  57   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0  19 228 254 105   0   0   0   0   0   0   7 228 254  57   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0  58 254 254  87   0   0   0   0   0   0  10 254 246  47   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0  58 254 254   9   0   0   0   0   0   0  10 254 210   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0  58 254 254   9   0   0   0   0   0   0 105 254  91   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   5 219 254   9   0   0   0   0   0  24 230 254  24   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0 216 254   9   0   0   0   0   0  84 254 251  23   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0 216 254  36   0   0   0   0  22 208 251  94   0   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0 129 254 120   0   0   0   3 140 254 229   0   0   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0  83 254 222  17   0   0  91 254 236  53   0   0   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0  18 235 254 134  21 119 237 254 124   0   0   0   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0   0  53 249 254 234 252 254 172   3   0   0   0   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0   0   0 116 237 254 254 133  20   0   0   0   0   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0] [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]]

原来,数据是60000个元素的数组,每个元素,是一个 28 行的数据,每一行有 28 个数,每个数都是从 0 到 255 之间的一个数字,代表灰度。0 就是纯黑,255 就是纯白,中间的数字代表从 0 到 255 之间的 256 档的灰度。

大家猜猜如上的这 28 x 28 = 784 个数字代表的是哪一个数字?

用我们从小就训练得炉火纯青的人肉神经网络判断,这排列成28行28列的 784 个数字后面代表的那一个数应该是 0 。看一下训练集里给出的正确答案,也是 0 。 

接下来,我们用三行 Python 语句把这个图像显示出来:

# 导入绘图工具 matplotlib。 在命令行下用 pip3 install matplotlib 安装import matplotlib.pyplot as plt# 把这个28x28的矩阵直接给 Matplot 画灰度图plt.imshow(x_train[1000], cmap="gray")# 显示出来plt.show()

如果说上面的那个纯数字拼出来的 0 还有点像《黑客帝国》里面的机师 Tank 眼中的场景的话,如下的图像就还原到人眼可以看到的世界。这个似乎更明确了,就是 0 ,没错了。

在 MNIST 数据集里面有 5923 个不同的人写的各种各样的 0 。之后我们会通过几行代码就可以训练计算机认识这个数字,并且识别准确率高达 99% 。

接下来的旅程,我们就从这个 0 开始。我希望来回答,“计算机怎么知道这是个 0 ” 这一个问题。

思考题

我希望你和我一样,深情的望着这个小圈圈,然后用灵魂拷问的方式来问自己:我是怎么知道这是个 0 的?

仔细的探索自己的神经网络的每个角落,拷问自己的大脑,是如何在0.01秒不到的时间就知道,这是一个 0。而不是 1 ,而不是 4 呢?是因为我看到了一个圈吗?那我怎么知道这是个圈呢?在我知道这是个圈之前,大脑里面到底发生了些什么呢?

注①:

C语言的 Hello World 是 printf(“Hello World”); 

Hadoop 的 Hello World 是 Word Count ,

而人工智能的 Hello World 一定就是 MNIST 识别数字。

发表回复

您的电子邮箱地址不会被公开。