2025上半年,最新 AI实践都在这!20+ 应用案例,任听一场议题就值回票价 了解详情
写点什么

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:596617
用户头像

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

关注

评论

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

上周刚面的美团 现已拿到offer,分享一下三面面经

Java架构之路

Java 程序员 架构 面试 编程语言

字节跳动Android面试:来一份全面的面试宝典练练手,不吃透都对不起自己

欢喜学安卓

android 程序员 面试 移动开发

DataPipeline合伙人&CPO陈雷:成为中国的世界级数据中间件厂商

DataPipeline数见科技

【科创人】融云CEO韩迎:飞信十年珍贵历练,做To B别有取巧的心思

科创人

蚂蚁金服三面真题:基础+高并发+消息中间件+GC算法+MySQL数据同步

Java架构之路

Java 程序员 架构 面试 编程语言

2021年3月国产数据库排行榜:OceanBase勇夺亚军 神舟挺进20强!

墨天轮

数据库 性能优化 运维

容器 & 服务:K8s与Docker应用集群 (一)

程序员架构进阶

容器 k8s 服务化 七日更 28天写作

区块链助力山东文化旅游整体行业解决方案

源中瑞-龙先生

Pgbouncer最佳实践:系列三

PostgreSQLChina

数据库 postgresql 软件 开源社区

女乘客跳车、货拉拉涉事司机被批捕

石云升

28天写作 3月日更

从业务在线化视角实施数字化落地的两大路径

boshi

数字化 七日更

2021Java岗面试清单最新整理:分布式/Spring/JVM/并发编程等(15专题全面解析)

比伯

Java 编程 程序员 架构 面试

快手基于 Flink 的持续优化与实践

Apache Flink

flink

大话 Python:python 操作 excel 系列 -- 能够操作 excel 的 python 库有哪些?

老王说编程

Python ecxel

程序员的数学

大奎

力扣(LeetCode)刷题,简单+中等题(第29期)

不脱发的程序猿

面试 LeetCode 编程之路 28天写作 算法面经

从根上理解高性能、高并发(七):深入操作系统,一文读懂进程、线程、协程

JackJiang

大话 Python:python 操作 excel 系列 -- 怎样将数据写入 excel 文件?

老王说编程

Python Excel xlsxwriter

【LeetCode】比特位计数Java题解

Albert

算法 LeetCode 28天写作

JVM 分析工具

insight

JVM 3月日更

字节跳动技术总监自爆:Android项目开发如何设计整体架构?建议收藏

欢喜学安卓

android 程序员 面试 移动开发

5G时代,为什么NoSQL和SQL存在短板?

VoltDB

数据库 通信 VoltDB 电信

牛掰,阿里架构师用 115 张原理与流程图,讲清了 Java 程序员常被问及的分布式架构核心知识点

Java架构师迁哥

四面字节跳动成功斩获offer(Java岗),只有努力复习,方能战胜寒冬

Java架构之路

Java 程序员 架构 面试 编程语言

homework2

Geek_xq

使用SSO增强身份安全性的四个原因

龙归科技

身份认证 SSO 密码管理

【数独问题】入门题:判断一个数独是否有效 ...

宫水三叶的刷题日记

面试 LeetCode 数据结构与算法

一周信创舆情观察(2.22~2.28)

统小信uos

基于 KubeVela 与 Kubernetes 打造“无限能力”的开放 PaaS

阿里巴巴云原生

容器 开发者 运维 云原生 k8s

一个100%省力的,让城市管廊运维变得轻松的秘诀

一只数据鲸鱼

物联网 数据可视化 智慧城市 3D可视化 智慧管廊

力扣(LeetCode)刷题,简单+中等题(第28期)

不脱发的程序猿

面试 LeetCode 编程之路 28天写作 算法面经

Clojure和Haskell——深度学习中的函数式语言之美_编程语言_Jun Wu_InfoQ精选文章