读书会丨迷你AlphaGo的完整实现

百家 作者:程序人生 2018-08-25 02:05:32

点击上方“程序人生”,选择“置顶公众号”

第一时间关注程序猿(媛)身边的故事


PyTorchhttp://pytorch.org/)是一个人工神经网络开发库,利用PyTorch可以让机器实现人工神经网络,完成人工智能应用。PyTorch是最简单、最灵活的人工神经网络库之一。

人工神经网络就是由人工神经元组成的网络,而人工神经元是对输入进行线性组合再进行非线性操作。在确定人工神经网络的结构后,通过优化,为人工神经元内的权重设置合适的值,就可以发挥人工神经网络强大的功能。那么,如何让计算机实现人工神经元、搭建人工神经网络,并选择合适的权重呢?这就需要人工神经网络的开发软件来帮忙。PyTorch就是一种人工神经网络的开发软件。

在开发人工神经网络的过程中,PyTorch可以帮助我们做以下事情。

q确定人工神经网络的结构:我们只要告诉PyTorch神经网络中神经元的个数、每个神经元是什么样的(比如输入、输出、非线性函数),以及各神经元的连接方式,PyTorch就可以让计算机构建出这个人工神经网络的结构。

q确定人工神经元的权重值:只要告诉PyTorch什么样的权重值比较好,PyTorch就可以帮助我们找到合适的权重值。

q处理输入和输出:此外,PyTorch还可以和其他库合作,协助处理人工神经网络的输入和输出,把人工神经网络的计算结果展示出来。

有了人工神经网络开发工具PyTorch,我们不再需要编写复杂的代码去实现人工神经元,或是漫无目的地寻找合适的权重值。借助PyTorch,只需要一句话,就可以指定某些神经网络连接关系;只需要一句话,就可以指定神经元使用的非线性函数。而且,我们不需要手动为每个神经元寻找合适的权重。

PyTorch不仅简单好用,而且完全免费。PyTorch的源代码是完全公开的,你可以在https://github.com/pytorch/pytorch上找到所有的实现代码。

来看一个用PyTorch实现的完整应用。在这一节中你会看到一些使用PyTorch的Python语句。也许你不会Python,或是没有安装运行Python的软件,这都没有关系。本书后续的章节会详细介绍软件安装、Python编写和PyTorch的使用。本节只是希望你能对PyTorch的用法有个初步的了解。

1. 迷你AlphaGo介绍

本节一起来看一个小程序“迷你AlphaGo”。这个小程序完成了下面的功能:有一个连续可导的函数,它有4个输入,前3个输入是,第4个输入是,它能返回一个实数。我们并不清楚函数的具体形式。我们的目标就是对任意的,找到合适的,使得函数的值最大。用数学语言表示,就是给定函数,求解

这个问题可以用图2-2表示。图中标有问号“?”的方框就是我们想要求解的关系。

这个应用之所以称为“迷你AlphaGo”,是因为这个问题和AlphaGo试图解决的问题非常相似。如果我们把前三个输入看作围棋的当前局势,把看作下一步要下的棋,把函数看作胜率函数,那么这个问题就相当于在给定局势的情况下,找到最优的下棋策略,使得胜率最大(当然,AlphaGo实际比这个复杂得多,例如实际可选的下棋位置只是离散的几个网格交叉点,胜率函数不能非常容易地评估出来等。所以本节的例子只是AlphaGo的一个简化版本)。

“迷你AlphaGo”问题可以用人工神经网络求解。求解思路如下:用一个人工神经网络来代替从的关系。通过设计人工神经网络的结构、确定合适的参数,使得这个人工神经网络可以实现从的关系。值得一提的是,由于不知道函数的具体形式,所以也不知道从的最优关系的形式。实际上,从的关系甚至可能没有显式表达式。这再一次体现了人工神经网络的强大之处:我们不需要知道解答的形式,只需要搭建人工神经网络;我们不需要告诉机器神经网络中神经元的权重都是多少,PyTorch可以帮助找到神经元的权重。在完成神经网络的搭建、选取合适的权重后,这个人工神经网络就能够实现“迷你AlphaGo”的全部功能。

2. 迷你AlphaGo的完整实现

在这一节我们来看一个基于PyTorch的迷你AlphaGo的完整实现。完整实现分为4个部分。

q确定神经网络结构。这个部分确定神经网络中有几个神经元,神经元之间是怎么连接的。

q构造测试函数。这个部分确定要针对哪个函数来选择人工神经元的权重。显然,函数不同,设置的权重值就不同。

q设置人工神经元的权重值。根据测试函数,让PyTorch自动设置合适的神经元权重值。完成这步后,神经网络就完全确定了。

q测试人工神经网络的效果。这步验证之前实现的人工神经网络能够很好地完成“迷你AlphaGo”的功能。

接下来依次来看这四部分的完整代码。将这四部分完整代码依次拼接在一起,就得到了完整的程序(而不需要再添加其他任何代码)。代码下载地址参见本书前言部分。


注意:如果你觉得这些代码难以理解,请不用担心。这里只是希望你有一个初步的概念。本书的后续章节会逐步介绍如何理解或编写这些代码。等你读完本书,你也能写出这样的代码。


首先来看第一部分代码。如代码清单2-1所示,这部分代码的主要功能是确定神经网络的结构。具体而言,以“import”和“from”开头的第1行代码告诉计算机我要用PyTorch了,让机器做好准备。接下来用一个序列构造神经网络。在这个序列中,有表示连接的Linear类,也有表示非线性运算的ReLU类。在这个序列中一共有3个Linear类实例,说明这个神经网络有3层。第一个Linear类实例用参数3和8构造,这两个参数说明每个神经元都有3个输入,一共有8个神经元。这个序列中有两个ReLU类实例,也就是说,其中两个层的神经元的非线性函数都是

你可能会有疑问:为什么这个神经网络的最后一层没有使用非线性函数?这是因为,我们希望将要制作的“迷你AlphaGo”应用既能输出的结果,也能输出的结果。如果在最后的输出中设置了,那就不可能输出的结果。因此这里最后一层的神经元没有使用非线性函数

代码清单2-1神经网络结构搭建代码


from torch.nnimport Linear, ReLU, Sequential

net =Sequential(

        Linear(3, 8), # 1层有8个神经元

        ReLU(), # 1层神经元的非线性函数是max(·,0)

        Linear(8, 8), # 2层有8个神经元

        ReLU(), # 2层的神经元的非线性函数是max(·,0)

        Linear(8, 1), # 3层有1个神经元

        )


接下来看第二部分代码。在这部分中,将定义函数。当然,这个函数的形式可以是任意的,而且神经网络不需要知道这个函数的具体形式。但是,神经网络权重的确定和函数有关。函数不同,神经网络就需要不同的权重值。因此,给出函数是有必要的。这部分代码如代码清单2-2所示。这里的代码需要用到一些PyTorch的编程知识,我们目前只需要知道这段代码定义了函数

其中,


代码清单2-2函数的定义


defg(x, y):

    x0, x1, x2 = x[:, 0] ** 0, x[:, 1] ** 1,x[:, 2] ** 2

    y0 = y[:, 0]

    return (x0 + x1 + x2) * y0 - y0 * y0 - x0 *x1 * x2


接下来看第三部分代码。这部分代码见代码清单2-3。在这部分代码中,在PyTorch的帮助下为神经网络中的每个神经元找到合适的权重。在这段代码中,我们没有显式地为每个神经元指定权重值,而是使用了一个优化器。代码第3行构造了优化器optimizer。这个优化器每次可以改良所有权重值,但是这个改良不是一步到位的。我们需要让优化器反复改良很多次,才能让神经网络的所有权重都合适。在这段代码中以“for”开头的语句说明整个过程需要循环很多次(实际上是1000次),而后面缩进的语句都是要循环的内容。在循环的内容中,我们需要告诉优化器每次改良的依据是什么。因此后面缩进的代码先告诉优化器改良的依据,然后通过“optimizer.step()”语句完成权重的改良。完成循环后,神经网络中所有的权重值就都比较合适了。这时候我们说训练好了人工神经网络。

代码清单2-3使用优化器确定神经元的权重值


importtorch from torch.optim import Adam

 

optimizer= Adam(net.parameters())

forstep in range(1000):

    optimizer.zero_grad()

    x = torch.randn(1000, 3)

    y = net(x)

    outputs = g(x, y)

    loss = -torch.sum(outputs)

    loss.backward()

    optimizer.step()

    if step % 100 == 0:

        print ('{}次迭代损失 ={}'.format(step, loss))


那么,实现好的人工神经网络是不是正确完成了“迷你AlphaGo”的任务目标呢?第四部分的代码就来验证。这部分代码见代码清单2-4。这部分的代码又可以细分为三小部分。

生成测试数据。随机生成一些数据作为输入,我们将看到人工神经网络是不是能很好地计算出对应的。生成的输入数据被以“print”开头的语句输出在电脑屏幕上。

调用人工神经网络,看看在给定输入下神经网络的输出是什么。神经网络的输出和对应的函数的值被打印了出来。

计算理论最优结果作为参考。这部分并没有用到人工神经网络,只是用这个结果和神经网络的输出做比较。如果的具体形式为

,那么这个g实际上是一个关于y的二次函数,它的开口向下。利用二次函数的知识,可以知道,这个二次函数在

处取到最大值。因此,理论上的最佳输出为


这部分代码将理论上的最佳输出和最佳

输出对应的函数g的值打印了出来。

代码清单2-4验证生成的人工神经网络


# 生成测试数据

x_test= torch.randn(2, 3)

print('测试输入:{}'.format(x_test))

 

# 查看神经网络的计算结果

y_test= net(x_test)

print('人工神经网络计算结果:{}'.format(y_test))

print('g的值:{}'.format(g(x_test, y_test)))

 

# 根据理论计算参考答案

defargmax_g(x):

    x0, x1, x2 = x[:, 0] ** 0, x[:, 1] ** 1,x[:, 2] ** 2

    return 0.5 * (x0 + x1 + x2)[:, None]

yref_test= argmax_g(x_test)

print('理论最优值:{}'.format(yref_test))

print('g的值:{}'.format(g(x_test, yref_test)))


由于第四部分验证代码的输入是随机确定的,所以每次运行的输入和输出都不一样。下面给出某次运行结果:

测试输入: tensor([[0.2487,  0.3399, -0.4967],

        [ 1.0140,  0.1038, -0.1002]])

人工神经网络计算结果: tensor([[0.8289],

        [ 0.4975]])

g的值: tensor([0.5442,  0.3056])

理论最优值: tensor([[0.7933],

        [ 0.5569]])

g的值: tensor([0.5455,  0.3091])


比较神经网络的输出结果和理论计算结果,可以断定,我们的人工神经网络已经正确地输出了最优结果,实现了“迷你AlphaGo”的功能。


——节选自《神经网络与PyTorch实战》,作者:肖智清


推荐阅读

 《神经网络与PyTorch实战》

ISBN:978-7-111-60577-5

作 者:肖智清 著

定 价:59.00元

出版时间:2018/08

内容简介:

深度学习一线研发人员撰写,讲解神经网络设计与PyTorch应用 

以张量为基,以科学计算为线,以神经网络为面,以PyTorch为器,高效铸造AI应用


作者简介:肖智清 

深度学习一线研发人员,现就职于世界排名第一的投资银行,清华大学博士。擅长概率统计、随机过程、时间序列和机器学习。近5年发表SCI/EI论文十余篇,是多个顶级期刊和会议审稿人。在国内外多项程序设计和数据科学竞赛获得冠军。


本期评奖规则

扫描下方海报二维码,添加小助手,回复「分享」,小助手会邀你进群。免费听《神经网络与PyTorch实战》该书作者肖智清的分享。

分享结束后,会在群内抽出5名互动积极用户,免费送出作者著作一本!



详情参见“阅读原文

关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接