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

欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~

来自维基百科

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

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

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

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

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

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

正如Bioinfo Publications所述

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

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

维基百科提及到说

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

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

import java.util.ArrayList;
import java.util.List;
import edu.neuralnet.core.activation.ActivationFunction;
import edu.neuralnet.core.input.InputSummingFunction;
/**
 * Represents a neuron model comprised of(以下内容组成的神经元模型): </br>
 * <ul>
 * <li>Summing part(求和部分)  - input summing function(输入求和函数 )</li>
 * <li>Activation function(激活函数)</li>
 * <li>Input connections(输入连接)</li>
 * <li>Output connections(输出连接)</li>
 * </ul>
 */
public class Neuron {
 /**
  * Neuron‘s identifier
  * 神经元标识符
  */
 private String id;
 /**
  * Collection of neuron‘s input connections (connections to this neuron)
  * 神经元输入连接的集合(与此神经元的连接)
  */
 protected List < Connection > inputConnections;
 /**
  * Collection of neuron‘s output connections (connections from this to other
  * neurons)
  * 神经元输出连接的集合(从这个到其他神经元的连接)
  */
 protected List < Connection > outputConnections;
 /**
  * Input summing function for this neuron
  * 该神经元的输入和函数
  */
 protected InputSummingFunction inputSummingFunction;
 /**
  * Activation function for this neuron
  * 这个神经元的激活函数
  */
 protected ActivationFunction activationFunction;
 /**
  * Default constructor
  * 默认构造方法
  */
 public Neuron() {
  this.inputConnections = new ArrayList < > ();
  this.outputConnections = new ArrayList < > ();
 }
 /**
  * Calculates the neuron‘s output
  * 计算神经元输出
  */
 public double calculateOutput() {
   double totalInput = inputSummingFunction.getOutput(inputConnections);
   return activationFunction.getOutput(totalInput);
  }
  ...
}

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

/**
 * Represents a connection between two neurons an the associated weight.
 * 表示两个神经元之间的连接以及相关的权重
 */
public class NeuronsConnection {
/**
 * From neuron for this connection (source neuron). This connection is
 * output connection for from neuron.
 * 从神经元中获取这个连接(源神经元)。此连接是来自神经元的输出连接
 */
protected Neuron fromNeuron;
/**
 * To neuron for this connection (target, destination neuron) This
 * connection is input connection for to neuron.
 * 对于用于此连接的神经元(目标,目标神经元),此连接是神经元的输入连接
 */
protected Neuron toNeuron;
/**
 * Connection weight
 * 连接权重
 */
protected double weight;
/**
 * Creates a new connection between specified neurons with random weight.
 * 在具有随机权重的指定神经元之间创建一个新的连接
 * @param fromNeuron
 *            neuron to connect from
 * @param toNeuron
 *            neuron to connect to
 */
public NeuronsConnection(Neuron fromNeuron, Neuron toNeuron) {
this.fromNeuron = fromNeuron;
this.toNeuron = toNeuron;
this.weight = Math.random();
}
/**
 * Creates a new connection to specified neuron with specified weight object
 * 创建与指定权重对象的指定神经元的新连接
 *
 * @param fromNeuron
 *            neuron to connect from
 * @param toNeuron
 *            neuron to connect to
 * @param weight
 *            weight for this connection
 */
public NeuronsConnection(Neuron fromNeuron, Neuron toNeuron, double weight) {
this(fromNeuron, toNeuron);
this.weight = weight;
}
/**
 * Returns weight for this connection
 * 返回此连接的权重
 * @return weight for this connection
 */
public double getWeight() {
return weight;
}
/**
 * Set the weight of the connection.
 * 设置连接的权值
 * @param weight
 *            The new weight of the connection to be set
 */
public void setWeight(double weight) {
this.weight = weight;
}
/**
 * Returns input of this connection - the activation function result
 * calculated in the input neuron of this connection.
 * 返回此连接的输入 - 在此连接输入神经元中激活函数计算的结果
 * @return input received through this connection
 */
public double getInput() {
return fromNeuron.calculateOutput();
}
/**
 * Returns the weighted input of this connection
 * 返回此连接的权值输入
 * @return weighted input of the connection
 */
public double getWeightedInput() {
return fromNeuron.calculateOutput() * weight;
}
/**
 * Gets from neuron for this connection
 * 从神经元获取此连接
 * @return from neuron for this connection
 */
public Neuron getFromNeuron() {
return fromNeuron;
}
/**
 * Gets to neuron for this connection
 * 获取用于此连接的神经元
 * @return neuron to set as to neuron
 */
public Neuron getToNeuron() {
return toNeuron;
}
...
}

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

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

import java.util.List;
import edu.neuralnet.core.Connection;
/**
 * Represents the inputs summing part of a neuron also called signal collector.
 * 神经元的求和部分,也可以称为信号收集器
 */
public interface InputSummingFunction {
/**
 * Performs calculations based on the output values of the input neurons.
 * 根据输入神经元的输出值执行计算
 * @param inputConnections
 *            neuron‘s input connections
 * @return total input for the neuron having the input connections
 *         总输入,具有输入连接的神经元
 */
double collectOutput(List<Connection> inputConnections);
}

分别实现为:

import java.util.List;
import edu.neuralnet.core.Connection;
/**
 * Calculates the weighted sums of the input neurons‘ outputs.
 * 计算输入神经元输出的加权和
 */
public final class WeightedSumFunction implements InputSummingFunction {
/**
 * {@inheritDoc}
 */
@Override
public double collectOutput(List<Connection> inputConnections) {
double weightedSum = 0d;
for (Connection connection : inputConnections) {
weightedSum += connection.getWeightedInput();
}
return weightedSum;
}
}

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

/**
 * Neural networks activation function interface.
 * 神经网络激活函数的接口
 */
public interface ActivationFunction {
/**
 * Performs calculation based on the sum of input neurons output.
 * 基于输入神经元输出的和来进行计算
 * @param summedInput
 *            neuron‘s sum of outputs respectively inputs for the connected
 *            neuron
 *
 * @return Output‘s calculation based on the sum of inputs
 *          基于输入和来计算输出
 */
double calculateOutput(double summedInput);
}

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

神经层可以分为三类:

  1. 输入层
  2. 隐藏层
  3. 输出层

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

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

import java.util.ArrayList;
import java.util.List;
/**
 * Neural networks can be composed of several linked layers, forming the
 * so-called multilayer networks. A layer can be defined as a set of neurons
 * comprising a single neural net‘s layer.
 * 神经网络可以由多个连接层组成,形成所谓的多层网络,
 * 一层可以定义为一组包含神经网络层的神经元
 */
public class NeuralNetLayer {
/**
 * Layer‘s identifier
 * 层次标识符
 */
private String id;
/**
 * Collection of neurons in this layer
 * 该层神经元的集合
 */
protected List<Neuron> neurons;
/**
 * Creates an empty layer with an id.
 * 用ID创建一个空层
 * @param id
 *            layer‘s identifier
 */
public NeuralNetLayer(String id) {
this.id = id;
neurons = new ArrayList<>();
}
/**
 * Creates a layer with a list of neurons and an id.
 * 创建一个包含神经元列表和id的层
 * @param id
 *            layer‘s identifier 层次标识符
 * @param neurons
 *            list of neurons to be added to the layer 添加到该层的神经元列表
 */
public NeuralNetLayer(String id, List<Neuron> neurons) {
this.id = id;
this.neurons = neurons;
}
...
}

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

/**
 * Represents an artificial neural network with layers containing neurons.
 * 含有神经元层的人工神经网络
 */
public class NeuralNet {
/**
 * Neural network id
 * 神经网络ID
 */
private String id;
/**
 * Neural network input layer
 * 神经网络的输入层
 */
private NeuralNetLayer inputLayer;
/**
 * Neural network hidden layers
 * 神经网络隐藏的层
 */
private List<NeuralNetLayer> hiddenLayers;
/**
 * Neural network output layer
 * 神经网络的输出层
 */
private NeuralNetLayer outputLayer;
/**
 * Constructs a neural net with all layers present.
 * 构造一个具有所有层的神经网络
 * @param id
 *            Neural network id to be set 设置神经网络标识
 * @param inputLayer
 *            Neural network input layer to be set 设置神经网络的输入层
 * @param hiddenLayers
 *            Neural network hidden layers to be set 设置神经网络隐藏的层
 * @param outputLayer
 *            Neural network output layer to be set 设置神经网络的输出层
 */
public NeuralNet(String id, NeuralNetLayer inputLayer, List<NeuralNetLayer> hiddenLayers,
NeuralNetLayer outputLayer) {
this.id = id;
this.inputLayer = inputLayer;
this.hiddenLayers = hiddenLayers;
this.outputLayer = outputLayer;
}
/**
 * Constructs a neural net without hidden layers.
 * 构造一个没有隐藏层的神经网络
 * @param id
 *            Neural network id to be set 设置神经网络标识
 * @param inputLayer
 *            Neural network input layer to be set 设置神经网络的输入层
 * @param outputLayer
 *            Neural network output layer to be set 设置神经网络隐藏的层
 */
public NeuralNet(String id, NeuralNetLayer inputLayer, NeuralNetLayer outputLayer) {
this.id = id;
this.inputLayer = inputLayer;
this.outputLayer = outputLayer;
}
...
}

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

翻译人:BAStriver,该成员来自云+社区翻译社

原文链接:https://dzone.com/articles/designing-a-neural-network-in-java

原文作者:Daniela Kolarova

相关阅读

通过JS库Encog实现JavaScript机器学习和神经学网络

自然语言处理的神经网络模型初探

如何使用Python超参数的网格搜索ARIMA模型


此文已由作者授权云加社区发布,转载请注明文章出处

原文地址:https://www.cnblogs.com/qcloud1001/p/8425830.html

时间: 2024-11-06 09:30:51

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

从一个程序员的角度看——微信小应用

前言: 最近初步了解了一下微信小应用,APP端的同事也非常感兴趣,于是在公司内部做了一个小小的分享,分享的过程中有很多讨论内容,大家也是非常感兴趣和有自己的看法,当时"混乱"的场面好几次我都没有把持住.以下内容部分来自于内部分享所用ppt.文章对微信小应用的使用做了展示性介绍,并简单介绍了代码结构.后端交互方法.最后提出一些总结和疑问.文章内容比较主观,有不对的地方欢迎大家指出纠正. 前段时间微信小应用公开内测,在朋友圈火了一把,各种阐述疯狂蔓延,干掉APP之类的说法比较突出,确实达到

从一个程序员的角度看——微信小应用(第二弹 见解)

最近公司的小程序刚通过了代码审核(待发布状态),从最初对它的学习 到开发 到小程序待发布 再到28日微信公开课,也算一步步的了解了微信小程序吧. 28日微信pro公开课张小龙针对小程序进行了一些答疑,之后行业的同僚都很关注,似乎大家还是有很多疑惑.之前初学后写过博客 从一个程序员的角度看--微信小应用(第一弹 初学),今天决定再写一篇小程序的小文,所以此篇谈谈我对小程序的理解吧. 说说张小龙回答的8个问题 1.小程序的入口在哪里?张小龙给出的答案是:小程序在微信没有入口. 2.小程序会不会有类似

从一个程序员的角度看——微信小应用(含直播视频)

前言: 最近初步了解了一下微信小应用,APP端的同事也非常感兴趣,于是在公司内部做了一个小小的分享,分享的过程中有很多讨论内容,大家也是非常感兴趣和有自己的看法,当时"混乱"的场面好几次我都没有把持住.以下内容部分来自于内部分享所用ppt.文章对微信小应用的使用做了展示性介绍,并简单介绍了代码结构.后端交互方法.最后提出一些总结和疑问.文章内容比较主观,有不对的地方欢迎大家指出纠正. 前段时间微信小应用公开内测,在朋友圈火了一把,各种阐述疯狂蔓延,干掉APP之类的说法比较突出,确实达到

从程序员的角度谈创业三年

  摘要:在创业三年时间里作为联合创始人,虽然拿着大家均等的股份,我始终是没有什么话语权的,但是,这也给了我从旁观者的角度看清整个局面的机会.创业公司的成败绝大程度取决于技术大牛和公司 Leader,这两个人最好能在性格上形成互补,而遗憾的是我们公司是同一人. 关于决定是否创业 2012年4月,正好三年前整,在深圳能源正混的郁郁不得志的时候,大学的好兄弟找到我一起创业,他们有钱.有 idea,就是差人,当时的我还是技术菜鸟,本科学的也不是计算机,看着移动互联网蓬勃的发展羡慕不已.很快就答应了一起

从程序员的角度谈创业三年(转)

  摘要:在创业三年时间里作为联合创始人,虽然拿着大家均等的股份,我始终是没有什么话语权的,但是,这也给了我从旁观者的角度看清整个局面的机会.创业公司的成败绝大程度取决于技术大牛和公司 Leader,这两个人最好能在性格上形成互补,而遗憾的是我们公司是同一人. 关于决定是否创业 2012年4月,正好三年前整,在深圳能源正混的郁郁不得志的时候,大学的好兄弟找到我一起创业,他们有钱.有 idea,就是差人,当时的我还是技术菜鸟,本科学的也不是计算机,看着移动互联网蓬勃的发展羡慕不已.很快就答应了一起

从程序员的角度分析微信小程序

昨天朋友圈被微信小程序刷爆了. 我赶快在书架上拿出三年前买的书,把上面的土擦干净,压压惊. 作为一个并不是资深的程序员. 从程序员的角度分析一下微信小程序,欢迎指点. 首先吐槽 微信小程序只发了200个邀请号,和我预想的一样,张小龙并没有翻我牌,难道就不能雨露均沾吗? 先来了解下什么是微信小程序. 转自知乎 微信也许重申了"我们是一款约炮软件" 微信还提供了一大堆接口和组件(不好意思,说了句废话). 下面是禅叔的观点: 小程序原理就是用JS调用底层native组件,和React Nat

【知乎】怎么成为一个优秀的程序员,而不是一个优秀的码农?

怎么成为一个优秀的程序员,而不是一个优秀的码农? 9 条评论 分享 默认排序按时间排序 98 个回答 3844赞同反对,不会显示你的姓名 萧井陌 微信公众号:炼瓜研究所 技术社区 - 3844 人赞同 优秀的程序员会告诉你打根基的重要性,会劝你在厚积薄发前要隐忍. 优秀的码农会告诉你学啥底层.啥啥啥一拖就好了,学了python还要啥自行车啊,数据结构排序函数二分搜索这不都内置了吗?工作中永远用不到,学算法有啥用啊?成为高手有很多种方法汇编是个屁啊? +++基础的分割线+++ 列举几个我认为比较重

站在服务端程序员的角度下的一下编程看法

作者:陈硕链接:https://www.zhihu.com/question/22608820/answer/21968467来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 既然你是在校学生,而且编程语言和数据结构的基础还不错,我认为应该在<操作系统>和<计算机体系结构>这两门课上下功夫,然后才去读编程方面的 APUE.UNP 等书. 下面简单谈谈我对学习这两门课的看法和建议,都是站在服务端程序员的角度,从实用主义(pragmatic)的立场出发而言

从程序员的角度来看为什么我们需要工作流

每一个程序员,在接触到工作流的时候,都会有这么一个疑问--我用一般的方法可以实现,为什么还要用工作流? 我曾经也问过这个问题,不过现在稍微有点明白了.别着急要答案,看过下面的例子,或许你也就明白一些了. 这是一个简单的业务--订货流程: 客户提交采购订单 业务员执行订单处理 如果缺货,转工厂生产 仓库出货 物流发货 如果不使用工作流技术,从头开始开发这个订购流程的业务逻辑,我们需要: 每个活动点都需要开发交互页面和后台处理程序 每个活动的流转都需要硬性判断下一步活动节点及其操作人 每次操作都需要