从程序员的角度设计一个Java的神经网络

2018 年 2 月 12 日 数盟

人工神经网络(ANN)或连接系统是受生物神经网络启发构成生物大脑的计算系统。这样的系统通过考虑例子来学习(逐步提高性能)来完成任务,通常没有任务特定的编程。

用Java或任何其他编程语言设计神经网络我们需要理解人工神经网络的结构和功能。

人工神经网络执行的任务比如有模式识别、从数据中学习以及像专家一样预测趋势,而不像传统的算法方法那样需要执行一组步骤来实现所定义的目标。人工神经网络由于其高度交互的网络结构,可以学习如何自己解决一些任务。

人造神经元具有与人脑神经元相似的结构。一个天然的神经元是由核,树突和轴突组成的。轴突延伸到几个分支形成突触与其他神经元的树突。

到目前为止,我们已经区分了神经元的结构和相连神经元的网络。另一个重要方面是分别与单个神经元相关的神经网络的处理或计算。自然神经元是信号处理器 – 它们在树突中接收可以触发轴突信号的微信号。有一个潜在的阈值,到达的时候,刺激轴突,并传播信号到其他神经元。因此,我们可以将人造神经元视为一个在输入中具有信号接收器、在输出中具有激活单元的东西,其可以发送的信号将被转发到与图中所示类似的其他神经元上:

此外,神经元之间的连接具有相应可以修改信号的权重,从而影响神经元的输出。由于权重是神经网络的内部因素并影响其输出,所以可以认为它们是神经网络的内部学科,调节描述神经元与其他神经元或外部世界的连接的权重将反映神经网络的能力。

正如Bioinfo Publications所述:

人造神经元接收一个或多个输入(代表树突)并将它们相加以产生输出/ 激活  (代表神经元的轴突)。一般来说每个节点的总和被加权,总和通过激活函数或传递函数传递。

这个组件为神经网络处理增加了非线性,这是因为自然神经元具有非线性行为。在一些特殊情况下,它可以是一个线性函数。

维基百科提及到说:

一个标准的计算机芯片电路可以看作是一个激活功能的数字网络,取决于输入的是“ON”(1)还是“OFF”(0)。这与神经网络中的线性感知器的行为类似。然而,  非线性  激活函数允许这样的网络仅使用少量的节点来计算特殊问题。使用的流行的激活函数的例子是Sigmoid、双曲正切、硬极限阈值和纯线性。

将这些知识转化为Java代码,我们将有一个如下的神经元类:

  1. import java.util.ArrayList;

  2. import java.util.List;

  3. import edu.neuralnet.core.activation.ActivationFunction;

  4. import edu.neuralnet.core.input.InputSummingFunction;

  5. /**

  6.  * Represents a neuron model comprised of(以下内容组成的神经元模型): </br>

  7.  * <ul>

  8.  * <li>Summing part(求和部分)  – input summing function(输入求和函数 )</li>

  9.  * <li>Activation function(激活函数)</li>

  10.  * <li>Input connections(输入连接)</li>

  11.  * <li>Output connections(输出连接)</li>

  12.  * </ul>

  13.  */

  14. public class Neuron {

  15.  /**

  16.   * Neuron’s identifier

  17.   * 神经元标识符

  18.   */

  19.  private String id;

  20.  /**

  21.   * Collection of neuron’s input connections (connections to this neuron)

  22.   * 神经元输入连接的集合(与此神经元的连接)

  23.   */

  24.  protected List < Connection > inputConnections;

  25.  /**

  26.   * Collection of neuron’s output connections (connections from this to other

  27.   * neurons)

  28.   * 神经元输出连接的集合(从这个到其他神经元的连接)

  29.   */

  30.  protected List < Connection > outputConnections;

  31.  /**

  32.   * Input summing function for this neuron

  33.   * 该神经元的输入和函数

  34.   */

  35.  protected InputSummingFunction inputSummingFunction;

  36.  /**

  37.   * Activation function for this neuron

  38.   * 这个神经元的激活函数

  39.   */

  40.  protected ActivationFunction activationFunction;

  41.  /**

  42.   * Default constructor

  43.   * 默认构造方法

  44.   */

  45.  public Neuron() {

  46.   this.inputConnections = new ArrayList < > ();

  47.   this.outputConnections = new ArrayList < > ();

  48.  }

  49.  /**

  50.   * Calculates the neuron’s output

  51.   * 计算神经元输出

  52.   */

  53.  public double calculateOutput() {

  54.    double totalInput = inputSummingFunction.getOutput(inputConnections);

  55.    return activationFunction.getOutput(totalInput);

  56.   }

  57.   …

  58. }

神经元有输入和输出连接、输入求和值和激活函数,那输入权重在哪里呢?它们包含在连接本身中,如下所示:

  1. /**

  2.  * Represents a connection between two neurons an the associated weight.

  3.  * 表示两个神经元之间的连接以及相关的权重

  4.  */

  5. public class NeuronsConnection {

  6. /**

  7.  * From neuron for this connection (source neuron). This connection is

  8.  * output connection for from neuron.

  9.  * 从神经元中获取这个连接(源神经元)。此连接是来自神经元的输出连接

  10.  */

  11. protected Neuron fromNeuron;

  12. /**

  13.  * To neuron for this connection (target, destination neuron) This

  14.  * connection is input connection for to neuron.

  15.  * 对于用于此连接的神经元(目标,目标神经元),此连接是神经元的输入连接

  16.  */

  17. protected Neuron toNeuron;

  18. /**

  19.  * Connection weight

  20.  * 连接权重

  21.  */

  22. protected double weight;

  23. /**

  24.  * Creates a new connection between specified neurons with random weight.

  25.  * 在具有随机权重的指定神经元之间创建一个新的连接

  26.  * @param fromNeuron

  27.  *            neuron to connect from

  28.  * @param toNeuron

  29.  *            neuron to connect to

  30.  */

  31. public NeuronsConnection(Neuron fromNeuron, Neuron toNeuron) {

  32. this.fromNeuron = fromNeuron;

  33. this.toNeuron = toNeuron;

  34. this.weight = Math.random();

  35. }

  36. /**

  37.  * Creates a new connection to specified neuron with specified weight object

  38.  * 创建与指定权重对象的指定神经元的新连接

  39.  *

  40.  * @param fromNeuron

  41.  *            neuron to connect from

  42.  * @param toNeuron

  43.  *            neuron to connect to

  44.  * @param weight

  45.  *            weight for this connection

  46.  */

  47. public NeuronsConnection(Neuron fromNeuron, Neuron toNeuron, double weight) {

  48. this(fromNeuron, toNeuron);

  49. this.weight = weight;

  50. }

  51. /**

  52.  * Returns weight for this connection

  53.  * 返回此连接的权重

  54.  * @return weight for this connection

  55.  */

  56. public double getWeight() {

  57. return weight;

  58. }

  59. /**

  60.  * Set the weight of the connection.

  61.  * 设置连接的权值

  62.  * @param weight

  63.  *            The new weight of the connection to be set

  64.  */

  65. public void setWeight(double weight) {

  66. this.weight = weight;

  67. }

  68. /**

  69.  * Returns input of this connection – the activation function result

  70.  * calculated in the input neuron of this connection.

  71.  * 返回此连接的输入 – 在此连接输入神经元中激活函数计算的结果

  72.  * @return input received through this connection

  73.  */

  74. public double getInput() {

  75. return fromNeuron.calculateOutput();

  76. }

  77. /**

  78.  * Returns the weighted input of this connection

  79.  * 返回此连接的权值输入

  80.  * @return weighted input of the connection

  81.  */

  82. public double getWeightedInput() {

  83. return fromNeuron.calculateOutput() * weight;

  84. }

  85. /**

  86.  * Gets from neuron for this connection

  87.  * 从神经元获取此连接

  88.  * @return from neuron for this connection

  89.  */

  90. public Neuron getFromNeuron() {

  91. return fromNeuron;

  92. }

  93. /**

  94.  * Gets to neuron for this connection

  95.  * 获取用于此连接的神经元

  96.  * @return neuron to set as to neuron

  97.  */

  98. public Neuron getToNeuron() {

  99. return toNeuron;

  100. }

  101. }

连接对象提供权重并负责计算输入的权值。

求和函数被定义为接口,以便能够替换神经元的计算策略:

  1. import java.util.List;

  2. import edu.neuralnet.core.Connection;

  3. /**

  4.  * Represents the inputs summing part of a neuron also called signal collector.

  5.  * 神经元的求和部分,也可以称为信号收集器

  6.  */

  7. public interface InputSummingFunction {

  8. /**

  9.  * Performs calculations based on the output values of the input neurons.

  10.  * 根据输入神经元的输出值执行计算

  11.  * @param inputConnections

  12.  *            neuron’s input connections

  13.  * @return total input for the neuron having the input connections

  14.  *         总输入,具有输入连接的神经元

  15.  */

  16. double collectOutput(List<Connection> inputConnections);

  17. }

分别实现为:

  1. import java.util.List;

  2. import edu.neuralnet.core.Connection;

  3. /**

  4.  * Calculates the weighted sums of the input neurons’ outputs.

  5.  * 计算输入神经元输出的加权和

  6.  */

  7. public final class WeightedSumFunction implements InputSummingFunction {

  8. /**

  9.  * {@inheritDoc}

  10.  */

  11. @Override

  12. public double collectOutput(List<Connection> inputConnections) {

  13. double weightedSum = 0d;

  14. for (Connection connection : inputConnections) {

  15. weightedSum += connection.getWeightedInput();

  16. }

  17. return weightedSum;

  18. }

  19. }

激活函数的接口可以定义如下::

  1. /**

  2.  * Neural networks activation function interface.

  3.  * 神经网络激活函数的接口

  4.  */

  5. public interface ActivationFunction {

  6. /**

  7.  * Performs calculation based on the sum of input neurons output.

  8.  * 基于输入神经元输出的和来进行计算

  9.  * @param summedInput

  10.  *            neuron’s sum of outputs respectively inputs for the connected

  11.  *            neuron

  12.  *

  13.  * @return Output‘s calculation based on the sum of inputs

  14.  *         基于输入和来计算输出

  15.  */

  16. double calculateOutput(double summedInput);

  17. }

开始编写代码之前需要注意的最后一个问题是神经网络层。神经网络由几个链接层组成,形成所谓的多层网络。神经层可以分为三类:

  1. 输入层

  2. 隐藏层

  3. 输出层

在实践中,额外的神经层增加了另一个抽象层次的外部刺激,增强了神经网络认知更复杂知识的能力。

一个图层类可以被定义为一个有连接的神经元列表:

  1. import java.util.ArrayList;

  2. import java.util.List;

  3. /**

  4.  * Neural networks can be composed of several linked layers, forming the

  5.  * so-called multilayer networks. A layer can be defined as a set of neurons

  6.  * comprising a single neural net’s layer.

  7.  * 神经网络可以由多个连接层组成,形成所谓的多层网络,

  8.  * 一层可以定义为一组包含神经网络层的神经元

  9.  */

  10. public class NeuralNetLayer {

  11. /**

  12.  * Layer’s identifier

  13.  * 层次标识符

  14.  */

  15. private String id;

  16. /**

  17.  * Collection of neurons in this layer

  18.  * 该层神经元的集合

  19.  */

  20. protected List<Neuron> neurons;

  21. /**

  22.  * Creates an empty layer with an id.

  23.  * 用ID创建一个空层

  24.  * @param id

  25.  *            layer’s identifier

  26.  */

  27. public NeuralNetLayer(String id) {

  28. this.id = id;

  29. neurons = new ArrayList<>();

  30. }

  31. /**

  32.  * Creates a layer with a list of neurons and an id.

  33.  * 创建一个包含神经元列表和id的层

  34.  * @param id

  35.  *            layer’s identifier 层次标识符

  36.  * @param neurons

  37.  *            list of neurons to be added to the layer 添加到该层的神经元列表

  38.  */

  39. public NeuralNetLayer(String id, List<Neuron> neurons) {

  40. this.id = id;

  41. this.neurons = neurons;

  42. }

  43. }

最后,用Java创建一个简单的神经网络:

  1. /**

  2.  * Represents an artificial neural network with layers containing neurons.

  3.  * 含有神经元层的人工神经网络

  4.  */

  5. public class NeuralNet {

  6. /**

  7.  * Neural network id

  8.  * 神经网络ID

  9.  */

  10. private String id;

  11. /**

  12.  * Neural network input layer

  13.  * 神经网络的输入层

  14.  */

  15. private NeuralNetLayer inputLayer;

  16. /**

  17.  * Neural network hidden layers

  18.  * 神经网络隐藏的层

  19.  */

  20. private List<NeuralNetLayer> hiddenLayers;

  21. /**

  22.  * Neural network output layer

  23.  * 神经网络的输出层

  24.  */

  25. private NeuralNetLayer outputLayer;

  26. /**

  27.  * Constructs a neural net with all layers present.

  28.  * 构造一个具有所有层的神经网络

  29.  * @param id

  30.  *            Neural network id to be set 设置神经网络标识

  31.  * @param inputLayer

  32.  *            Neural network input layer to be set 设置神经网络的输入层

  33.  * @param hiddenLayers

  34.  *            Neural network hidden layers to be set 设置神经网络隐藏的层

  35.  * @param outputLayer

  36.  *            Neural network output layer to be set 设置神经网络的输出层

  37.  */

  38. public NeuralNet(String id, NeuralNetLayer inputLayer, List<NeuralNetLayer> hiddenLayers,

  39. NeuralNetLayer outputLayer) {

  40. this.id = id;

  41. this.inputLayer = inputLayer;

  42. this.hiddenLayers = hiddenLayers;

  43. this.outputLayer = outputLayer;

  44. }

  45. /**

  46.  * Constructs a neural net without hidden layers.

  47.  * 构造一个没有隐藏层的神经网络

  48.  * @param id

  49.  *            Neural network id to be set 设置神经网络标识

  50.  * @param inputLayer

  51.  *            Neural network input layer to be set 设置神经网络的输入层

  52.  * @param outputLayer

  53.  *            Neural network output layer to be set 设置神经网络隐藏的层

  54.  */

  55. public NeuralNet(String id, NeuralNetLayer inputLayer, NeuralNetLayer outputLayer) {

  56. this.id = id;

  57. this.inputLayer = inputLayer;

  58. this.outputLayer = outputLayer;

  59. }

  60. }

我们所得到的是一个基于Java的神经网络层次、神经元和连接的结构定义。我们也谈到了一些关于激活函数的内容,并为它们定义了一个接口。为简单起见,我们省略了各种激活函数的实现以及学习神经网络的基础知识。这两个主题将在本系列的后续文章中介绍。

原文链接:https://cloud.tencent.com/developer/article/1038393

作者:Daniela Kolarova

文章来源:51CTO


登录查看更多
1

相关内容

【经典书】机器学习高斯过程,266页pdf
专知会员服务
192+阅读 · 2020年5月2日
干货书《数据科学数学系基础》2020最新版,266页pdf
专知会员服务
314+阅读 · 2020年3月23日
《深度学习》圣经花书的数学推导、原理与Python代码实现
【新书】Python中的经典计算机科学问题,224页pdf
专知会员服务
143+阅读 · 2019年12月28日
深度学习算法与架构回顾
专知会员服务
77+阅读 · 2019年10月20日
干货!神经网络原来是这样和数学挂钩的
图灵教育
13+阅读 · 2019年5月21日
干货 | 深入理解深度学习中的激活函数
计算机视觉life
16+阅读 · 2019年1月29日
机器学习必知的8大神经网络架构
七月在线实验室
7+阅读 · 2018年4月26日
Python 杠上 Java、C/C++,赢面有几成?
CSDN
6+阅读 · 2018年4月12日
理解神经网络的激活函数
论智
7+阅读 · 2018年1月8日
入门 | 一文概览深度学习中的激活函数
深度学习世界
4+阅读 · 2017年11月3日
干货|浅谈神经网络中激活函数的设计
机器学习研究会
5+阅读 · 2017年10月28日
神经网络理论基础及 Python 实现
Python开发者
6+阅读 · 2017年7月15日
Arxiv
34+阅读 · 2019年11月7日
dynnode2vec: Scalable Dynamic Network Embedding
Arxiv
13+阅读 · 2018年12月6日
Relational recurrent neural networks
Arxiv
8+阅读 · 2018年6月28日
Arxiv
5+阅读 · 2017年12月29日
Arxiv
3+阅读 · 2017年12月18日
Arxiv
3+阅读 · 2017年11月21日
Arxiv
23+阅读 · 2017年3月9日
VIP会员
相关VIP内容
【经典书】机器学习高斯过程,266页pdf
专知会员服务
192+阅读 · 2020年5月2日
干货书《数据科学数学系基础》2020最新版,266页pdf
专知会员服务
314+阅读 · 2020年3月23日
《深度学习》圣经花书的数学推导、原理与Python代码实现
【新书】Python中的经典计算机科学问题,224页pdf
专知会员服务
143+阅读 · 2019年12月28日
深度学习算法与架构回顾
专知会员服务
77+阅读 · 2019年10月20日
相关资讯
干货!神经网络原来是这样和数学挂钩的
图灵教育
13+阅读 · 2019年5月21日
干货 | 深入理解深度学习中的激活函数
计算机视觉life
16+阅读 · 2019年1月29日
机器学习必知的8大神经网络架构
七月在线实验室
7+阅读 · 2018年4月26日
Python 杠上 Java、C/C++,赢面有几成?
CSDN
6+阅读 · 2018年4月12日
理解神经网络的激活函数
论智
7+阅读 · 2018年1月8日
入门 | 一文概览深度学习中的激活函数
深度学习世界
4+阅读 · 2017年11月3日
干货|浅谈神经网络中激活函数的设计
机器学习研究会
5+阅读 · 2017年10月28日
神经网络理论基础及 Python 实现
Python开发者
6+阅读 · 2017年7月15日
相关论文
Arxiv
34+阅读 · 2019年11月7日
dynnode2vec: Scalable Dynamic Network Embedding
Arxiv
13+阅读 · 2018年12月6日
Relational recurrent neural networks
Arxiv
8+阅读 · 2018年6月28日
Arxiv
5+阅读 · 2017年12月29日
Arxiv
3+阅读 · 2017年12月18日
Arxiv
3+阅读 · 2017年11月21日
Arxiv
23+阅读 · 2017年3月9日
Top
微信扫码咨询专知VIP会员