什么?!只用30行代码就能创建一个JavaScript的神经网络?

时间:2022-05-02
本文章向大家介绍什么?!只用30行代码就能创建一个JavaScript的神经网络?,主要内容包括神经元和突触、代码、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

在本文中,我将向你展示如何使用Synaptic.js来创建和训练神经网络,它允许你在Node.js和浏览器中进行深度学习。我们将创建最简单的神经网络:一个能够解决XOR方程的问题。

但在我们看代码之前,我们先来看看神经网络的基本知识。

神经元和突触

神经网络的第一个组成部分是,神经元。神经元就像一个函数,它需要一些输入,然后返回一个输出。

有很多不同类型的神经元。我们的网络将使用S函数的神经细胞,它取任何给定的数字,并将其压缩为0到1之间的值。

下面的圆圈说明了一个S型的神经元。它的输入是5,输出是1。箭头被称为突触,它将神经元与网络中的其他层连接起来。

为什么是红色数字是5呢? 因为这是三个突触的和,连接到神经元,正如左边的三个箭头所示。让我们解开这个问题。

在最左边,我们看到两个值加上一个所谓的偏差值。值是1和0,也就是绿颜色的数字。偏差值是-2,也就是棕色数字。

首先,这两个输入的权重乘以它们的权重,也就是蓝色数字所示的7和3。最后加上偏差,得到红色数字5。这是我们人工神经元的输入。

因为这是一个S形的神经元,它把任何值都压缩到0到1之间,输出被压缩到1。

如果你把这些神经网络连在一起,你就有了一个神经网络。这是通过神经元之间通过突触相互连接的神经传递的。如下图:

神经网络的目标是训练它的泛化能力,比如识别手写的数字或电子邮件中的垃圾邮件。而擅长泛化就是在整个网络中拥有正确的权重和偏差值。比如上面的例子中蓝色和棕色的数字。

在训练网络时,你只是简单地展示了大量的例子,比如手写的数字,并让网络来预测正确的答案。

在每次预测之后,你将计算所预测的误差,并调整权重和偏差值,以便下次网络能够更准确地猜出它们。这个学习过程叫做反向传播。

通过这样几千次的实践,你的网络很快就会变得让人满意。

从技术上讲,反向传播的作用超出了本教程的范围,这里有三个最好的信息来源值得你去了解:

  • 一步一步的反向传播的例子——Matt Mazur 地址:http://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/
  • 黑客们对神经网络的指导——Andrej Karpathy 地址:http://karpathy.github.io/neuralnets/
  • 神经网络和深度学习——Michael Nielsen 地址:http://neuralnetworksanddeeplearning.com/chap1.html

代码

你已经知道了基本的介绍,现在让我们看看代码。我们需要做的第一件事就是创建图层。我们在突触的new Layer()函数中这样做。传递给这个函数的数字决定了每个层应该有多少个神经元。

const { Layer, Network } = window.synaptic;
var inputLayer = new Layer(2);
var hiddenLayer = new Layer(3);
var outputLayer = new Layer(1);

接下来,我们把这些层连接起来,并实例化一个新的网络,如下:

inputLayer.project(hiddenLayer);
hiddenLayer.project(outputLayer);
var myNetwork = new Network({
input: inputLayer,
hidden: [hiddenLayer],
output: outputLayer
});

这是一个2–3–1类型的网络,可以像这样可视化:

现在让我们来训练网络:

// train the network - learn XOR
var learningRate = .3;
for (var i = 0; i < 20000; i++) {
// 0,0 => 0
myNetwork.activate([0,0]);
myNetwork.propagate(learningRate, [0]);
// 0,1 => 1
myNetwork.activate([0,1]);
myNetwork.propagate(learningRate, [1]);
// 1,0 => 1
myNetwork.activate([1,0]);
myNetwork.propagate(learningRate, [1]);
// 1,1 => 0
myNetwork.activate([1,1]);
myNetwork.propagate(learningRate, [0]);
}

在这里我们运行网络2万次。每次我们正向和反向传播四次,传递给这个网络的四种可能的输入为:[0,0] [0,1] [1,0] [1,1]。

我们先从myNetwork.activate([0,0])开始,其中[0,0]是我们发送到网络的数据点。这是正向传播,也被称为激活网络。在每一个正向传播之后,我们需要做一个反向传播,在这个网络中,网络更新它自己的权重和偏差。

反向传播是用这一行代码完成的:myNetwork.propagate(learningRate, [0]),在这里, learningRate是一个常量,它每次都会告诉网络它应该调整多少权重。第二个参数0表示输入[0,0]的正确输出。

然后,网络将自己的预测与正确的标签进行比较。这将会说明它是正确的还是错误的。它使用比较来作为修正它自己的权重和偏差值的基础,这样下次它就会猜得更准确一些。在完成这一过程2万次之后,我们可以通过激活网络来了解我们的网络是如何通过所有四种可能的输入来实现的:

console.log(myNetwork.activate([0,0])); 
-> [0.015020775950893527]
console.log(myNetwork.activate([0,1]));
->[0.9815816381088985]
console.log(myNetwork.activate([1,0]));
-> [0.9871822457132193]
console.log(myNetwork.activate([1,1]));
-> [0.012950087641929467]

如果我们把这些值四舍五入到最近的整数,我们就会得到XOR方程的正确答案。