函数求值需要运行所有线程_精读《深度学习 - 函数式之美》
1 引言
函数式语言在深度学习领域应用很广泛,因为函数式与深度学习模型的契合度很高,The Beauty of Functional Languages in Deep Learning — Clojure and Haskell 就很好的诠释了这个道理。
通过这篇文章可以加深我们对深度学习与函数式编程的理解。
2 概述与精读
深度学习是机器学习中基于人工神经网络模型的一个分支,通过模拟多层神经元的自编码神经网络,将特征逐步抽象化,这需要多维度、大数据量的输入。TensorFlow 和 PyTorch 是比较著名的 Python 深度学习框架,同样 Keras 在 R 语言中也很著名。然而在生产环境中,基于 性能和安全性 的考虑,一般会使用函数式语言 Clojure 或 Haskell。
在生产环境中,可能要并发出里几百万个参数,因此面临的挑战是:如何高效、安全的执行这些运算。
所以为什么函数式编程语言可以胜任深度学习的计算要求呢? 深度学习的计算模型本质上是数学模型,而数学模型本质上和函数式编程思路是一致的:数据不可变且函数间可以任意组合。这意味着使用函数式编程语言可以更好的表达深度学习的计算过程,因此更容易理解与维护,同时函数式语言内置的 Immutable 数据结构也保障了并发的安全性。
另外函数式语言的函数之间都是相互隔离的,即便在多线程环境下也不会发生竞争和死锁的情况,函数式编程语言会自动处理这些情况。
比如说 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)
上面的代码创建了引用(refs),同时创建了多个线程自增这个引用对象,按理说每个线程都修改这个引用会导致竞争状态出现,但从结果来看是正常的,说明 Clojure 引擎在执行时会自动解决这个问题。实际上当两个线程出现竞争而失败时,Clojure 会自动重试其中之一。
原文介绍
Clojure 的另一个优势是并行效率高:
(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))))
使用 partition
结合 pmap
可以使并发效率达到最大化,也就是 CPU 几乎都消耗在实际计算上,而不是并行的任务管理与上下文切换。Clojure 凭借 partition
对计算进行分区,采取分而治之并对分区计算结果进行合并的思路优化了并发性能。
原文介绍
Clojure 另一个特性是函数链式调用:
;; pipe arg to function
(-> "x" f1) ; "x1";; pipe. function chaining
(-> "x" f1 f2) ; "x12"
其中 (-> "x" f1 f2)
等价于 f2(f1("x"))
,这种描述不仅更简洁清晰,也更接近于实际数学模型。
原文介绍
最后,Clojure 还具备计算安全性,计算过程不会修改已有的数据,因此在神经网络的任何一层的原始值都会保留,每层计算都可以独立运行且函数永远幂等。
Haskell 也有独特的优势,它具有类型推断、惰性求值等特性,被认为更适合用于机器学习。
类型推断即 Haskell 类型都是静态的,如果试图赋予错误的类型会报错。
Haskell 的另一个优势是可以非常清晰的描述数学模型。
想想一般数学模型是怎么描述函数的:
fn =>f1 = 1f2 = 9f3 = 16n > 2, fn = 3fn-3 + 2fn-2 + fn-1
一般语言用 if-else
描述等价关系,但 Haskell 可以几乎原汁原味的还原函数定义过程:
solve :: Int -> Interger
solve 1 = 1
solve 2 = 9
solve 3 = 16
solve n = 3 * solve (n - 3) + 2 * solve (n - 2) + solve (n - 1)
这使得阅读 Haskell 代码和阅读数学公式一样轻松。
原文
Haskell 另一个优势是惰性求值,即计算会在真正用到时才进行,而不会在计算前提前消费掉,比如:
let x = [1..]
let y = [2,4 ..]
head (tail tail( (zip x y)))
可以看到,x
与 y
分别是 1,2,3,4,5,6...
与 2,4,6,8...
的无限数组,而 zip
函数将其整合为一个新数组 (1,2),(2,4),(3,6),(4,8)...
这也是无限数组,如果将 zip
函数执行完那么程序就会永远执行下去。但 Haskell 却不会陷入死循环,而是直接输出第一位数字 1
。这就是惰性计算的特性,无论数组有多长,只有真正用到某项时才对其进行计算,所以哪怕初始数据量或计算量很大,实际消耗的运算资源只取决于这次计算实际用到的部分。
由于深度学习数据量巨大,惰性求值可以忽略海量数据输入,大大提升计算性能。
3 总结
本文介绍了为什么深度学习更适合使用函数式语言,以及介绍了 Clojure 与 Haskell 语言的共性:安全性、高性能,以及各自独有的特性,证明了为何这两种语言更适合用在深度学习中。
在前端领域说到函数式或函数之美,大部分时候想到的是 Class Component 与 Function Component 的关系,这个理解是较为片面的。通过本文我们可以了解到,函数式的思想与数学表达式思想如出一辙,以写数学公式的思维方式写代码,就是一种较好的函数式编程思路。
函数式应该只有表达式,没有语句,这是因为函数式是为了处理运算而诞生的,因此很适合用在深度学习领域。
讨论地址是:精读《深度学习 - 函数式之美》 · Issue #212 · dt-fe/weekly
如果你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。
关注 前端精读微信公众号
版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证)
函数求值需要运行所有线程_精读《深度学习 - 函数式之美》相关推荐
- 函数求值需要运行所有线程_JavaScript函数式编程(二)
纯函数就是,对于相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用,也不依赖外部环境的状态 但是实际的编程中,特别是前端的编程范畴里,"不依赖外部环境"这个条件是根本不可 ...
- Python分支基础题练习(1. 英制单位和公制单位互换 2.掷骰子决定做什么 3.分段函数求值 4.输入三条边的长度如果能构成三角形就计算周长和面积)
Python 分支基础题练习二 练习一 英制单位和公制单位互换: 代码分析: 使用Input()函数获取到数值和单位 根据输入的单位按照相应的计算方法计算出结果 输出结果 程序示例: "&q ...
- 1035: 分段函数求值 C语言
1035: 分段函数求值 时间限制: 1 Sec 内存限制: 30 MB 提交: 33715 解决: 23213 [状态] [讨论版] [提交] [命题人:admin] 题目描述 已知:y是x的函数, ...
- 【C语言】分段函数求值 控制输出格式 float精确到小数点后几位
案例如下 //分段函数求值 #include <stdio.h> //#include <math.h> int main() {float x,y;printf(" ...
- python使用函数求特殊a串数列和_习题6-2 使用函数求特殊a串数列和
#include int fn(int a, int n); int SumA(int a, int n); int main() { int a, n; scanf_s("%d %d&qu ...
- 26 利用switch语句解决问题 【项目1:投票表决器】【项目2:成绩等级】【项目3:分段函数求值switch语句版】【项目4:本月有几天?】【项目5:个人所得税计算器switch语句版】
/*项目1:投票表决器] 设计一个投票表决器,其功能是: 输入Y.y,打印agree 输入N.n,打印disagree 输入其他,打印lose */#include <stdio.h>in ...
- 深度学习模型建立过程_所有深度学习都是统计模型的建立
深度学习模型建立过程 Deep learning is often used to make predictions for data driven analysis. But what are th ...
- 深度学习:在图像上找到手势_使用深度学习的人类情绪和手势检测器:第1部分
深度学习:在图像上找到手势 情感手势检测 (Emotion Gesture Detection) Has anyone ever wondered looking at someone and tri ...
- 深度学习将灰度图着色_通过深度学习为视频着色
深度学习将灰度图着色 零本地设置/ DeOldify / Colab笔记本 (Zero Local Setup / DeOldify / Colab Notebook) "Haal Kais ...
最新文章
- python怎么画小海龟_Python 海龟 turtle 画图实战任务(一):让小海龟留下Z字形的足迹以及绘制一个小于号<...
- mysql8自定义安装位置_【MySQL】Windows10:MySQL 8 自定义路径安装
- Linux网络编程 | 信号 :信号函数、信号集、统一事件源 、网络编程相关信号
- The following module was built either with optimizations enabled or without debug information - winz
- 网络安全08-虚拟机运行架构(寄居架构+原生架构)、虚拟机产品简单介绍、windows操作系统--屏蔽系统自动更新
- 当当网新用户注册界面——界面源码
- surround360
- 小说网jsp源码_基于jsp+mysql的JSP小说网
- php 开启coredump,GDB分析PHP连接Memcached 导致coredump问题
- dz email地址无效_Zcash屏蔽地址漏洞或揭示全节点IP地址(附解决方案)
- 图像运动模糊原理及python实现
- memcached全面剖析–memcached的删除机制和发展方向
- 无法启用数据库中的 Service Broker,因为已存在启用的具有相同 ID 的 Service Broker。...
- CCNP交换实验(5) -- 网关热备冗余
- 百度地图python_python百度地图API爬取街景
- 闭关修炼,看了老大的博客,才发现自己是多么的技术低,原来我就达到06年的他...
- 安装 LaserJet 1020 时这个设备的驱动程序丢失了一个必需的项,这可能是由于 inf 是为 Windows 95 或更新版本而写的。联系您的硬件供应商。
- mac系统升级导致VirtualBox报Kernel driver not installed (rc=-1908)
- 博学笃志 追求卓越--献给研究生的12条忠告与建议
- python 实现轨迹数据可视化
热门文章
- HAProxy介绍及配置文件详解
- 很棒的HTML5效果实例
- 勒索病毒攻击应急防范
- Android——Fragment实例精讲——底部导航栏+ViewPager滑动切换页面
- 设计模式是用来弥补面向对象编程缺陷的方法总结
- fread函数和fwrite函数,read,write
- h.264 rtp打包
- 全景图像拼接——基本流程
- HALCON示例程序count_fish_sticks.hdev鱼棒完整性检测
- 【error】深度优先搜索TypeError: unhashable type: ‘list‘