配置环境、安装合适的库、下载数据集……有时候学习深度学习的前期工作很让人沮丧,如果只是为了试试现在人人都谈的深度学习,做这些麻烦事似乎很不值当。但好在我们也有一些更简单的方法可以体验深度学习。近日,编程学习平台 Scrimba 联合创始人 Per Harald Borgen 在 Medium 上发文介绍了一种仅用 30 行 JavaScript 代码就创建出了一个神经网络的教程,而且使用的工具也只有 Node.js、Synaptic.js 和浏览器而已。另外,作者还做了一个交互式 Scrimba 教程,也许能帮你理解其中的复杂概念。
- Synaptic.js:https://synaptic.juancazala.com
- Node.js:https://nodejs.org
- Scrimba 教程:https://scrimba.com/casts/cast-1980
Synaptic.js 让你可以使用 Node.js 和浏览器做深度学习。在这篇文章中,我将介绍如何使用 Synaptic.js 创建和训练神经网络。
- // 创建网络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);varmyNetwork = newNetwork({
- input: inputLayer,
- hidden: [hiddenLayer],
- output: outputLayer
- });// 训练网络——学习异或运算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]);
- }// 测试网络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]
我们将创建一个最简单的神经网络:一个可以执行异或运算的网络。上面就是这个网络的全部代码,但在我们深入解读这些代码之前,首先我们先了解一下神经网络的基础知识。
神经元和突触
神经网络的基本构造模块是神经元。神经元就像是一个函数,有几个输入,然后可以得到一个输出。神经元的种类有很多。我们的网络将使用 sigmoid 神经元,它可以输入任何数字并将其压缩到 0 到 1 之间。下图就是一个 sigmoid 神经元。它的输入是 5,输出是 1。箭头被称为突触,可以将该神经元与网络中的其它层连接到一起。
所以,红色的数字 5 是哪里来的?它是左边的三个突触的和,让我们来剖析一下。
在最左边我们可以看到两个值和一个所谓偏置(bias)值。这两个值是 1 和 0,用绿色表示。偏置值是 -2,用棕色表示。
首先,这两个输入与它们的权重(weight)相乘,即蓝色的数字 7 和 3。***我们将这两个值与偏置加到一起就得到了红色的 5。这就是这个人工神经元的输入。
因为这是一个 sigmoid 神经元,会将任何值压缩到 0 到 1 之间,那么这个输出可以被压缩成 1。
如果你将这些神经元连接成一个网络,你就得到了一个神经网络。通过突触彼此相连的神经元可以向前传播输入,从而得到输出,如下图所示:
训练神经网络的目的是让它能够进行泛化,比如识别手写的数字或垃圾邮件。实现很好的泛化涉及为整个网络找到合适的权重和偏置值,就像我们上面案例中的蓝色和棕色数字。
当训练一个神经网络时,你只需要向其展示大量样本(比如手写数字),然后让其预测正确的答案即可。
在每次预测之后,你要计算这个预测的错误程度,并调整其权重和偏置值让该网络在下一轮预测时能更正确一点。这个学习过程被称为反向传播(backpropagation)。如此反复几千次,你的网络很快就擅长泛化了。
本教程不会解释反向传播的具体技术细节,但如果你有兴趣了解,可以参阅下面的文章:
- 反向传播的一步步示例:http://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/
- 神经网络黑客指南:http://karpathy.github.io/neuralnets/
- 神经网络和深度学习:http://neuralnetworksanddeeplearning.com/chap1.html
代码
现在你已经了解了基本的知识,就开始写代码吧!首先我们需要创建层。我们可以使用 synaptic 中的 new Layer() 函数。传递给该函数的数字表示每层应该有多少个神经元。
如果你不知道层是什么,可以看看上面提到的交互式教程。
- const{Layer,Network}=window.synaptic;varinputLayer =newLayer(2);varhiddenLayer =newLayer(3);varoutputLayer =newLayer(1);
接下来,我们将这些层连接到一起,并实例化一个新网络,如下:
- );
- hiddenLayer.project(outputLayer);varmyNetwork =newNetwork({
- input:inputLayer,
- hidden:[hiddenLayer],
- output:outputLayer
- });
所以,这就是一个「2 层-3 层-1 层」的网络,可以可视化为下图的形式:
现在训练这个网络:
- // train the network - learn XORvar 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]);
- }
这里我们运行该网络 20000 次。每一次我们都前向和反向传播 4 次,为该网络输入 4 组可能的输入:[0,0] [0,1] [1,0] [1,1]。
首先我们执行 myNetwork.activate([0,0]),其中 [0,0] 是我们发送给该网络的数据点。这是前向传播,也称为激活这个网络。在每次前向传播之后,我们需要执行反向传播,这时候网络会更新自己的权重和偏置。
反向传播是通过这行代码完成的:myNetwork.propagate(learningRate, [0]),其中 learningRate 是一个常数,给出了网络每次应该调整的权重的量。第二个参数 0 是给定输入 [0,0] 对应的正确输出。
然后,该网络将自己的预测与正确的标签进行比较,从而了解自己的正确程度有多少。
然后网络使用这个比较为基础来校正自己的权重和偏置值,这样让自己的下一次猜测更加正确一点。
这个过程如此反复 20000 次之后,我们可以使用所有四种可能的输入来检查网络的学习情况:
- ->[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]
如果我们将这些值四舍五入到最近的整数,我们就得到了正确的异或运算结果。
这样就完成了。尽管这仅仅只碰到了神经网络的表皮,但也足以帮助你进一步探索 Synaptic 和继续学习了。https://github.com/cazala/synaptic/wiki 这里还包含了更多好教程。
原文:
https://medium.freecodecamp.org/how-to-create-a-neural-network-in-javascript-in-only-30-lines-of-code-343dafc50d49
【本文是51CTO专栏机构“机器之心”的原创译文,微信公众号“机器之心( id: almosthuman2014)”】