文档结构  
翻译进度:已翻译     翻译赏金:10 元 (?)    ¥ 我要打赏

前言:这篇文字的写作(注[1])是在做任何形式的可行性研究之前,或部分可行性已经存在之前,因此你应该对文中的一切观点持保留态度,也许大部分观点的最终结果会大相径庭,我仍希望这篇文字能够抛砖引玉,对于那些非常有趣的东西,做了一些有用的探索。好吧,我们这就开始:

我期待编程变得更加声明式(译注[2])并且不要那么精确,详细一点来说,我们得看看现在的编程是怎样进行的:通常你有一些输入或者一个系统状态,想要得到一个结果或是其他的系统状态,你通过定义一系列精确的步骤来实现从输入到结果的过程。当然,这不再是通过系统指令直接完成了 —— 而是在输入和结果之间有许多抽象的层,所有这些抽象层都十分精确的和下层互相关联,当中没有任何的模棱两可。也就是说,我们实际上精确的指定了一系列很小的步骤,然后计算机去执行。总结:这里有个基本假设,计算机会做的唯一事情就是精确的执行一系列预定步骤,如果没有,那它什么也不做。

第 1 段(可获 2.74 积分)

曾经有一些尝试试图创造一种编程方法,可以不用给出精确的步骤,通过使用一个更加声明式的方法来引入逻辑语句和约束,并且能在其上进行演绎和求解。而困难在于,如果程序演绎不足,则可能哪里也去不成,求解器将给返回我们许多结果,除了正确的 / 想要的那个。如果我们选取一个最有可能是错误的结果,这里会带给我们下一个基本假设:假如程序留有一定的自由选择度,那么计算机很可能无法做出正确的选择。

当然,这些假设是完全合理有效的,至少对当今的计算机而言,我们编程的方式,以及我们用程序解决的那些问题,大部分都会继续保持。但是让我们超越这个问题,撇开这些假设来看:要是编程不涉及定义精确的步骤呢,而只是粗略定义一下我们有什么,我们要什么,也许再给一些提示,就能让电脑大致做出正确的事 —— 这不是很棒吗?

听起来不可能,对吧?不一定。不妨让我们先回顾下一些最近几年发生的事,有一些想法或许值得探索,曲径通幽。

第 2 段(可获 2.93 积分)

观察和预期

第一代计算机曾被用于各种各样的任务:比如高级计算器,管理公司财务,甚至控制火箭,计算到月球的路径等。这些应用领域都有一个共同特点:问题都有一个已知正确的解决方案 - 不得不进行自动化的原因仅仅是因为,人工执行任务的时候太过单调乏味,而且也不够准确和快速。另外,这些计算机的使用方式有一个很有趣的特点:从计算机中期望得到的结果被定义为精确计算的结果。为了理解我说的这句话,我们需要跳回到今天:

今天,一大批这种计算任务仍旧存在,可是大部分场景已经升格为:焦点已经不再是根据一系列指令来获取结果 - 如今我们只有一个目标,而不知如何到达。目标实际上会更远:对许多目标来说,比如怎样取悦人们,怎样卖出更多货,或者小一些的目标,比如怎样拥有一个可用接口,这些目标我们甚至都不知道如何实现,但是我们仍然尝试用我们一个个精确的步骤来压榨出“我们知道该去哪儿,以及怎么去那里” - 编程模型。

第 3 段(可获 2.95 积分)

在芯片开发方面,我们也可以看到一些很大的变化:晶体管越来越小,接近于物理极限,仍然能够保证它们始终正常工作。这与一个依赖于精确结果的编程模型是非常不一致的,每一步都被正确执行以获得正确的结果。如果我们能够使用和构建硬件, 而计算只能在大多数情况下都是正确的,那该怎么办呢? 这不仅可以解决缩放问题,还可以通过嵌入生物元素来查看全新的计算方法。

除了芯片开发中的要求和挑战的变化之外,系统还必须处理越来越多的噪声数据。

我们正在寻找的东西必须能够处理任何类型的噪音 - 在输入数据和处理过程中,只有准确的结果和偶尔的错误才能更好地处理。另外,还应该有一个方法来弄清楚如何做“正确的事情”,而不是给出确切的步骤。一个非常适合的领域是最近在机器学习方面的进步,特别是神经网络。如果我们不是在代码的某些部分调用它们,而是在它们之上构建一个完整的计算和编程模型。

第 4 段(可获 3 积分)

达到目的需要考虑什么

事先声明一下:我认为神经网络并不是这类问题的唯一解决方式。它甚至不是解决这类问题的正确方式,但目前来看它们是最有希望的方式。注意,要理解下面的内容你应该对神经网络有所了解。

我认为神经网络的主要研究方面有三个:一、编程接口,即新的编程模型里代码的样子。二、神经网络接口。这关乎神经网络里内部数据的表示、如何将它们与外部世界联系起来/如何利用现有技术和神经网络之间的自动连接。三、我会阐述一下为达成其他功能,神经网络里应改变的部分。

编程接口

“无米”之时,很难想象如何编码,尤其是代码很大程度上依赖于底层的计算模型的能力时。然而代码又十分重要,因为它给其他的工作赋予了目标,还定义了要完成目标的必要条件。

第 5 段(可获 2.43 积分)

我的第一个直觉就是去组合一个声明性的方法(能够定义我们拥有什么,我们想要什么以及一些网络必须工作的一些约束)和基于组件的思维(假设存在训练过的神经网络部件,用于训练去做或识别某些东西)。 声明性部分的启示可以来自现有的声明性语言(如Prolog)的语法,也可能来自不同的概率编程方法的一些想法。

这些将是最可能出错的部分(它绝对超出了我们目前在神经网络领域的能力),但是我会试着第一次尝试这样的代码看看会是什么样 - 在这种情况下,用一个有图片展示的网站赚钱:

Using Web { Domain = "FunnyClickbaitNMore.com" }
Using Content { Source = "./.../images.data" }
Using Ads { Source = "someadserver.com/ads.data" }

net = Net[requestID] {
    Using HTML
    IN Web.Requests[requestID]
    IN Content.AllAvailableElements
    IN Ads.AllAvailableElements
    OUT HTML.Page
}

Web { RequestHandler = net }

Goal = max(Ads.Revenue[requestID])
第 6 段(可获 1.78 积分)

这份代码依然包含大量的管道,因为它使用了大量已有的基础设施。 Using 载入组件, {} 中的部分设置组件作用域内的参数值。一个组件通常包含两个组成部分: 与已有的外部基础设施一起工作的普通代码与普通接口,神经网络将会连接的神经元。这些神经元或者是可重用的预训练网络的一部分, 或者是普通代码的神经接口的一部分 - 例如,我们使用图像作为输入时的图像处理网络的前几层。

Net 域是发生奇迹的地方 - 它定义了我们为解决任务而要训练的神经网络。这里的作用域来选择我们新的神经网络将会连接的神经元 - 该作用域内的每一个神经元组对神经网络都是可访问的。 N 标注定义了提供输入数据的神经接口,OUT 设置结果读取的位置。另外,在这个示例中我们有一个被载入到新神经网络作用域内的组件。这意味着它可以访问那里的所有神经元。例如在这个例子中 HTML 是一个 HTML 代码网络的预训练图片。很明显图像方面并不是非常有用,但是由于这些网络能够生成 HTML 代码,我们的新网络能够利用图像之前的几层并重用其他部分。

第 7 段(可获 3.2 积分)

最后,有一些胶水代码将一切连接起来 - [requestID] 为每一个网络调用设置作用域。在该示例中我们希望为所发生的所有网络请求调用网络并使其生成一个显示给用户的网络。Requests[requestID] 参数被重用使其能够访问相关的请求 - 理想情况下如果请求包含单词  "car" ,网络能够学到显示汽车的图片或广告将会有用。

Goal 定义了用于更新神经网络的奖励或错误。

我必须承认这相当复杂。正因如此,我准备了第二例子,该示例更接近于今天的功能,因而更容易理解。在该示例中,我们希望为二值图像分割训练一个神经网络。这意味着我们有一个输入图像以及一个粉饰相关像素的掩码,例如,汽车部分的像素。

input = Using Images { Source = "./.../images.list" }
reference = Using Images { Source = "./.../masks.list" }

Net[id] {
    IN input[id]
    OUT result[id]
}

Goal = min(delta(reference[id], result[id]))
第 8 段(可获 2.11 积分)

组件 Images 提供了载入图像列表的方法,以及能够访问图像的神经接口 (在该示例中类似于当今神经网络库中的图像数据层) ,使用 [id] 来指定。 在该示例中,id 是一个未绑定的变量,这意味着在其被使用的所有位置,在相同时刻应该具有相同的值。然后训练过程将会遍历所有可能的值,也就是所有图像。

正如你注意到的,我们并没有指定神经网络的真正布局 - 这应该是在训练过程中自动发生的。在该示例中我们依然能够这样做,但是在前面的示例中,手动发现有用的事情非常困难。自动化神经网络布局将会是到达那里的更有挑战性的任务之一  - 开始的一些想法将会在下面的内容中讨论。

神经网络接口

在神经网各接口领域有两个需要解决的主题:与现有工具交互的训练神经网络以及神经网络之间接口的自动训练。

第 9 段(可获 2.54 积分)

与面有工具或数据的交互可以非常简单,例如该示例中的图像,也可以非常复杂,例如前面想像的 HTML 示例。通常而言,对于任务如何开始有两个观点。

第一个也是当前更为流行的外部观点:也就是寻找如何将数据传递给神经网络,通常使用非常简单的编码,例如像素值或是字符序列,以及如何获得结果。 已经有许多重要的研究适用于不同的任务,包括图像,使神经网络生成并解析文本,甚至是使其读取代码并计算结果。

第二个也是我的观点,更为有趣的方法是采用内部观点并开始思考如何训练神经网络来利用已有的工具并访问数据自身,而不仅是传递数据。例如,通常人类并不是通过向其传递一个一个字符的方式来读取文本的,相反我们会尝试获取大块多个字符,并前后跳跃  - 也许这对于神经网络也会有用。另一个示例是写代码 - 没有人是仅写下字符序列就完成的。 我们也会跳跃,拥有自动完成,甚至是仅运行我们已有部分的反馈回路 - 为神经网络赋予这些功能也将会非常有用。

第 10 段(可获 3.11 积分)

接口之间的自动训练将是使得一切正常工作的核心挑战之一。一个非常简单的方法是仅将一切相连,然后逐步丢弃具有不重要权重的连接。这种方法的缺点是其速度非常慢,另外它并没有创建对于大多数时候好结果所必须的高级多层结构。另一种方法是由空开始,并在需要时动态添加神经元与连接 - 这里的困难是找出在哪里以及何时添加。

神经网络自身

基于当前的神经网络思想有一些有趣的事情需要解决,尽管并不是这种新的编程方式。 我认为最重要的问题之一是错误传播与梯度下降的使用。随着网络变得更深以及更不规则,例如该示例中,这将会成为一个越来越严重的问题。我期望前进的道路是找到一种创建某种局部紧急行为的方法。

同时,弄明白神经网络错误空间是什么样子会非常有用。为此,我们可以收集不同的参数权重配置以及相应的错误值,并寻找获取错误空间信息的方法。 这可以通过开发一种方法将高维特征空间映射到能够可视化查看的三维空间来实现, 或者至少可以通过查找同样可作用于高维空间的指标来实现。一种想法 (很有可能不工作,但是却给出一个应走向哪里的例子) 是通过在所有的权重参数上执行类似 PCA 的操作将其降维为2维,而使用误差或者错误作为第三维,高度维,来构建一个 3D 映射。通过这种方法可以了解所得到的高度配置,而且有可能找到最优结果所共同拥有的内容。使用 PCA 的问题可能在于最优值与所有其他值遍布于整个空间而导致高度混乱。但是也有可能存在适用于该示例的其他变换。

第 11 段(可获 4.78 积分)

作为高维参数的指标,适用于局部与全局最小值的谷的形状非常有趣。我的大胆猜测是来自过拟全的最优点会位于窄而陡峭的谷,而来自真实泛化的最优点位于较宽的谷。当然,这可能完全错误,但是这会为你提供一种思路,为什么这些指标类型对于构建更好的优化算法非常有用。

另一个非常重要的目标是找到一种无需预先定义结构来训练神经网络的方法,而是让训练过程找到一种合适的结构。作为起点,应该存在一种度量单个神经元与单个连接有用性的指标。 对于连接,权重意味着与零的距离,因为较小的值意味着通过连接的信息具有较小的影响因而很可能并不是非常相关。神经元的有用性可以定义为所有其连接有用性的组合,由于与层中其他神经元的相似性,也许需要减去或除以一个分值,因为对于两个相同连接的神经元,我们很有可能只需要一个。

第 12 段(可获 2.56 积分)

那么训练初始时可以仅由输入与输出之间的一个神经元开始,并动态添加或删除神经元,直到接近某个有用的阀值。然后一个新层  - 仅有一个神经元 - 可以使用其他的指标创建。也许类似于一层是否大于其两个邻居。在长期内,我希望最好能够脱离层结构。特别是面向特定硬件而不是 GPU 上的浮点处理时。另外,某些更为复杂的结构甚至可能并没有一个清晰的层结构。

毫无疑问,这篇文章并不完整 - 写下该文章的原因是,对我甚至可能对你,提供一些由哪里开始以及做什么的思路。如果你正在做类似的事情,或者其中的一部分,或者有一些想法,建议或问题,请联系我 research@bjenik.com. (我甚至准备了一个漂亮的 mailto: 链接,预先填写了一半的邮件,从而你仅需要书写内容。你应该去做 - 点击邮件地址吧。)

[1] 我相信今天的大量研究受限于首先了解, 然后变为专家,维持现状并构建小的迭代改进。最好首先确定一个目标,然后寻找到达那里的路- 至少我们就是这样登上月球的。

第 13 段(可获 3.25 积分)

文章评论