65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 上的神经网络

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (303投票s)

2006年11月19日

GPL3

13分钟阅读

viewsIcon

1326636

downloadIcon

73726

本文介绍了一个用于神经网络计算的 C# 库,以及它们在解决各种问题中的应用。

Sample Image - neuron.jpg

引言

众所周知,许多问题很难找到形式化的算法来解决。一些问题无法用传统方法轻松解决;一些问题甚至还没有解决方案。对于许多此类问题,可以使用神经网络,它们在很大范围内都表现出相当不错的结果。神经网络的历史始于 20 世纪 50 年代,当时提出了最简单的神经网络架构。在这一领域的初步工作之后,神经网络的想法变得相当流行。但随后该领域出现了崩溃,当时发现当时的神经网络在可应用的任务数量方面非常有限。在 20 世纪 70 年代,随着反向传播学习算法的多层神经网络思想的提出,该领域再次迎来了一个高峰。从那时起,许多不同的研究人员一直在研究神经网络领域,这导致了各种各样的神经网络架构,它们被应用于各种不同的问题。目前,神经网络可以应用于分类、识别、逼近、预测、聚类、记忆模拟以及许多其他不同的任务,而且它们的数量还在不断增长。

本文介绍了一个用于神经网络计算的 C# 库。该库实现了几种流行的神经网络架构及其训练算法,如反向传播、Kohonen 自组织映射、弹性网络、Delta 规则学习和感知器学习。该库的用法通过几个示例进行了演示

  • 分类(使用感知器学习算法训练的单层神经网络);
  • 逼近(使用反向传播学习算法训练的多层神经网络);
  • 时间序列预测(使用反向传播学习算法训练的多层神经网络);
  • 颜色聚类(Kohonen 自组织映射);
  • 旅行商问题(弹性网络)。

随附的压缩文件包含整个库的源代码、上述所有示例以及文章中未列出和讨论的一些附加示例。

本文无意提供神经网络的全部理论,您可以在互联网上的各种资源以及 CodeProject 上轻松找到这些理论。相反,本文假设读者对神经网络有一般的了解,因此本文的目的是讨论用于神经网络计算的 C# 库及其在不同问题中的应用。

使用库

在设计该库时,主要思想之一是使其灵活、可重用且易于使用和理解。与其将多个神经网络实体组合到一个类中而导致代码和设计的灵活性和清晰度丢失,不如将所有实体拆分为不同的类,使它们更容易理解和重用。一些神经网络库倾向于将神经元网络的实体与学习算法结合起来,这使得开发可应用于同一神经网络架构的另一种学习算法变得困难。另一些库和应用程序不提取诸如神经元、神经元层或层网络之类的实体,而是将整个神经网路架构实现为单个类。在某些情况下,哪种方法更好值得商榷,因为可能存在一些不寻常的神经网络架构,难以将其分解为层和神经元。在其他情况下,网络不倾向于多层架构,因此拥有一个额外的层实体可能没有用。但在大多数情况下,将所有这些实体拆分为不同的类是有益的,这不仅更容易理解,而且还允许重用所有这些组件,并从更小的通用件构建新的神经网络架构。

该库包含六个主要实体

  • Neuron - 所有神经元的基本抽象类,它封装了诸如神经元权重、输出值和输入值之类的通用实体。其他神经元类继承自基类,以添加其他属性并对其进行专门化。
  • Layer - 表示一组神经元。这是一个基本抽象类,它封装了所有神经元层的通用功能。
  • Network - 表示一个神经网络,它是一组神经元层。这是一个基本抽象类,它提供了通用神经网络的通用功能。要实现特定的神经网络架构,需要继承该类,并用任何神经网络架构的特定功能对其进行扩展。
  • IActivationFunction - 激活函数接口。激活函数用于激活神经元 - 一种神经元,其中计算其输入的加权和,然后将该值作为输入传递给激活函数,输出值成为神经元的输出值。
  • IUnsupervisedLearning - 无监督学习算法接口 - 在学习阶段仅向系统提供样本输入,而不提供期望输出的学习算法。系统的目标是组织自身以找到数据样本之间的相关性和相似性。
  • ISupervisedLearning - 监督学习算法接口 - 在学习阶段向系统提供样本输入和期望输出值的学习算法。系统的目标是泛化学习数据,并学会当仅提供输入值时提供正确的输出值。

AForge.Neuro class diagram

该库提供了以下神经网络架构

  • Activation Network - 神经网络,其中每个神经元将其输出计算为激活函数的输出,并且参数是其输入的加权和与阈值值的组合。网络可能由单层或多层组成。通过监督学习算法进行训练,该网络允许解决诸如逼近、预测、分类和识别等任务。
  • Distance Network - 神经网络,其中每个神经元将其输出计算为其权重值与输入值之间的距离。网络由单层组成,可以作为 Kohonen 自组织映射、弹性网络和 Hamming 网络等网络的基础。

不同的学习算法用于训练不同的神经网络,并用于解决不同的问题

  • Perceptron Learning [1] - 该算法可以被认为是第一个神经网络学习算法,其历史始于 1957 年。该算法可与单层激活网络一起使用,其中每个神经元都具有阈值激活函数。其应用范围相当小,仅限于线性可分数据的分类。
  • Delta Rule Learning [2] - 该算法是感知器学习算法之后的下一步。它利用激活函数的导数,并且只能应用于单层激活网络,其中每个神经元具有连续的激活函数而不是阈值激活函数。最流行的连续激活函数是单极和双极 S 型函数。由于该算法只能应用于单层网络,因此其应用主要限于某些分类和识别任务。
  • Back Propagation Learning [3] - 这是最流行和最知名的多层神经网络学习算法之一。它最初于 1974 年被描述,从那时起,它得到了广泛的研究并应用于各种各样的任务。由于该算法能够训练多层神经网络,因此其应用范围非常广泛,包括诸如逼近、预测、对象识别等任务。
  • SOM Learning [4] - 该算法由 Kohonen 开发,可以被认为是用于聚类问题最著名的无监督学习算法之一。它将神经网络视为一个二维节点图,其中每个节点可以代表一个单独的类别。该算法以这样一种方式组织网络,使得能够找到数据样本之间的相关性和相似性。
  • Elastic Network Learning [5] - 该算法类似于 SOM 学习算法的思路,但它将网络神经元视为一个节点环,而不是二维节点图。在学习过程中,该环会形成某种形状,代表一个解决方案。旅行商问题(TSP)是该学习算法最常见的演示之一。

AForge.Neuro help file

有关更多信息来源,该库提供了 HTML 帮助格式的帮助信息。

分类

Classification Application

此示例演示了使用具有阈值激活函数的单层激活网络以及感知器学习算法。网络中的神经元数量等于不同数据类的数量,并且每个神经元仅针对某个特定类进行训练。将数据样本输入到训练好的网络中,网络中的一个神经元应该被激活(产生输出 1),而所有其他神经元应该被禁用(产生输出 0)。数据样本的类别由激活神经元的编号确定。如果多个神经元被激活或没有神经元被激活,则网络无法正确分类呈现的数据样本。对于二维数据样本,可视化网络非常容易,因为每个神经元的权重和阈值代表一条线,将一个类与其他所有类分开。

// prepare learning data
double[][] input = new double[samples][];
double[][] output = new double[samples][];
// ... preparing the data ...

// create perceptron
ActivationNetwork network = new ActivationNetwork( new ThresholdFunction( ), 
                                                   2, classesCount );
// create teacher
PerceptronLearning teacher = new PerceptronLearning( network );
// set learning rate
teacher.LearningRate = learningRate;
// loop
while ( ... )
{
    // run epoch of learning procedure
    double error = teacher.RunEpoch( input, output );
    ...
}

尽管网络架构简单,但它可用于许多不同的分类/识别任务。该架构唯一的限制是网络只能分类线性可分数据。

逼近

Approximation Application

此示例演示了使用反向传播算法训练的多层神经网络,并将其应用于函数逼近问题。假设我们只知道函数在有限数量的点上的值,但我们希望在其他一些点上计算该函数的值,这些点在已知函数值的 minmax X 值范围内。在训练阶段,网络被训练以对给定的 X 值产生正确的函数值。训练完成后,该网络用于计算训练过程中未提供给网络的其他不同值。

// prepare learning data
double[][] input = new double[samples][];
double[][] output = new double[samples][];
// ... preparing the data ...
// create multi-layer neural network
ActivationNetwork    network = new ActivationNetwork(
    new BipolarSigmoidFunction( sigmoidAlphaValue ),
    1, neuronsInFirstLayer, 1 );
// create teacher
BackPropagationLearning teacher = new BackPropagationLearning( network );
// set learning rate and momentum
teacher.LearningRate = learningRate;
teacher.Momentum     = momentum;
// loop
while ( ... )
{
    // run epoch of learning procedure
    double error = teacher.RunEpoch( input, output ) / samples;
    ...
}

网络架构不仅可用于逼近二维函数。任意维度的函数都可以用多层神经网络进行逼近。但不要忘记,网络的层数和神经元数量以及 S 型函数的 alpha 值等参数可能会非常剧烈地影响学习速度。您网络的一些不正确设置可能导致根本无法学习任何内容。所以,请谨慎并尝试更多实验。

时间序列预测

Time Series Prediction Application

此示例还演示了具有反向传播学习算法的多层神经网络,但应用于不同的任务——时间序列预测。时间序列预测问题非常重要且流行,许多研究人员在该领域尝试了许多不同的算法和方法。通过查看其应用领域,可以轻松解释该问题的受欢迎程度。一个受欢迎的领域是交易——如果您可以预测股票或货币汇率的未来值,那么……如果您能做得非常好,那么您可能会变得富有。但是,让我们回到神经网络。在训练阶段,将一定数量的时间序列的先前值输入到网络中,然后训练网络来预测时间序列的下一个值。您拥有的训练样本越多,您获得的预测模型就越好。此外,一个非常重要的参数是窗口大小——有多少历史值用于预测未来的值。窗口越大,模型就可能越好,但也不一定——这取决于时间序列,需要实验。但是,更大的窗口大小将减少您需要的训练样本数量,因此这是一个权衡值。

此问题的样本代码与上一个示例相同,只有学习数据的准备过程发生了变化。

颜色聚类

Color Clusterization Application

这是一个非常简单的示例,演示了 Kohonen 自组织映射的组织过程。创建了一个方形 SOM 网络,由 10000 个具有随机初始化权重的神经元组成。每个神经元有三个权重,这些权重被解释为可视化的 RGB 值。因此,网络的初始可视化将显示某种噪点彩色地图。在学习过程中,一次随机选择一种颜色并将其输入到网络。通过重复学习迭代,神经网络会组织自己,使其在可视化时不再像随机图片,而是具有某种结构——在 RGB 调色板上相近的颜色在 Kohonen 图上也更靠近。

// set neurons weights randomization range
Neuron.RandRange = new DoubleRange( 0, 255 );
// create network
DistanceNetwork network = new DistanceNetwork( 3, 100 * 100 );
// create learning algorithm
SOMLearning trainer = new SOMLearning( network );
// input
double[] input = new double[3];
// loop
while ( ... )
{
    // update learning rate and radius
    // ...

    // prepare network input
    input[0] = rand.Next( 256 );
    input[1] = rand.Next( 256 );
    input[2] = rand.Next( 256 );

    // run learning iteration
    trainer.Run( input );
    
    ...
}

玩弄这个示例,您会发现神经网络总是创建不同的图片,观察地图的组织过程非常有趣。也许可以作为屏幕保护程序的想法……

而不是颜色,可以使用任何其他可以由实值特征向量描述的对象。在学习过程中将这些特征向量输入到 Kohonen 地图中,将导致其组织,因此在训练过程完成后,您可以查看二维地图,并发现哪些对象根据其特征彼此相似且靠近。

旅行商问题

Traveling Salesman Problem Application

旅行商问题演示了弹性网络的用法,该网络在自组织概念上与 SOM 相似,但在神经网络的解释上有所不同。SOM 将神经网络解释为二维节点图,而弹性网络将其解释为节点环。在训练阶段,特征向量逐个输入到网络中,这使得网络形成某种代表解决方案的形状。对于 TSP 问题,网络中的每个神经元都有两个权重,代表 (X, Y) 坐标。在训练阶段,城市坐标逐个输入到网络中,网络组织其权重,使其代表旅行代理的路径。

// set random generators range
Neuron.RandRange = new DoubleRange( 0, 1000 );
// create network
DistanceNetwork network = new DistanceNetwork( 2, neurons );
// create learning algorithm
ElasticNetworkLearning trainer = new ElasticNetworkLearning( network );
// input
double[] input = new double[2];
// loop
while ( ... )
{
    // set network input
    int currentCity = rand.Next( citiesCount );
    input[0] = map[currentCity, 0];
    input[1] = map[currentCity, 1];

    // run one training iteration
    trainer.Run( input );
    ...
}

此方法的缺点是它不能提供精确的解决方案——神经元的权重可能接近城市坐标,但可能不等于它们。此方法的另一个缺点是它在大量城市上无法产生良好的结果。但仍然,该方法是神经网络应用的一个很好的演示。

结论

提供的五个示例表明,该库的最初目标已经实现——它灵活、可重用,并且易于用于不同任务。尽管由于神经网络架构及其学习算法种类繁多,还有很多工作要做,但该库仍然可以用于许多不同的问题,并且可以扩展以解决更多问题。我希望该库不仅对我的进一步研究工作有用,而且其他不同的研究人员也会发现它有趣且有用。

参考文献

  1. 感知器,来自 Wikipedia,自由的百科全书。
  2. Delta 规则,来自 Wikipedia,自由的百科全书。
  3. 反向传播,来自 Wikipedia,自由的百科全书。
  4. 自组织映射,来自 Wikipedia,自由的百科全书。
  5. 弹性网络教程,Andrei Cimponeriu,1999 年 10 月 12 日。

历史

  • [2006年11月19日] - 文章初次发布。
© . All rights reserved.