InfoQ 编辑部出品——2021年度技术盘点与展望 了解详情
写点什么

Clojure 和 Haskell——深度学习中的函数式语言之美

  • 2019 年 10 月 02 日
  • 本文字数:3821 字

    阅读完需:约 13 分钟

Clojure和Haskell——深度学习中的函数式语言之美

深度学习是基于人工神经网络的机器学习方法的一个子集。这些方法的灵感来自于大脑等生物系统中的信息处理方式和分布式通信节点。在深度学习中,每一层都要通过学习将输入数据转换成更加抽象和综合的表示形式。例如在人脸识别系统中,系统的某一层可能是像素,而另一层可能是图像中的边缘,眼睛和脸也可能分别都用一层来表示。深度学习方法如此复杂,所以编程社区习惯使用现成的包。基于 Python 语言的的 TensorFlow 和 PyTorch 很受欢迎,基于 R 语言的 Keras 包也很流行。然而,在深度学习系统的生产环境中,性能和安全性这两问题促使公司倾向选择 Clojure 和 Haskell 等函数式编程语言



深度学习实现的难点

在将深度学习系统投入生产环境时,神经网络可能包含多达一百万个参数。为了训练这些参数,训练数据可能会呈现爆炸式增长。如此庞大的数据需求,让深度学习的训练只能通过具有安全并发性和并行能力的高效编程语言来实现。神经网络的数据是一层层传递的,这种复杂性意味着编程语言处理这些数据时应该足够简单和一致。这里所说的安全性是指以一致的方式保留原始数据状态的能力,而简单性是指能够轻松地读取和维护代码库,同时最大化性能指标。


为什么函数式编程更适合深度学习

为了解决实现深度学习时可能出现的困难,程序员发现函数式编程语言可以提供解决一些方案


在计算机科学中,函数式编程是一种将计算作为数学函数评估,避免状态变化和数据变化的编程范式。它是一种更接近数学思维的编程模式。


深度学习模型本质上是数学模型。例如,人工神经网络由相互连接的节点组成,每个节点执行简单的数学运算。通过使用函数式编程语言,程序员能够用更接近操作本身的语言描述这些数学操作。这些程序的显式编写方式使得读取和维护代码库变得容易许多。


与此同时,深度学习算法的合成性质意味着,在神经网络的每一层上,这些层或函数往往会链接在一起执行任务。这可以通过函数式编程语言的函数链轻松实现。



此外,在深度学习中,当函数应用于数据时,数据不会改变。新值可能是沿行顺序往下输出的,但是数据本身会保持一致。函数式编程语言的不可变特性允许程序员在每次生成新值时创建一个新的数据集,而不需要修改原始的不可变数据集。这使得维护整个神经网络数据的一致性变得更加容易。


最后,实现深度学习涉及到大量的参数和训练数据,这意味着并行性和并发性是创建生产级深度学习系统的关键所在。并行性意味着在不同的 CPU 上运行线程以加速学习过程。并发性则是指管理线程以避免冲突的能力。函数式编程允许并发和并行,而不引入额外开销。这意味着,从本质上讲,函数式编程(纯函数是无状态的)将始终为特定的输入生成相同的输出,因此我们能隔离任何函数,并随时执行它。这使得并发性和并行性更容易管理。您不必处理诸如死锁和条件竞争之类的问题。运行在不同 CPU 上的不同线程能够独立运行,没有竞争。


Clojure

随着函数式编程在深度学习中越来越受欢迎,同时出现了许多用于深度学习的健壮包。Clojure 现在受到了沃尔玛和 Facebook 等公司的青睐。它是一种基于 LISP 编程语言的高级动态函数式编程语言,还带有编译器,可以运行在 Java 和.NET 运行时环境中。


Clojure 中强大的并发编程

Clojure 并非 Java 线程系统的替代品,而是与后者协同工作。由于核心数据结构是不可变的,因此可以在线程之间轻松地共享它们。与此同时,程序中的状态可以更改的,Clojure 提供了确保状态一致性的机制。如果两个事务在试图修改相同引用时发生冲突,其中一个将退出。这里我们不需要显式锁定。


import ‘(java.util.concurrent Executors))(defn test-stm [nitems nthreads niters](let [refs (map ref (repeat nitems 0))   pool (Executors/newFixedThreadPool nthreads)   tasks (map (fn [t]               (fn []                (dotimes [n niters]                  (dosync                   (doseq [r refs]                    (alter r + 1 t))))))              (range nthreads))]   (doseq [future (.invokeAll pool tasks)]      (.get future))   (.shutdown pool)   (map deref refs)))(test-stm 10 10 10000) -> (550000 550000 550000 550000 550000 550000 550000 550000 550000 550000)
复制代码


源代码


Clojure 中的并行性很廉价

在深度学习中,模型必须训练大量的数据。并行性意味着在不同的 CPU 上可以运行多个线程。廉价的并行性意味着显著的性能改进,将分区与映射结合使用可以实现成本更低的并行性。


(defn calculate-pixels-2 [] (let [n (* *width* *height*)       work (partition (/ n 16) (range 0 n))       result (pmap (fn [x]                  (doall (map                   (fn [p]                     (let [row (rem p *width*) col (int (/ p *height*))]                       (get-color (process-pixel (/ row (double *width*)) (/ col (double *height*))))))                   x)))                  work)]   (doall (apply concat result))))
复制代码


源代码


Clojure 中的链式函数意味着更清晰的代码

在 Clojure 中,很多函数只有很少的数据类型。函数也可以作为参数传递给其他函数,于是深度学习中就可以使用链式函数了。因为 Clojure 的实现更接近实际的数学模型,其代码也更容易阅读和维护。


;; pipe arg to function(-> "x" f1) ; "x1"
;; pipe. function chaining(-> "x" f1 f2) ; "x12"
复制代码


源代码


Clojure 中的标识和状态提供了安全性

在 Clojure 中,每个模型的标识在任何时候都有一个状态。这种状态是一个永远不会改变的真实值。如果标识看起来出现了变化,那是因为它关联到了不同的状态。新值是旧值的函数。在神经网络的每一层中,原始数据的状态始终保持不变。每组具有新值(函数的输出)的数据都可以独立操作。这意味着可以在这些数据集上安全地执行操作,不用考虑计算资源竞争。我们可以往回追溯,随时查阅数据的原始状态。因此在这种情况下,一致性即意味着安全性。


库和局限性

一直以来,Cortex机器学习库包含了在 Clojure 中实现机器学习算法所需的所有内容。随着最近用于深度学习的开源 MXNet 框架的日益流行,使用MXNet-Clojure API更容易实现深度学习。


尽管现在有许多不同的 API 和机器学习库可供 Clojure 使用,但是要熟练地使用 Clojure 仍然有一个陡峭的学习曲线。机器学习代码的报错信息可能是令人费解的,企业需要提前做一些投资,才能真正熟练使用它们,进而扩大机器学习系统的规模。随着使用 Clojure 编写的可用于生产系统的案例越来越多,这种语言将在未来几年变得越来越流行,但前提是使用 Clojure 语言的库的数量和规模持续增长。


Haskell

Haskell 是一种函数式语言,使用类型推断和延迟计算进行静态类型化。它在 Miranda 编程语言的语义之上,实现了一种更有表现力、更快、更安全的机器学习语言。


Haskell 中的类型安全提供了安全性和灵活性

类型安全定义了一种约束,即变量对应的值类型上的约束。这将有助于防止非法操作,提供更好的内存安全性,并减少逻辑错误。延迟计算意味着 Haskell 会延迟计算一个表达式,直到某个地方需要用到后再去计算它。它还避免了重复计算以节省运行时间。同时,延迟计算允许定义数量无限的数据结构。这给了程序员无限的数学可能性。


Haskell 中简单的显式代码提供了清晰的实现

Haskell 最大的优点之一是它可以用非常明确的数学结构描述算法。您可以用几行代码表示一个模型。您也可以像阅读数学方程一样阅读代码。这在复杂的算法中非常有用,比如机器学习中的深度学习算法就是一个典型例子。例如,下面实现的单层前馈神经网络就能看出代码的可读性优势。


import Numeric.LinearAlgebra.Static.Backproplogistic :: Floating a => a -> alogistic x = 1 / (1 + exp (-x))feedForwardLog   :: (KnownNat i, KnownNat o)   => Model (L o i :& R o) (R i) (R o)feedForwardLog (w :&& b) x = logistic (w #> x + b)
复制代码


源代码


Haskell 中的多核并行提供了高性能

在深度学习中,典型的神经网络定义的模型包含一百万个参数。而且需要大量的数据来学习这些参数,这在计算上是非常耗时的。在一台机器上使用多个核并行地共享内存和进程对于实现深度学习来说是非常重要的。而在 Haskell 中,实现多核并行很容易


库和局限性

Haskell 的HLearn库包含机器学习算法实现,同时也可以使用 Tensorflow 中的Haskell绑定来做深度学习计算,并行和并发库则用于并行和并发需求。


尽管有一些机器学习库是用 Haskell 开发的,但生产级的 Haskell 实现还是需要做一些基础工作。因为用于特定深度学习和机器学习任务的公共库数量不多,Haskell 在人工智能中的应用也是受限的。Aetion Technologies 和瑞士信贷全球建模和分析集团(Credit Suisse Global Modeling and Analytics Group)等公司正在实践中使用 Haskell——使用 Haskell 的组织的完整列表在此


结论

深度学习模型是复杂的数学模型,需要特定的函数层。函数式编程语言(如 Clojure 和 Haskell)通常可以用更简洁、更接近模型数学表达式的代码表示复杂内容。这将节省时间、提高效率,并简化代码库的管理。函数式编程的特定属性使这些语言的实现比其他语言的实现更安全。随着人工智能技术的发展,越来越多的人们将根据 AI 大规模系统开发项目的需求来评估这些语言。


本文来自 Behind the Code。访问Behind the Code发现更多的文章和视频。


原文链接


https://www.welcometothejungle.co/fr/articles/btc-deep-learning-clojure-haskell


2019 年 10 月 02 日 08:593930
用户头像

发布了 61 篇内容, 共 19.9 次阅读, 收获喜欢 130 次。

关注

评论

发布
暂无评论
发现更多内容

Java官方入门教程pdf,开课吧在线教育,面试分享一次成功的经历

Java 程序员 后端

Java开发从零开始,牛客网java选择题库,程序员Javaweb源码

Java 程序员 后端

Java开发教程,极客时间架构师训练营,面试流程4轮技术面+1轮HR

Java 程序员 后端

Java小技巧:尚学堂视频百度云密码,靠着这份900多页的PDF面试整理

Java 程序员 后端

Java工程师面试该怎么准备,尚硅谷java百度网盘,Java技术图谱

Java 程序员 后端

Java开发实战讲解,牛客网面试经验,Java编程入门教材

Java 程序员 后端

XA 分布式事务

风翱

分布式事务 10月日更

Java开发从零开始,java基础入门传智播客网页版,Java后端路线图

Java 程序员 后端

Java开发人员不得不收集的代码,史上最全的微服务专业术语面试50问

Java 程序员 后端

Java开发实战讲解,牛客网面试经验,Java高级知识图谱

Java 程序员 后端

Java开发工程师笔试题目,图灵学院vip百度云盘,阿里P8大牛手把手教你

Java 程序员 后端

Java工作资料,java编程思想第五版百度云,面试官6个灵魂拷问

Java 程序员 后端

Java开发五年,java百度人脸识别,最全153道Spring全家桶面试题

Java 程序员 后端

Java岗面试必问!java面试题pdf下载百度云,Java程序员算法书籍

Java 程序员 后端

Java开发人员不得不收集的代码,精选Java面试真题集锦

Java 程序员 后端

Java小技巧,springboot菜鸟教程电子版,腾讯T2手把手教你

Java 程序员 后端

Java就业班资料,极客大学算法训练营百度网盘,Java面试总结

Java 程序员 后端

Java工程师最容易遇到4个瓶颈是什么,Java架构面试题spring原理

Java 程序员 后端

Java并发原理解析!图灵学院四期java架构师,Java零基础入门视频

Java 程序员 后端

最近几天在 InfoQ 连更的再反思

baiyutang

10月日更

Java开发前景怎么样,java全套教程百度云,linux基础入门教程

Java 程序员 后端

Java开发岗还不会这些问题,想拿高工资

Java 程序员 后端

【大咖直播】Elastic Security 安全管理实战工作坊(第二期)

腾讯云大数据

elasticsearch

复习

IT蜗壳-Tango

10月日更

Java开发你需要了解的那些事,Java线程池基础入门和简单实践以及使用技巧

Java 程序员 后端

Java就业班视频,尚硅谷众筹项目视频及源码,spring框架教程

Java 程序员 后端

Java开发中遇到最难的问题,redis视频教程韩顺平,附小技巧

Java 程序员 后端

Java开发入门与实战!极客学院和黑马程序员,Java高级工程师系列学习路线介绍

Java 程序员 后端

模块一作业

忘记喝水的猫

架构训练营

Java工程师进阶,马士兵架构师破解吧,我的Java春季历程

Java 程序员 后端

Java开发三年月薪才12K,java图形化界面教程,linux网络架构详解

Java 程序员 后端

Clojure和Haskell——深度学习中的函数式语言之美-InfoQ