翻译Deep Learning and the Game of Go(7)开始使用神经网络

这一章包括

  • 介绍了人工神经网络的基本原理
  • 讲授一种识别手写数字的网络
  • 通过堆叠层来创建神经网络
  • 从数据中学习从而实现一个简单的神经网络

本章介绍了人工神经网络(ANN)的核心概念,它是现代深度学习的核心算法。令人惊讶的是,人工神经网络的历史可以追溯到20世纪40年代初。耗费了几十年时间,它的应用程序才在许多领域取得巨大成功,但其基本思想仍然有效。

人工神经网络的核心是从神经科学中获得灵感,并建立一类与我们大脑部分功能相类似的算法,特别的,我们使用神经元的概念作为我们人工神经网络的基本单位。神经元的群体我们称为层,这些层以特定的方式相互连接来跨越网络。给定输入数据,神经元可以通过连接实现层层之间传递信息,如果信号足够强,我们可以称它们已经激活了。在这种方式中,数据通过网络传播直到最后一步,到了输出层,我们就从中得到我们的预测。然后,这些预测可以与预期的输出进行比较来计算预测的误差,网络使用该误差来学习并改进对未来的预测。

虽然大脑启发的架构类比有时是有用的,但我们不想在这里过度强调它,因为即使我们知道很多关于大脑视觉皮层方面的知识,这种类比有时还是会误导甚至有害。我们认为最好把人工神经网络看作是试图揭示生物学习的指导原则,就像造飞机使用空气动力学而不是去复制一只鸟。

为了使本章更加具体,我们从零开始提供一个神经网络的基本实现。您将应用此网络来解决来自光学字符识别(OCR)的问题,即如何让计算机预测手写数字的图像上是哪个数字。

我们的OCR数据集中的每幅图像都是由网格上的像素组成的,您必须分析像素之间的空间关系来找出它代表的数字。围棋,就像其他许多棋盘游戏一样,是在一个网格上玩的,你必须考虑棋盘上的空间关系,才能选择一个好的落子点。你可能希望OCR的机器学习技术也能应用于围棋这样的游戏。结果是,他们可以做到。第6章到第8章展示了如何将这些技术应用于围棋游戏中。

本章中,我们把相关的数学知识放得比较少。如果你不熟悉线性代数、微积分和概率论的基础知识,或者需要一个简短而实用的知识,我们建议你先阅读附录A。.此外,神经网络学习过程中更困难的部分可以在附录B中找到。如果你知道神经网络,但从来没有实现过,我们建议你直接跳转到5.5节。如果您既熟悉又实现过神经网络,请直接跳到第6章。在该章中,您将应用神经网络来预测第4章中生成游戏的落子点。 

5.1.一个简单的用例:分类处理

在详细介绍神经网络之前,让我们从一个具体的用例开始。在本节中,您将构建一个应用程序,该应用程序可以合理地预测手写图像数据中的数字,准确率约为95%。值得注意的是,您只需将图像的像素值暴露在神经网络中,就可以做到这一点;该算法将学习提取有关数组结构本身的相关信息。

您将使用修改后的国家标准和技术研究所(MNIST)的手写数字数据集,这是一个在机器学习和深度学习实践中精心研究的数据集。

在本节中,您将使用NumPy库来处理低级别数学运算。NumPy是机器学习和使用Python进行数学计算的行业标准,您将在整本书的其余部分使用它。在尝试本章中的任何代码示例之前,您应该使用包管理器来安装NumPy。如果您使用pip,请从shell中运行pip install numpy来安装它。如果使用conda,运行conda install numpy..

5.1.1.手写数字的MNIST数据集 

该MNIST数据集由6万幅图像组成,每幅图像都是28×28像素。这些数据的几个例子如图5.1所示。对人类来说,识别这些图像是一件微不足道的事情,你可以识别出第一行是7、5、3、9、3、0等。但在某些情况下,即使是人类也很难理解这幅画所代表的内容。例如,图5.1中的第五行的最后一个数是4或9 都有可能

在MNIST中的每个图像都有一个标签,一个从0到9的数字来表示图像上描绘的真实值。

在你看数据之前,你需要先加载它。在关于这本书的GitHub仓库的文件夹http://mng.bz/P8mn.中找到一个名为mnist.pkl.gz的文件。

在这个文件夹中,您还将找到在本章中编写的所有代码。像以前一样,我们建议您在遵循本章的流程并构建代码库时,也可以运行GitHub存储库中找到的代码。

5.1.2.MNIST数据预处理

由于此数据集中的标签是从0到9的整数,所以您将使用一种名为one-hot编码(注:又称为一位有效编码,主要是采用N位状态寄存器来对N个状态进行编码,每个状态都有它独立的寄存器位,并且在任意时候只有一位有效)的技术,将数字1先转换为长度为10的全部为0的向量,然后在下标为1的地方放置。这种表示在机器学习中是有用的,且是广泛使用的。为标签1保留向量中的一个槽,可以允许诸如神经网络这样的算法更容易的区分这些标签。例如,使用one-hot编码,数字2具有以下表示形式:[0,0,1,0,0,0,0,0,0,0]

import numpy as np
import gzip
import six.moves.cPickle as pickle


#给标签进行one-hot编码
def encode_label(j):
    e = np.zeros((10,1))
    e[j] = 1
    return e

one-hot编码的好处是使得每个数字都有自己的“插槽”,这样你就可以使用神经网络来输出一个输入图像的概率,这将在后面有用。

检测文件mnist.pkl.gz的内容,您可以访问三个数据池:训练、验证和测试数据。从第一章中回想起来,你会使用训练数据去训练出一个适合的机器学习算法并使用测试数据来评估算法的有效程度。验证数据可以用来调整和验证算法的配置,但在本章中可以被忽略。

图片在MNIST数据集中是二维的,高度和宽度都是28个像素。您将图像数据加载到大小为28×28=784的特征向量中,这里您将完全丢弃图像结构而只看表示为向量的像素。这个向量的每个值表示0到1之间的灰度值,0是白色的,1是黑色的。


#加载数据的实现
def load_data_Impl():
     #加载数据文件
     file = np.load("mnist.npz")
     #得到文件里的训练数据
     x_train, y_train = file['x_train'], file['y_train']
     #得到文件里的测试数据
     x_test, y_test = file['x_test'], file['y_test']
     file.close()
     return (x_train, y_train), (x_test, y_test)


#加载数据
def load_data():
   train_data,test_data = load_data_Impl()
   return shape_data(train_data),shape_data(test_data)

您现在可以简单地表示MNIST数据集;特征和标签都被编码为向量。您的任务是设计一种机制,去学习如何准确地将特征映射到对应的标签上。从本质上说,您希望设计一种算法,该算法通过特征和标签的训练来学习,以便它能够预测测试特征的标签。

神经网络可以很好地完成这项工作,这个你会在下一节看到。但让我们首先讨论一个天真的想法,它将向您展示您在这个应用程序必须要解决的一般问题。识别数字对人类来说是一项相对简单的任务,但我们很难准确地解释是如何做到这一点,以及我们如何知道我们识别的准确性,这种知道比你能解释得还多的现象被称为波拉尼式悖论。这使我们特别难以明确地说明如何解决这个问题。

其中一个至关重要的方面就是模式识别——每一个手写数字都有一定的特征,这些特征来源于它的原型数字版本。例如,0大致是一个椭圆形,在许多国家,一个1只是一条垂直线。考虑到这种启发式算法,你可以通过将手写数字与其他手写数字进行比较来进行分类:给定一个8的图像,这个图像应该比任何其他数字更接近8的平均图像。下面的average_digital函数为您做到了这一点。

# 计算数据中所有样本的平均值来表示一个给定的数字
def average_digit(data,digit):
    # x[0]表示特征向量,x[1]表示标签
    filtered_data = [x[0] for x in data if np.argmax(x[1]) == digit]
    filtered_array = np.asarray(filtered_data)
    return np.average(filtered_array, axis=0)


train, test = load_data()
# 使用平均的8来作为简单模型的参数来检测8
avg_eight = average_digit(train, 8)

在你的训练集中,这个平均8是什么样子的?,如下图所示

因为笔迹在个体之间可能有很大的不同,正如预期的那样,平均8是有点模糊,但它形状仍然像一个8。也许你可以使用这个在您的数据集中去识别其他的8?您使用下面的代码来计算和显示上图

#显示平均8
img = (np.reshape(avg_eight,(28,28)))
plt.imshow(img)
plt.show()

在MNIST的训练集中,表示8的平均---avg_eight应该包含很多说明一张图像有8的含义。您将使用avg_eight作为参数用于判断给定输入向量x是否为8的简单模型。在神经网络的背景下,我们提到参数时经常会提到权重,avg_eight可以表示为你的权重

为了方便起见,您将使用矩阵转置方法并定义W=np.transpose(avg_eight)。然后,您可以计算W和x的点积,对W和x的值进行逐点相乘,并相加得到784个结果值。如果你的启发式算法是正确的,如果x是一个8,个别像素应该与W相同有一个较暗的色调.。相反,如果x不是8,则应该少一点重叠。让我们用几个例子来验证这个启发式算法。

x_3 = train[2][0]
x_18 = train[17][0]
W = np.transpose(avg_eight)
#点积
np.dot(W, x_3)
np.dot(W, x_18)

你计算两个MNIST样本与w的点积来计算权重,一个代表4,一个代表8。你可以看到后一个结果是54.2,远远高,于代表4的20.1。现在,你如何决定一个结果值是否足够高以至于能预测一个8?原则上,两个向量的点积可以得到任何实数,你需要解决的问题是将点积的输出转换为范围0-1的数。例如,你可以定义预测8的阈值是0.5

一种方法是使用Sigmoid函数。这个Sigmoid函数通常用s来表示,来源于希腊单词sigma。对于实数x,这个sigmoid函数定义为:

下图展示了这个图像

 接下来,让我们在Python中编写Sigmoid函数,然后将其应用于点积的输出。

import numpy as np


def sigmoid_double(x):
    return 1.0/(1.0+np.exp(-x))


def sigmoid(z):
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值