如何创建简单的 3 层神经网络并使用监督学习进行教学?

How to create simple 3-layer neural network and teach it using supervised learning?

基于PyBrain's tutorials我设法拼凑了以下代码:

#!/usr/bin/env python2
# coding: utf-8

from pybrain.structure import FeedForwardNetwork, LinearLayer, SigmoidLayer, FullConnection
from pybrain.datasets import SupervisedDataSet
from pybrain.supervised.trainers import BackpropTrainer

n = FeedForwardNetwork()

inLayer = LinearLayer(2)
hiddenLayer = SigmoidLayer(3)
outLayer = LinearLayer(1)

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

in_to_hidden = FullConnection(inLayer, hiddenLayer)
hidden_to_out = FullConnection(hiddenLayer, outLayer)

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

n.sortModules()

ds = SupervisedDataSet(2, 1)
ds.addSample((0, 0), (0,))
ds.addSample((0, 1), (1,))
ds.addSample((1, 0), (1,))
ds.addSample((1, 1), (0,))

trainer = BackpropTrainer(n, ds)
# trainer.train()
trainer.trainUntilConvergence()

print n.activate([0, 0])[0]
print n.activate([0, 1])[0]
print n.activate([1, 0])[0]
print n.activate([1, 1])[0]

本来应该学习异或函数的,但是结果看起来很随机:

0.208884929522

0.168926515771

0.459452834043

0.424209192223

0.84956138664

0.888512762786

0.564964077401

0.611111147862

你的方法有四个问题,看了之后很容易识别Neural Network FAQ:

  • Why use a bias/threshold?:你应该添加一个偏置节点。缺乏偏差使得学习非常有限:网络表示的分离超平面只能通过原点。有了偏置节点,可以自由移动,更好地拟合数据:

    bias = BiasUnit()
    n.addModule(bias)
    
    bias_to_hidden = FullConnection(bias, hiddenLayer)
    n.addConnection(bias_to_hidden)
    
  • Why not code binary inputs as 0 and 1?:您所有的样本都位于样本 space 的一个象限内。移动它们使其散布在原点周围:

    ds = SupervisedDataSet(2, 1)
    ds.addSample((-1, -1), (0,))
    ds.addSample((-1, 1), (1,))
    ds.addSample((1, -1), (1,))
    ds.addSample((1, 1), (0,))
    

    (相应地修复脚本末尾的验证码。)

  • trainUntilConvergence 方法使用验证来工作,并且做一些类似于 early stopping method 的事情。对于这么小的数据集,这没有意义。请改用 trainEpochs1000 epochs 已经足够网络学习这个问题了:

    trainer.trainEpochs(1000)
    
  • What learning rate should be used for backprop?:调整学习率参数。这是你每次使用神经网络时都会做的事情。在这种情况下,值 0.1 甚至 0.2 会显着提高学习速度:

    trainer = BackpropTrainer(n, dataset=ds, learningrate=0.1, verbose=True)
    

    (注意 verbose=True 参数。在调整参数时观察错误行为是必不可少的。)

通过这些修复,我得到了给定网络和给定数据集的一致且正确的结果,并且误差小于 1e-23