无论是开始接受还是从事一些新事物,总是不容易的。机器学习是可能需要尽快学习新项目的编程技能之一,但你或许并不知道从哪里开始。当然,在这个大社交媒体、门户网站经常出现的这个词,或许真的是出现在你简历上的一个很好的证明。
本文将使用Clojure和Cortex进行机器学习。你将学习如何从头开始创建易于理解和随时可用的神经网络,以及使用经过训练的网络REPL与LISP获得即时结果。
Cortex可能会是比较新的概念,但它是现有机器学习框架的一个非常有力的替代方案。它基于Clojure,消除了培养和运行自己的网络所需的大部分代码。
为了突出如何训练和使用网络,本文将介绍一个创建简单的秘密函数(即网络的秘密),训练网络以便能够计算以前从未见过的输入,并迅速获得好的结果。
Cortex本身就是一个Clojure库,它提供API来创建和训练自己的网络,包括自定义输入、输出和隐藏层,并估计当前训练的网络的好坏。
最小的Clojure项目设置是一个相当标准的Leiningen设置,Leiningen成为Clojure的实际构建工具,安装起来很轻松。
我们还将使用REPL之一的Gorilla REPL来绘制Web REPL来绘制函数,稍后会看到。
Gorilla插件允许运行Web REPL,并可以使用上述project.clj文件中提供的笔记本别名来启动它。 以下是它看起来像一个简单的终端或控制台命令:
在Clojure命名空间中,将定义以下三件事情:
网络应该正确映射的秘密功能
一个随机输入序列的生成器
数据集生成器,提供网络进行训练。 这将调用secret-fn来产生训练网络所需的输入和输出。
在这个项目中,包含代码的Clojure命名空间在src / tutorial.clj中定义,并将被两个Gorilla笔记本使用。
在Gorilla REPL启动后,前往以下本地网址:
这是REPL所在的地方,你可以在那里跟随笔记本,直接在浏览器中输入Clojure代码和命令。
准备
第一个任务是导入一些Cortex命名空间。
网络和图层名称空间将被用来定义网络的内部。 train命名空间采用网络定义和数据集来产生训练有素的网络。 最后,execute命名空间将训练好的网络和一个额外的仅用于输入的数据集与所提供的输入一起运行网络。 tutorial名称空间包含上面编写的代码,带有隐藏函数和数据集生成器。
创建和测试输入生成器将是第一步。 输入生成器会生成许多由两个元素组成的元组。
随机序列生成器可以提供输入和输出数据集,内部使用隐藏函数。
现在生成数据的样子已经很清楚了,我们来创建两个数据集:都是20000个元素。 教数据集将被用来告诉网络什么是已知的,应该记住什么是真的,而测试数据集将被用来测试网络的正确性并计算它的分数。 有两个完全不同的集合通常会更好。
现在有两个强大的、奇妙的数据集,就可以编写网络,网络被定义为由四层组成的共同线性网络。
两层将用于预期的输入和输出,而另外两层将定义内部结构。 定义神经网络的层次本身就是一门艺术。 在这里,我们把双曲正切作为激活函数。实际上一个经过良好训练的网络,它有两个激活层。
看到这里,有一个很好的介绍它的话题。
第一层定义了网络入口和输入,并且有两个元素作为一个输入,并且输入的标签被命名为:x
最后一层定义了网络的输出,只有一个元素,其ID将是:y
使用Cortex API提供了下面的小型网络代码:
所有需要训练网络的模块都被定义了,就像女王曾说过的一句话:
这一切都和训练有关:如果你训练有素的话,你可以做很多事情。——英国女王伊丽莎白二世
训练
训练的目标是拥有自己的训练网络,你可以立即使用或者提供给其他用户,以便他们可以完全独立使用你的网络。
训练是分步完成的。每个步骤都采用批处理中的教学数据集的元素,并用一些系数缓慢地拟合每个图层的块,以便整个图层组可以给出接近期望输出的结果。我们正在使用的激活功能在某种意义上就是模仿人类的记忆过程。
在每个示教步骤之后,使用提供的测试数据集对网络进行准确性测试。在这个阶段,网络与现有的内部部门一起运行,并与之前的版本进行比较,以了解它是否执行得更好,从而计算出一种被称为网络丢失的情况。
如果发现网络比上一次更好,Cortex会将网络保存为一个NIPPY文件,该文件是网络的一个压缩版本,以地图的形式表示。说够了;让我们最后开始那个训练。
训练的输出将在日志文件中,如果你看,你可以在日志中看到的第一件事就是网络是如何在内部表示的。 以下是不同的图层,每个图层的输入和输出尺寸以及要适合的参数数量。
然后,每个步骤/时代都会获得新的分数,以及网络是否更好,并在这种情况下,保存。
每个步骤的得分都会给出网络的有效性,并且损失越接近零,网络执行得越好。 所以,在训练你的网络的同时,你的目标应该是尽可能地将损失值尽可能接近零。
3000次的全面训练只需要几分钟,一旦完成,就可以立即了解训练的网络是如何运作的。 如果时间比较紧张,1,500-2,000是一个很好的时间范围,可以让你在速度和已经相当精确的训练好的网络之间做出妥协。
培训完成后,将在当前文件夹中找到新的my-fn.nippy文件。 这是一个基于训练的Cortex网络版本的压缩文件。
伴随项目中包含了训练有素的网络mynetwork.nippy的副本。 网络的损失方面让人比较满意,值接近于零,如下所示。
让我们用手动定义的自定义输入来给新训练的网络一个镜头。
这非常接近预期的0 * 1 = 0输出。
现在,让我们尝试一下网络从来没有见过的双值元组。
7.42比预期的结果相当好,5 * 1.5 = 7.5。
使用网络
正如你所见,训练有素的网络被保存在一个NIPPY文件中。 该文件可以被网络的外部“用户”加载和使用。 从现在开始,如果你看看提供的笔记本,你可以加载下面的注释:
用户需要一些名称空间。 本教将执行命名空间(即util)用于从文件中加载网络,并且由Gorilla插件提供绘图来绘制值。
之后,我们计划绘制预期的结果与网络提供的结果。
加载训练好的网络是使用Cortex提供的read-nippy-file功能的简单方法。
我们以前没有看过,但是网络确实是一个地图,你可以检查它的顶级密钥。
检查网络经历的历元数量以及当前的损失值是一个好主意。
你可以确认载入网络的结果与上一节中刚刚接受训练的版本相同。
现在,让我们用加载的网络生成一堆结果并绘制它们。 (在新的输入集上运行网络对于你来说现在可能是微不足道的!)
当然,我们可以检查网络产生的一些结果值。
可以使用Gorilla提供的来自 Gorilla-plot.core命名空间的绘图功能进行绘图。 在这里,我们将只关注输出,将使用Clojure的平坦函数来创建一个输出值的平集合,而不是在结果中找到的向量序列。
在指定颜色后,知道图应该使用线条而不是点,可以在浏览器REPL中直接看到下面的图形。
你也可以生成一个由已知或未隐藏函数直接产生的预期结果与训练网络产生的结果组成的“组合”图。
这两条线实际上太靠近了,完全相互重叠。
重新训练
从那里,一个有趣的进展路径将是采取目前训练的网络,并通过使用更多的数据集,并再次运行皮层训练n功能使其更好。
注意:通过指定一个新的网络文件,可以保留一个独立版本的更新网络。
而且,对于新的数据集和一个新的训练周期,仍然有一个很好的机会来实现一个更好的网络,在这种情况下,使用新的文件名再次保存网络。
结论
在这篇文章中你已经看到了如何训练自己的神经网络来模拟已知函数的输出。 了解了如何生成并提供用于训练的所需数据集,以及Cortex如何保存最佳网络的文件版本。
现在有一些想法是:
尝试相同的一个不同的隐藏你自己的功能。
更改网络元数据中功能和网络的输入和输出参数的数量。
如果网络性能不尽如人意,可在网络的不同层面上花费一些时间,找到更好的配置。