如果一门语言本身就是一个可微的编程系统,那写代码是什么感觉。近日,JuliaComputing团队发表了一篇论文,表明他们已经构建了一个可微分的编程系统,将自动微分嵌入到Julia语言中,从而使其成为一级语言特性。也就是说,以后可以直接用Julia语言写模型,可以微分编程吗?不再需要调用TensorFlow或PyTorch之类的框架了吗?如果我们把可微分的编程系统看作是一种编程语言最重要的特征之一,那么对于机器学习或者其他科学计算来说就会方便很多,这样的语言也将是科学计算的最佳语言。YCombinatorResearch的研究员MichaelNielsen对此也很兴奋,他非常认同AndrejKarpathy的“梯度下降是一个更好的程序员”的观点。Karpathy还回答说:“我们正在向前推进一点。我们现在没有一个完整的程序定义,而是在写一个粗略的架构。这样的架构将通过权重进行参数化。如果我们有一个很好的评估,那么优化算法可以帮助我们找到更好的解决方案。”这里Karpathy说的是机器学习和编程的区别,ML会通过梯度下降等优化方法自动寻找最优解。但是这里有个问题,模型需要梯度才能走向最优,所以很多部分模型要求是可微的,有鉴于此,很多人也称ML可微编程,但可微编程是否只能用于机器学习,是否可以扩展到其他领域,甚至成为编程语言的基本特征呢?答案是肯定的,这也是Julia团队和麻省理工学院等研究机构正在努力做的事情。近年来,机器学习模型越来越复杂,呈现出许多科学计算的特征,凸显了机器学习的强大能力。学习框架。据研究人员称,由于广泛的科学计算和机器学习领域需要借助底层结构中线性代数的支持,可以以可微编程的形式创建新的计算基础设施。论文地址:https://arxiv.org/pdf/1907.07587.pdfGitHub项目地址:https://github.com/MikeInnes/zygote-paper可微分编程和DL框架有什么区别?在论文中,研究人员提出了一种可微分的编程系统,可以在Julia语言中实现梯度计算,并成为Julia语言的一级特征。这使得构建深度学习模型更加直观。更重要的是,这允许用户使用现有的Julia科学计算包来构建深度学习模型并高效地实现梯度计算。那么可微编程与TensorFlow或PyTorch等深度学习框架有何不同,它是否比这些构建细粒度图的系统更快?研究人员表示,可微分编程执行源到源转换,自动微分转换基本上没有运行时开销,因此它优于反向传播的实际计算成本。也有开发者在Reddit上对此进行了讨论:一位名为“Coconut_island”的开发者表示,Zygote与现有机器学习框架的区别在于,Zygote将源代码视为计算图,省略了中间语言。过程。更重要的是,子梯度计算是通过控制流程进行的。这种梯度计算方法可以应用于任何控制流分支,具有代码的抽象性。科学计算与机器学习的结合:可微分编程乍一看,科学计算和机器学习是不同的领域。神经网络中现代机器学习的突破导致了整个学科的巨大进步。神经网络解决许多不同计算机科学问题的能力导致设计新的硬件和软件以提高性能、处理大量标记数据并同时在设备上部署经过训练的模型。相比之下,科学计算有着非常悠久的历史,并且希望使用一系列源自物理现象的建模技术。与典型的机器学习研究人员不同,许多科学计算科学家处理的数据量较小,但计算复杂度更高,数据范围更广。但从观察上看,科学计算和机器学习有一些共同点。这两个领域都倾向于使用动态编程语言进行计算,例如Python、R和Julia。一般来说,Python和R中的性能关键模块使用C++和Fortran,而在Julia中则较少。而且两者的核心计算过程都是基于线性代数,并且有专门的硬件来加速这个计算。由于机器学习和科学计算都依赖于线性代数,并且已经有大量的硬件优化来加速运算,可微编程有可能进一步融合两者。这项工作将以什么语言完成?由于编程工作量大,研究人员只选择在Julia语言中加入可微分的编程能力。选择这门语言的一个原因是,Julia语言已经有大量的机器学习和科学计算包,都是用纯Julia语言实现的。这有助于他们在相对大量的应用程序中进行测试。研究人员表示,现有的Julia包可以直接使用他们的系统,包括处理用户定义的类、基于状态的控制流,以及通过“源到源”自动微分的大规模标量操作。本文展示了一些使用可微分编程的案例。用Zygote对正弦函数求微分研究人员以正弦函数为例,讲解可微编程的方法。图为正弦函数sin(X)的泰勒展开式:这个公式可以用Julia语言定义。为了运行它,请安装Julia语言版本1.1或更高版本,并安装Zygote.jl和ForwardDiff.jl包。代码如下:usingPkgPkg.add("Zygote")Pkg.add("ForwardDiff")usingZygote,ForwardDifffunctions(x)t=0.0sign=-1.0foriin1:19ifisodd(i)newterm=x^i/factorial(i)abs(newterm)<1e-8&&returntprintln("i=",i)sign=-signt+=sign*newtermendendreturntend虽然正弦函数用Julia语言可以更好的表示,但是为了演示计算过程,一个循环,一个条件语句、“isodd”和“阶乘”函数,这些是Julia的原生实现。在微分计算中,自动微分直接起作用。下面是i从x=1.0开始的变化,计算出的梯度,当这个梯度与cos(1.0)的梯度匹配时。julia>ForwardDiff.derivative(s,1.0)#ForwardModeADi=1i=3i=5i=7i=9i=110.540302303791887julia>Zygote.gradient(s,1.0)#ReverseModeADi=1i=3i=5i=7i=9i=11(0.5403023037918872,)julia>cos(1.0)0.540302305868139可微分编程中的深度学习Zygote是一个灵活的深度学习模型梯度计算后端,非常高效。一个典型的例子如下所示,研究人员使用LSTM来学习莎士比亚的作品。下面的代码演示了Zygote的许多优秀特性,只需调用Julia语言的一些便利特性即可实现。首先,定义的模型没有特殊的数据类型,可以直接启用自动微分(AD);模型的定义只需要确定前向传播的计算流程,反向传播只需要定义BLAS操作和基本的数组操作等,手动定义只需要基本的构建块。Zygote也可以用来封装模型loss的计算,明确表示模型梯度的计算边界应该是可微的,但是代码的其他部分,包括我们定义的LSTMlevel,不需要考虑写入时自动微分过程。最终模型可以在CPU、GPU和谷歌的TPU上运行,它们不需要或只需要很少的修改。#Loaddataandalphabetalphabet,Xs,Ys=load_data("shakespeare_input.txt")#DefinesimpleLSTM-basedmodeltomapfromalphabetbackontoalphabet,#predictingthenextletterinacorpusofShakespearetext.model=Chain(LSTM(length(alphabet),128),LSTM(128,ngbethal(128)),softmax,)复制代码opt=ADAM(0.01)#Runthroughourentiredatasetafewtimesforepoch_idxin1:10,(x_batch,y_batch)inzip(Xs,Ys)#Calculategradientsuponthemodelforthisbatchofdata,#summingcrossentropylossacrosseachtimeindexinthisbatchgrads=|\Zygoteplain|.gradient(模型)domodelreturnsum(交叉熵。(模型),y_batch))end#Updatethemodel,thenresetitsinternalLSTMstatesmodel=update!(opt,model,grads)Flux.reset!(model)end如上图,整个模型和训练过程看起来很简单,有点像Keras或者PyTorch的编程风格,基本上只需要建立模型、计算梯度、更新参数等重要步骤。即使用户不太了解Julia的语法规则,它仍然很容易阅读,其中很重要的一部分是通过Zygote找到梯度。Zygote提供了一个成本极低的自动分化接口。通过执行源到源转换,AD转换基本上没有运行时开销,因此它优于反向传播的实际计算成本。此外,Zygote在TPUpod上训练ResNet,其性能水平与TensorFlow相同。表1:不同深度的LSTM网络的估计Zygote每次操作(OP)开销。为了衡量上述结果,研究人员对LSTM网络的反向传播进行了基准测试,并研究了运行时间与批量大小之间的关系,以进一步估算自动微分系统中每个操作的固定开销。研究人员最终在i5CPU和Julia1.3上完成了测试,结果非常具有竞争力,如表1所示。由于PyTorch等成熟的深度学习框架,每个op的实际开销至少为1μs。这些消失的开销提高了AD系统的效率和使用门槛,因此可以非常细粒度地??集成到编程语言中,而不用担心性能问题。通常,自动微分的开销越低,AD系统的最小可行内核越小。因此,我们只需要考虑反向传播效率就可以设计出小型高效的自动微分核。其他案例除了在Julia中实现LSTM模型的自动微分,论文还提供了使用可微分编程在其他机器学习领域的应用示例。弹射器问题-强化学习图3:使用神经网络解决逆向问题的替代方案基于模型的强化学习比无模型强化学习具有优势,因为高性能代理必须能够适应其环境动态。然而,深度强化学习模型无法与真实环境相结合,限制了其发展。过去的研究通常使用机器学习框架,可以成功实现逼真的物理引擎,但是这种工程投入非常大,而且相对于现有引擎来说是有限的,因此在生物或气象等领域应用起来相对困难.很少。Zygote可以用来解决控制问题,可以在梯度请求中控制模型的反向传播过程。研究人员以投石机问题作为实验案例。他们优化了一个可以处理多个目标的神经网络。神经网络的输入是到目标的距离和当前风速,网络的输出是投石机的设置(例如射程和发射角度)。输入来自模拟器,可以作为普通微分方差,计算着陆点到目标的距离。然后研究人员将实际结果进行比较,并进行反向传播以调整网络权重。研究人员的数据集是从一系列目标和风速中随机选择的。该智能体可以在笔记本电脑的CPU上进行训练,可以在恒定时间内解决反问题,比直接优化投石机系统的强化学习方法快100倍。计算机视觉在这种情况下,研究人员使用原型生成器来演示根据所需的最终生成图像优化点光源位置的过程。研究人员定义了一个损失函数,它将点光源作为输入,生成图像并将其与参考图像进行比较。按照惯例,可以提取梯度并用于更新点光源的位置。julia>guess=PointLight(Vec3(1.0),20000.0,Vec3(1.0,2.0,-7.0))julia>functionloss_function(light)rendered_color=raytrace(origin,direction,scene,light,eye_pos)rendered_img=process_image(渲染颜色,screen_size.w,screen_size.h)returnmean((rendered_img.-reference_img).^2)endjulia>gs=gradient(x->loss_function(x,image),guess)图4、5、6:生成的图片和点光源关系。4(左)是初始生成的图像,5(中)是迭代100次的结果,6(右)是目标图像。
