1.6 实践神经网络
本书将会用Java编程语言来实现一个神经网络的整个过程。Java于20世纪90年代由太阳微系统公司(Sun Microsystems)的工程师发明,是一种面向对象的编程语言,其所有权于2010年被甲骨文公司(Oracle)获得。如今,Java运行在许多设备中,这些设备已成为我们日常生活的一部分。
在Java等面向对象语言中,我们同类和对象打交道。类是真实世界中某些事物的模板,而对象则是这种模板对应的实例,有点像汽车(代表所有以及各种车的类)和我的汽车(代表某辆特定的车)。Java类往往由属性和方法(或者函数)构成,它包含了面向对象编程(object-oriented programming, OOP)的概念。由于本书的目标只是从实践的角度来设计和创建神经网络,所以我们只会对这些概念进行一个简短的回顾,而不做深入的探究。在这个过程中,需要了解4个相关概念。
• 抽象:将真实世界的问题或者规律转录到某个计算机编程领域,只考虑其相关特征而忽略那些经常阻碍发展的细节。
• 封装:类似于由一些公开披露的特性所组成的产品包装(public方法),然而其他方法被隐藏在它们的域中(private或者protected方法),这样可以避免误用信息或者滥用信息。
• 继承:在真实世界中,多个类的对象可以以一种分层的方式共用属性和方法;例如,某种交通工具可以是汽车和卡车的父类。所以,在面向对象编程中,这个概念允许一个类继承另一个类的所有属性,从而避免了代码的改写。
• 多态:和继承几乎一样,但是区别在于不同的类中的相同签名的方法可以呈现出不同的行为。
根据本章介绍的神经网络和面向对象编程的概念,我们接下来将设计第一个实现神经网络的类集。神经网络包含层、神经元、权值、激活函数和偏置,层的类型主要有3种:输入层、隐藏层和输出层。每一层包含一个或者多个神经元。每个神经元都被连接到某个神经输入/输出或者另一个神经元,这些连接称为权值。
要特别强调一点,神经网络可以有许多隐藏层,也可以一个都没有,每一层的神经元数量也会变化。但是,输入和输出层的神经元数量分别与神经输入和神经输出的数量相等。
接下来,让我们开始实现。首先,我们来定义6个类,细节如表1-3所示。
表1-3
续表
续表
续表
续表
OOP语言的一个优势是易于在统一建模语言(UML)中用文档来表现程序。UML类图以一种简单而直观的方法展现了类、属性、方法和不同的类之间的关系,这样就能帮助程序员及其利益相关者将整个项目作为一个整体来理解。图1-9展现了该项目的最初版本类图。
图1-9
现在,让我们来应用这些类得到一些结果。下面展示的代码有一个测试类、一个main方法和一个名为n的NeuralNet类的对象。当这个方法被调用(通过类执行时),它会从对象n中调用initNet()和printNet()方法,生成如图1-10所示的结果。它表示了一个神经网络,输入层有两个神经元,隐藏层有3个神经元,输出层有一个神经元:
public class NeuralNetTest { public static void main(String[] args) { NeuralNet n = new NeuralNet(); n.initNet(); n.printNet(); } }
需要记住的是每次运行代码,会生成相应的新的伪随机权值。所以,当你运行这段代码时,其他值将会出现在控制台中,如图1-10所示。
图1-10