PyBrain官方Tutorial翻译(一)

来源:互联网 发布:gta5妹子捏脸数据 编辑:程序博客网 时间:2024/04/29 18:18

http://www.pybrain.org/docs/


1.介绍

PyBrain的主旨是将不同的数据处理算法封装到模块(Module)里。最小的模块包括一个依赖可自由调节参数的向前实现,一般通过一些机器学习算法。

模块有输入缓冲、输出缓冲和相应的应用在错误反向传播算法中的错误缓冲。

模块集成在网络(Network)类别的对象上,由连接(Connection)对象连接起来。他们自身也可能包括一系列可调节的参数,例如权重等。

注意一个网络本身也是一个模块,方便建立分层网络。除了提供构建最常见的网络结构的快捷键之外,原则上只要是有向非循环图,系统允许集成几乎任意的连接系统。

网络的自由参数通过训练(Trainer)进行调整,例如通过数据集(Dataset)去学习最优参数。但在强化学习实验中,会使用包含优化任务的模拟环境而非数据集。


2.   用模块和连接构建网络

本章将会指导你使用PyBrain最基本的结构元素:向前反馈网络(FeedForwardNetwork)和循环网络(RecurrentNetwork),和对应的模块对象和连接对象。我们已经知道如何用buildNetwork快捷键创建网络—但因为这项技术的种种限制,我们现在探查如何从最底层(ground up)创建网络。

2.1. Feed Forward Networks

我们会从简单的例子开始建立一个多层感知器。

首先我们创建一个新的FeedForwardNetwork对象:

>>> frompybrain.structureimport FeedForwardNetwork
>>> n= FeedForwardNetwork()

 

然后,我们构建输入层、隐藏层和输出层:

>>> frompybrain.structureimport LinearLayer, SigmoidLayer
>>> inLayer= LinearLayer(2)
>>> hiddenLayer= SigmoidLayer(3)
>>> outLayer= LinearLayer(1)

要想知道所有不同类别的层,可以查看modules包。 在使用它们之前,我们需要把它们加入网络:

>>> n.addInputModule(inLayer)
>>> n.addModule(hiddenLayer)
>>> n.addOutputModule(outLayer)

我们可以添加若干层的输入和输出模块。但是要明确告知哪些模块是输入,哪些是输出,便于向前传递输入和向后传递错误。

还需要具体指定它们如何连接。这里我们使用最常见的连接类型,即层与层之间的完全连接,将每一层的每一个神经元与其他(邻近)层的每一个神经元连接。在FullConnection类别里得到了实现:

>>> frompybrain.structureimport FullConnection
>>> in_to_hidden= FullConnection(inLayer, hiddenLayer)
>>> hidden_to_out= FullConnection(hiddenLayer, outLayer)

和模块一样,我们要具体指定的将它们加入网络中:

>>> n.addConnection(in_to_hidden)
>>> n.addConnection(hidden_to_out)

 

所有的元素都在适当的位置了,现在只差最后一步就可以让我们的MLP跑起来了,叫做.sortModules()方法:

>>> n.sortModules()

这个招呼实现了网络最终使用前,一些必要的内部初始化:例如,模块按照拓扑排序等。

1.2.       Examining a Network

我们可以直接打印出网络来检查它们的结构:

>>> print n
FeedForwardNetwork-6
Modules:
 [<LinearLayer 'LinearLayer-3'>, <SigmoidLayer 'SigmoidLayer-7'>, <LinearLayer 'LinearLayer-8'>]
Connections:
 [<FullConnection 'FullConnection-4': 'LinearLayer-3' -> 'SigmoidLayer-7'>, <FullConnection 'FullConnection-5': 'SigmoidLayer-7' -> 'LinearLayer-8'>]

注意输出在你们的电脑上可能会有所不同。

一种使用这个网络的方法是使用一个被转换的输入,招呼它本身的‘activate()’方法:

>>> n.activate([1,2])
array([-0.11302355])

再次注意,在你的电脑上可能结果会有所不同,因为连接权重的初始化是随机的。可以检查.params领域的连接,来查看这些参数。

我们可以直接取得连接的可训练参数(权重),或者一次性读取所有网络权重:

>>> in_to_hidden.params
array([ 1.37751406,  1.39320901, -0.24052686, -0.67970042, -0.5999425 , -1.27774679])
>>> hidden_to_out.params
array([-0.32156782,  1.09338421,  0.48784924])

网络封装模块也有这些参数。可以如下检测到:

>>> n.params
array([ 1.37751406,  1.39320901, -0.24052686, -0.67970042, -0.5999425 ,
     -1.27774679, -0.32156782,  1.09338421,  0.48784924])

可见最后三个网络参数等于第二层连接的参数值。

1.3.       Naming your Networks structure

在某些情况下,需要给网络不同部分起具体的名字。结构化组件源起Named类别,所以可以通过它们的.name属性来命名,否则会自动生成一个新名字。

从属类别可以在初始化的时候,通过传递.name自变量来命名:

>>> LinearLayer(2)
<LinearLayer 'LinearLayer-11'>
>>> LinearLayer(2, name="foo")
<LinearLayer 'foo'>

使用自己命名的网络,打印结果会更加简洁和可读。并且保证每次运行程序,都会按照相同的名称来显示。

1.4.       Using Recurrent Networks

要允许循环性,网络必须可以“及时向后看”。由于这样,RecurrentNetwork类别和FeedForwardNetwork有实质上的区别,即保存了完全的历史记录。很占记忆空间,但是学习算法所必需的。

创建一个循环性网络,基本和之前一样,选择适当的类别即可:

>>> frompybrain.structureimport RecurrentNetwork
>>> n= RecurrentNetwork()

我们很快可以建立一个和上面例子一样的网络:

>>> n.addInputModule(LinearLayer(2, name='in'))
>>> n.addModule(SigmoidLayer(3, name='hidden'))
>>> n.addOutputModule(LinearLayer(1, name='out'))
>>> n.addConnection(FullConnection(n['in'], n['hidden'], name='c1'))
>>> n.addConnection(FullConnection(n['hidden'], n['out'], name='c2'))

RecurrentNetwork类别多一个.addRecurrentConnection(), 每次可以回看一个timestep。我们可以在隐藏层之间多加一层:

>>> n.addRecurrentConnection(FullConnection(n['hidden'], n['hidden'], name='c3'))

如果现在我们激活网络,会每次得到不同的输出:

>>> n.sortModules()
>>> n.activate((2,2))
array([-0.1959887])
>>> n.activate((2,2))
array([-0.19623716])
>>> n.activate((2,2))
array([-0.19675801])

当然,我们可以清空网络历史,通过召唤reset方法来实现:

>>> n.reset()
>>> n.activate((2,2))
array([-0.1959887])
>>> n.activate((2,2))
array([-0.19623716])
>>> n.activate((2,2))
array([-0.19675801])

在召唤.rest()之后,我们将得到和对象创建时一样的输出结果。


0 0