Encog神经网络C#导论






4.95/5 (31投票s)
使用 Encog 框架为 C# 创建神经网络的介绍。
引言
本文档提供了使用 Encog 人工智能框架创建神经网络和神经网络编程的基础介绍。Encog 是一个可用于 Java 和 Microsoft .NET 的 AI 框架。在本文中,我将向您展示如何使用 Encog 为 C# 创建和训练一个非常基础的神经网络。我可能会在将来跟进更复杂的神经网络示例。但就目前而言,本文档展示了如何开始使用 Encog。
有一篇类似的文章展示了如何为 Java 完成同样的事情。您可以在 The Code Project 上找到它。 您可以在这里找到它。
背景
Encog 是一个先进的人工智能框架。使用 Encog,您可以创建高级神经网络应用程序。尽管 Encog 支持人工智能编程的其他方面,但本文档将重点关注神经网络编程。截至 2.3 版本,神经网络编程是 Encog 的主要焦点。Encog 在 LGPL(GNU 通用公共许可证)下发布。Encog 可以从以下 URL 下载: http://www.heatonresearch.com/encog/。
这是一个简单的入门示例,展示了如何创建一个识别 XOR 运算符的神经网络。XOR 运算符本质上是神经网络世界的“Hello World”。它经常被用来演示新的神经网络。
在向您展示如何使用 Encog 创建神经网络之前,了解神经网络的工作原理非常重要。几乎所有的神经网络都包含层。层是行为相似的神经元群。Encog 支持的不同类型的神经网络使用许多不同的层类型。但是,几乎每个神经网络都会有两个非常重要的层:输入层和输出层。输入层是您向神经网络输入数据的方式。输出层是您从神经网络获取响应的方式。
神经网络的输入和输出都是 C# double
值,即普通的浮点数。输入层和输出层都有一定数量的神经元。这决定了该层将处理多少个浮点数。输入层和输出层通常具有不同数量的神经元。决定输入层和输出层的结构就是您如何向神经网络定义您要解决的“问题”。
让我们看看如何创建一个能够执行 XOR 运算符的神经网络。XOR 运算符要求两个输入不同时,输出才为真。XOR 运算符的真值表可以表示如下:
0 XOR 0 = 0
1 XOR 0 = 1
0 XOR 1 = 1
1 XOR 1 = 0
我现在想创建一个可以执行此运算符的神经网络。这样的网络将有两个输入神经元和一个输出神经元。它将接受两个操作数并返回结果。
Using the Code
现在我们将看看这个示例的代码是如何构建的。这个示例是用 Encog v2.3 创建的,这是本文撰写时 Encog 的当前版本。Encog 2.3 DLL 文件随本示例的下载一起提供。您还需要 included 的 log4net 文件。您可能希望从本文前面提供的 URL 下载最新的 Encog JAR。
此示例打包为一个简单的 Visual Studio 项目。
神经网络在使用之前必须进行训练。要训练这个神经网络,我们必须提供训练数据。训练数据是 XOR 运算符的真值表。XOR 具有以下输入:
public static double[][] XOR_INPUT ={
new double[2] { 0.0, 0.0 },
new double[2] { 1.0, 0.0 },
new double[2] { 0.0, 1.0 },
new double[2] { 1.0, 1.0 } };
这些是 XOR 运算符所有可能的输入。同样,预期的输出也存储为数组。
public static double[][] XOR_IDEAL = {
new double[1] { 0.0 },
new double[1] { 1.0 },
new double[1] { 1.0 },
new double[1] { 0.0 } };
这两个数组将组合起来创建 XOR 运算符的训练数据。以下代码行将这两个数组组合起来创建训练数据:
INeuralDataSet trainingSet = new BasicNeuralDataSet(XOR_INPUT, XOR_IDEAL);
我们现在必须创建一个神经网络。以下代码行执行此操作:
BasicNetwork network = new BasicNetwork();
network.AddLayer(new BasicLayer(new ActivationSigmoid(), true, 2));
network.AddLayer(new BasicLayer(new ActivationSigmoid(), true, 6));
network.AddLayer(new BasicLayer(new ActivationSigmoid(), true, 1));
network.Structure.FinalizeStructure();
network.Reset();
您可以看到正在创建三个层。上面的三个 AddLayer
方法创建了这三个层。第一层是输入层,它有两个神经元。创建的最后一层是输出层,它有一个神经元。中间创建的层称为隐藏层。隐藏层帮助神经网络的其他部分学习。必须添加更多的隐藏神经元才能让神经网络学习更复杂的模式。对于 XOR 运算符来说,四个隐藏神经元已经足够多了。隐藏神经元的数量通常是一个试错过程。
调用上面的 Reset
方法会随机化网络中所有神经元之间的权重。这些随机权重不会让神经网络像 XOR 运算符一样工作。但是,我们稍后将看到的训练过程将优化这些权重,并鼓励神经网络产生类似于 XOR 运算符的输出。
ActivationSigmoid
类指定要使用的激活类型。Sigmoid 函数是一个不错的选择,因为我们在 XOR 运算符上不使用负值。如果网络需要识别负值,双曲正切激活函数将更合适。Encog 支持许多不同的激活函数,它们都有其独特的用途。
必须创建一个训练对象来训练神经网络。Encog 支持多种不同的训练方法。有些用于特定的神经网络类型。有些在不同类型的数据上表现更好。对于这种类型的神经网络,最好的“通用”训练器称为 RPROP(resilient propagation)。以下代码创建一个 RPROP 训练器:
ITrain train = new ResilientPropagation(network, trainingSet);
创建训练器后,我们应该进行一系列迭代。每次迭代都会使神经网络更接近于能够像 XOR 运算符一样工作。
do
{
train.Iteration();
Console.WriteLine("Epoch #" + epoch + " Error:" + train.Error);
epoch++;
} while ((epoch < 5000) && (train.Error > 0.001));
在每次迭代(或称为 epoch)中,我们都会检查误差。我们一直持续到误差低于 1%。误差定义了神经网络的输出与前面定义的理想输出之间的差距。
一旦神经网络得到了令人满意的训练,我们将使用它。我们将把每个输入馈送到神经网络并观察输出。以下代码执行此操作:
Console.WriteLine("Neural Network Results:");
foreach (INeuralDataPair pair in trainingSet)
{
INeuralData output = network.Compute(pair.Input);
Console.WriteLine(pair.Input[0] + "," + pair.Input[1]
+ ", actual=" + output[0] + ",ideal=" + pair.Ideal[0]);
}
我们遍历每个训练数据项,并显示神经网络的输出以及实际输出。程序的输出如下所示:
Epoch #1 Error:0.577117664847525
Epoch #2 Error:0.577117664847525
Epoch #3 Error:0.533613696022388
Epoch #4 Error:0.503211450802659
Epoch #5 Error:0.503000549513747
Epoch #6 Error:0.502288740107349
...
Epoch #40 Error:0.0206168956797096
Epoch #41 Error:0.00842597610945368
Epoch #42 Error:0.0011283298276187
Epoch #43 Error:0.000212804226087766
Neural Network Results:
0,0, actual=7.79044815631158E-07,ideal=0
1,0, actual=0.999959847028804,ideal=1
0,1, actual=0.999974904416701,ideal=1
1,1, actual=0.000101466036536172,ideal=0
正如您所见,神经网络经过多次迭代,误差百分比才降至 1% 以下。经过 43 次迭代后,网络训练完成。运行应用程序时,次数可能会多一些或少一些,因为神经网络从随机权重开始。
完成后,您将看到神经网络的实际输出。神经网络的输出并不完全匹配理想输出。这是可以预料的。然而,0.99 的值非常接近 1.0。同样,第一个模式显示的科学计数法数字接近于零。
关注点
本文演示了一个非常简单的神经网络应用程序。使用神经网络来创建 XOR 运算符有点大材小用。Encog 提供了许多更复杂的示例。我可能会在这里撰写更多文章来演示 Encog 的一些更高级的功能。
神经网络有趣之处在于,它的创建方式与传统程序完全不同。对于传统程序,您会考虑如何实现 XOR 运算符,并创建所有必要的编程逻辑来完成它。对于神经网络,您只需提供输入示例和预期的输出。由神经网络来学习如何提供这些预期的输出。通常,您真的不知道它实际上是如何学会提供其输出的。对于拥有数百个神经元的大型神经网络来说,情况尤其如此。