pybrain的神经网络文档部分翻译

Pybrain的安装

$ git clone git://github.com/pybrain/pybrain.git
$ python setup.py install

详细信息参看http://wiki.github.com/pybrain/pybrain/installation.

快速入门
神经网络是由模块(module)组成并且由连接组成,你可以把它看成是一个无环图,模块就是节点而边就是连接。创建网络的方式是:

>>> from pybrain.tools.shortcuts import buildNetwork
>>> net = buildNetwork(2, 3, 1)

返回一个双输入,三个隐藏层节点和单输出的神经元。这些层是模块对象并已形成全连接。这个网络已经由随机值初始化,我们可以使用activate方法计算输出,输入可以是一个列表,元组或者array:

>>> net.activate([2, 1])
array([-0.98646726])

神经网络的每个部分都有一个名称,你可以直接访问,用buildNetWork建立的时候,每个部分会自动命名:

>>> net['in']
<LinearLayer 'in'>
>>> net['hidden0']
<SigmoidLayer 'hidden0'>
>>> net['out']
<LinearLayer 'out'>

隐藏层神经元的名称后缀是数字,用于区分。当然我们更自由建立网络,比如默认情况下用的激活函数是sigmoid,但是在很多情况下,我们使用其他的函数:

>>> from pybrain.structure import TanhLayer
>>> net = buildNetwork(2, 3, 1, hiddenclass=TanhLayer)
>>> net['hidden0']
<TanhLayer 'hidden0'>

也可以为输出层设置不同的激活函数:

>>> from pybrain.structure import SoftmaxLayer
>>> net = buildNetwork(2, 3, 2, hiddenclass=TanhLayer, outclass=SoftmaxLayer)
>>> net.activate((2, 3))
array([ 0.6656323,  0.3343677])

我们还可以使用偏置因子:

>>> net = buildNetwork(2, 3, 1, bias=True)
>>> net['bias']
<BiasUnit 'bias'>

这些方式存在局限性,比如只能建立前向的拓扑结构,但是我们可以用pybrain建立精细的结构。

定义数据集
SupervisedDataSet类用于标准的监督学习。它支持输入值和目标值(target),数据大小需要在创建类时指定:

>>> from pybrain.datasets import SupervisedDataSet
>>> ds = SupervisedDataSet(2, 1)

我们产生了具有双输入和单输出的数据集。
一个经典的例子就是XOR函数,我们为数据集加入数据:

>>> ds.addSample((0, 0), (0,))
>>> ds.addSample((0, 1), (1,))
>>> ds.addSample((1, 0), (1,))
>>> ds.addSample((1, 1), (0,))

查看ds中的样本数量:

>>> len(ds)
4

我们可以迭代输出

>>> for inpt, target in ds:
...   print inpt, target
...
[ 0.  0.] [ 0.]
[ 0.  1.] [ 1.]
[ 1.  0.] [ 1.]
[ 1.  1.] [ 0.]

可以将输入和目标值分别输出为array

>>> ds['input']
array([[ 0.,  0.],
       [ 0.,  1.],
       [ 1.,  0.],
       [ 1.,  1.]])
>>> ds['target']
array([[ 0.],
       [ 1.],
       [ 1.],
       [ 0.]])

清除数据集dataset

>>> ds.clear()
>>> ds['input']
array([], shape=(0, 2), dtype=float64)
>>> ds['target']
array([], shape=(0, 1), dtype=float64)

训练神经网络
为了在有监督学习中调节参数,pybrain提出了trainer的概念,trainer训练模块使其拟合数据集。一个经典的训练就是反向传播:

>>> from pybrain.supervised.trainers import BackpropTrainer

我们使用建立的XOR数据集去训练网络:

>>> net = buildNetwork(2, 3, 1, bias=True, hiddenclass=TanhLayer)
>>> trainer = BackpropTrainer(net, ds)

现在trainer知道了网络和数据集,就可以在这个数据集上开始训练网络:

>>> trainer.train()
0.31516384514375834

这个命令调用train方法训练一个完整周期,并返回一个double类型的误差。要想训练至收敛,可以调用下面的方法:

>>> trainer.trainUntilConvergence()

返回每个训练周期的误差元组。
使用模块和连接建立网络
我们从基础开始介绍使用最基本的结构元素,FeedForward,RecurrentNetwork类,Module类以及Connetion类。
Feed Forward Networks
我们建立一个多层感知器:
首先建立一个对象

>>> from pybrain.structure import FeedForwardNetwork
>>> n = FeedForwardNetwork()

然后建立输入层,隐藏层和中间层。

>>> from pybrain.structure import LinearLayer, SigmoidLayer
>>> inLayer = LinearLayer(2)
>>> hiddenLayer = SigmoidLayer(3)
>>> outLayer = LinearLayer(1)

这里有很多类型的层,详细可以查看module的包。
我们把这个层加入到网络中。

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

实际上我们可以加入多层的输入和输出的模块,网络已经知道哪些是输出哪些是输入,这样就可以使输入值前向传播,误差值反向传播。
我们还需要指定连接方式,我们使用最常见的连接方式,层间全连接,就是将一层的每个神经元和另一层的每个神经元相连接。这个可以由FullConnection类实现:

>>> from pybrain.structure import FullConnection
>>> in_to_hidden = FullConnection(inLayer, hiddenLayer)
>>> hidden_to_out = FullConnection(hiddenLayer, outLayer)

和模块一样,也把它们加入到网络中:

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

所有元素就位了,让网络可用,调用sortModules()方法:

>>> n.sortModules()

网络内部初始化,这个在使用前的一步很关键,比如让模块按照拓扑结构排列。
测试一个网络:
输出网络并检查它们的结构:

>>> 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])

由于权重初始化时随机赋值,所以在不同的机子上的结果不同。我们可以查看连接的参数:

>>> 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])

命名网络结构
网络的零件在产生的时候就被自动命名,你可以在建立对象时传递一个name参数:

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

这样使输出更具可读性,并且名字可以在运行过程中保留。

循环神经网络
和前向传播类似的,

>>> from pybrain.structure import 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])

回到和初始建立时的一样。
使用前向传播网络分类
该教程带你建立分类数据集并训练一个神经网络并实现可视化。
首先导入必要的组件:

from pybrain.datasets  import ClassificationDataSet
from pybrain.utilities           import percentError
from pybrain.tools.shortcuts     import buildNetwork
from pybrain.supervised.trainers import BackpropTrainer
from pybrain.structure.modules   import SoftmaxLayer

可视化输出需要有pylab:

from pylab import ion, ioff, figure, draw, contourf, clf, show, hold, plot
from scipy import diag, arange, meshgrid, where
from numpy.random import multivariate_normal

为了可视化,我们产生了平面上的三类点,你也可以从文件中读取,比如使用
pylab.load()

means = [(-1,0),(2,4),(3,1)]
cov = [diag([1,1]), diag([0.5,1.2]), diag([1.5,0.7])]
alldata = ClassificationDataSet(2, 1, nb_classes=3)
for n in xrange(400):
    for klass in range(3):
        input = multivariate_normal(means[klass],cov[klass])
        alldata.addSample(input, [klass])

随机将数据集的75%划分给训练集,25%给测试:

tstdata, trndata = alldata.splitWithProportion( 0.25 )

针对神经网络分类,建议每个类别一个输出。

trndata._convertToOneOfMany( )
tstdata._convertToOneOfMany( )

打印出一些关于数据集的信息:

print "Number of training patterns: ", len(trndata)
print "Input and output dimensions: ", trndata.indim, trndata.outdim
print "First sample (input, target, class):"
print trndata['input'][0], trndata['target'][0], trndata['class'][0]

现在我们使用buildNetwork()建立含有5个隐藏单元的神经网络。输入层和输出层必须和数据集的输入和目标值维数匹配。你可以加入更多的隐藏节点。

fnn = buildNetwork( trndata.indim, 5, trndata.outdim, outclass=SoftmaxLayer )

建立一个训练者,训练者需要网络和训练数据作为输入。还有其他的训练者可以查看trainers,我们这里使用BackpropTrainer.

trainer = BackpropTrainer(fnn, dataset=trndata, momentum=0.1, verbose=True, weightdecay=0.01)

产生一个数据点的方形网络并形成一个数据集,然后分类得到等高线图。因此这里的目标值忽略。

ticks = arange(-3.,6.,0.2)
X, Y = meshgrid(ticks, ticks)

need column vectors in dataset, not arrays

griddata = ClassificationDataSet(2,1, nb_classes=3)
for i in xrange(X.size):
    griddata.addSample([X.ravel()[i],Y.ravel()[i]], [0])
griddata._convertToOneOfMany()  # this is still needed to make the fnn feel comfy

开始迭代训练神经网络。

for i in range(20):
trainer.trainEpochs( 1 )

评价神经网络在训练集和测试集上的表现,这里有几种方式,检查pybrain.tools.validation模块,我们可以让训练者进行测试。

trnresult = percentError( trainer.testOnClassData(),trndata['class'] )
tstresult = percentError( trainer.testOnClassData(dataset=tstdata ),tstdata['class'] )
print "epoch: %4d" % trainer.totalepochs, "  train error: %5.2f%%" % trnresult, \
       "  test error: %5.2f%%" % tstresult

我们通过FNN运行我们的网格数据,得到最可能的类别,并整理成一个方阵。

out = fnn.activateOnDataset(griddata)
out = out.argmax(axis=1)  # the highest output activation gives the class
out = out.reshape(X.shape)

绘制等高线图:

figure(1)
ioff()  # interactive graphics off
clf()   # clear the plot
hold(True) # overplot on
for c in [0,1,2]:
    here, _ = where(tstdata['class']==c)
    plot(tstdata['input'][here,0],tstdata['input'][here,1],'o')
    if out.max()!=out.min():  # safety check against flat field
        contourf(X, Y, out)   # plot the contour
    ion()   # interactive graphics on
    draw()  # update the plot
ioff()
show()

使用数据集
在pybrain中提供了一种更高等的数据结构,便于数据的处理。对于机器学习中的不同任务,不同的数据集类型具有共同的特征。一个数据集可以看成是2维的数组,本文中称为“字段(field)”。如果DS实现DataSet:

inp = DS['input']

返回输入字段,该字段的最后一维与输入维数一致。比如:

inp[0,:]

获取到第一个输入向量,通常还有一个“target”字段。通常情况下你需要迭代一个数据集类似这样:

for inp, targ in DS:
  ...

注意不论你得到一个或者多个样本行,依赖于数据集中的连接字段的数量,这些字段含有相同数量的样本并假定是同时使用的,就像上述的“input”和“target”字段。类似的,数据集可以逐一加入样本(清楚但是缓慢的做法),或者从数组引入。

for inp, targ in samples:
    DS.appendLinked(inp, targ)
  ...

or alternatively, with ia and ta being arrays:
assert(ia.shape[0] == ta.shape[0])
DS.setField(‘input’, ia)
DS.setField(‘target’, ta)
在后一个案例,DS不能检查连接数组的维度,否则无法从scratch中建立数据集。你可以把自己连接或者未连接的数据加入到数据集中,虽然许多训练算法在连接字段上迭代,但是如果它们的数量发生改变可能会发生错误:

DS.addField('myfield')
DS.setField('myfield', myarray)
DS.linkFields('input','target','myfield') # must provide complete list here

一个快速有效分割出训练集和测试集的方法是:

>>> len(DS)
100
>>> TrainDS, TestDS = DS.splitWithProportion(0.8)
>>> len(TrainDS), len(TestDS)
(80, 20)

监督回归训练用的数据集
“有监督回归训练数据集”最简单的形式是用于监督训练任务。这由字段”input”和“target”组成。它的大小是这样指定的:

>>> from pybrain.datasets import SupervisedDataSet
>>> DS = SupervisedDataSet( 3, 2 )
>>> DS.appendLinked( [1,2,3], [4,5] )
>>> len(DS)
1
>>> DS['input']
array([[ 1.,  2.,  3.]])

数据集中引入了序列的概念,在序列学习的任务中,它的形式被划分为各种长度的子序列。可以通过以下的方法获得:

getNumSequences()
getSequence(index)
getSequenceLength(index)

创建一个序列化的数据集,它依旧含有”input”和“target”字段。Sequentialdataset继承了SupervisedDataSet,这是一个带有序列长度的特例。为了填充数据集中的内容,我们可以在每个要存储的序列的开始使用newSequence()并用appendLinked()加入样式。我们可以在理论上由数组建立序列化的数据集,但是不要与索引字段向混淆。
一个典型的在序列化的数据集DS上的迭代方式是:

for i in range(DS.getNumSequences):
    for input, target in DS.getSequenceIterator(i):
       # do stuff

用于有监督分类的训练
该数据集用于处理分类问题,它的“target”定义为integer。它有一个额外的字段叫做“class”,这是对”target”自动打包,大部分情况下你用不到它。初始化数据集:
DS = ClassificationDataSet(inputdim, nb_classes=2, class_labels=[‘Fish’,’Chips’])
Labels是可选的,主要用于注释,目标数组应是一维的。目标值标签从0开始。如果你弄不明白标签有多少个,或者不明白setField()方法,可以使用assignClasses()或者calculateStatistics()得到类别的统计信息。

>>> DS = ClassificationDataSet(2, class_labels=['Urd', 'Verdandi', 'Skuld'])
>>> DS.appendLinked([ 0.1, 0.5 ]   , [0])
>>> DS.appendLinked([ 1.2, 1.2 ]   , [1])
>>> DS.appendLinked([ 1.4, 1.6 ]   , [1])
>>> DS.appendLinked([ 1.6, 1.8 ]   , [1])
>>> DS.appendLinked([ 0.10, 0.80 ] , [2])
>>> DS.appendLinked([ 0.20, 0.90 ] , [2])

>>> DS.calculateStatistics()
{0: 1, 1: 3, 2: 2}
>>> print DS.classHist
{0: 1, 1: 3, 2: 2}
>>> print DS.nClasses
3
>>> print DS.getClass(1)
Verdandi
>>> print DS.getField('target').transpose()
[[0 1 1 1 2 2]]

在分类时,如果类别是每类一个输出单元,很多算法会表现更好。ClassificationDataSet提供方法将输出的结果转化类标签数字

>>> DS._convertToOneOfMany(bounds=[0, 1])
>>> print DS.getField('target')
[[1 0 0]
 [0 1 0]
 [0 1 0]
 [0 1 0]
 [0 0 1]
 [0 0 1]]
>>> print DS.getField('class').transpose()
[[0 1 1 1 2 2]]
>>> DS._convertToClassNb()
>>> print DS.getField('target').transpose()
[[0 1 1 1 2 2]]

对应在序列化的分类中也有SequenceClassificationDataSet,融合了类的特征和Sequentialdataset。

黑盒优化Black-box Optimization
许多现实的问题可以看做是一个优化问题,比如搜索控制器(controller)最优的设置,最小化投资组合的风险,寻找游戏中的最佳策略等等。它涉及变量的数量,也就是问题的维度,每个变量都从集合中选取并最大(最小)化目标函数。
连续域优化
我们定义一个连续域的简单目标函数,比如平方和:

>>> def objF(x): return sum(x**2)

并给出起始位点:

>>> x0 = array([2.1, -1])

我们初始化一个优化算法,比如CMAES:

>>> from pybrain.optimization import CMAES
>>> l = CMAES(objF, x0)

所有算法默认参数是最大化目标函数,你可以利用minimize属性修改设定:

>>> l.minimize = True

我们创建对象时可以写为:CMAES(objF, x0, minimize = True)
停止标准可以在算法中指定,也可以在下列三个中指定:
maximal number of evaluations
maximal number of learning steps
reaching a desired value

>>> l.minimize = True
>>> l.maxEvaluations = 200

现在我们的优化程序已经建立,我们使用learn()方法学习,该方法努力优化变量直到满足终止条件,并返回一个参数的元组以及拟合的结果。

>>> l.learn()
(array([ -1.59778097e-05,  -1.14434779e-03]), 1.3097871509722648e-06)

广义优化:使用Evolvable*
我们优化的方式是在一般情况下让用户定义一个Evolvable并实现以下方法:
Copy()操作:
产生随机点的方法randomize()
Mutate()在搜索空间中移动一小步
Crossover()交叉操作产生同类。
优化算法由Evolvable的实例初始化,并用目标函数评估这个实例。
我们给出一个简单的示例:

>>> from random import random
>>> from pybrain.structure.evolvables.evolvable import Evolvable
>>> class SimpleEvo(Evolvable):
...     def __init__(self, x): self.x = max(0, min(x, 10))
...     def mutate(self):      self.x = max(0, min(self.x + random() - 0.3, 10))
...     def copy(self):        return SimpleEvo(self.x)
...     def randomize(self):   self.x = 10*random()
...     def __repr__(self):    return '<-%.2f->'+str(self.x)

这可以用HillClimer优化:

>>> from pybrain.optimization import HillClimber
>>> x0 = SimpleEvo(1.2)
>>> l = HillClimber(lambda x: x.x, x0, maxEvaluations = 50)
>>> l.learn()
(<-10.00->, 10)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值