函数求值需要运行所有线程_精读《深度学习 - 函数式之美》

7793ac035f5378b112ea02ec086ceffc.png

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)))

可以看到,xy 分别是 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

如果你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。

关注 前端精读微信公众号

d47f46dc483e6857fffdfcd4a1aa4d40.png
版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/266317.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu下无法看到共享文件夹的解决办法

参考:Ubuntu下无法看到共享文件夹的解决办法 作者:一只青木呀 发布时间:2020-08-07 10:09:04 网址:https://blog.csdn.net/weixin_45309916/article/details/107856157 今天早上起来突然发现共享文件夹的查看不到了,找…

实现图书增删的代码_不仅仅是图书信息管理系统

点击蓝字 关注我们不仅仅是图书信息管理系统基于双链表,采用面向对象编程方法制作的图书管理系统❞效果演示root用户:账号:0,密码:0普通用户:账号:1001,密码:666666图书信…

Ubuntu18.04换源更新国内源

参考:Ubuntu18.04更新国内源 作者:一只青木呀 发布时间:2020-08-05 10:24:11 网址:https://blog.csdn.net/weixin_45309916/article/details/107808268 树莓派换源博文:https://blog.csdn.net/zhuguanlin121/article/d…

Vmware15的安装(ps解决:重装Vmware出现无法安装服务Vmware Authorization Service)

参考:Linux之Vmware的安装 作者:一只青木呀 发布时间: 2020-07-09 22:13:14 网址:https://blog.csdn.net/weixin_45309916/article/details/107238658 目录1.前言2.打开Vmware虚拟机安装包安装解决:重装Vmware出现无法…

内存,RAM(DDR),ROM(EEPROM、flash),存储卡(emmc,sd,tf)以及Cache的区别与联系

参考:内存,RAM,ROM,Cache的区别与联系 作者:一只青木呀 发布时间:2020-09-26 09:55:40 网址:https://blog.csdn.net/weixin_45309916/article/details/108808106 参考:EEPROM和flash…

idea 项目jar反编译java_带你上手阿里开源的 Java 诊断利器:Arthas

本文适合有 Java 基础知识的人群。本文作者:HelloGitHub-秦人HelloGitHub 推出的《讲解开源项目》系列,今天给大家带来一款阿里开源的 Java 诊断利器 Arthas 项目—— Arthas项目源码地址:https://github.com/alibaba/arthas一、简介 为什么要…

Windows如何开启虚拟化,以安装虚拟机?

参考:Windows如何开启虚拟化,以安装虚拟机? 作者:一只青木呀 发布时间:2020-08-28 20:58:45 网址:https://blog.csdn.net/weixin_45309916/article/details/108286787 设置BIOS 安装 Ubuntu 时报错&#x…

Ubuntu 16.04安装教程及虚拟机设置

摘自:Ubuntu 16.04安装教程及设置 作者:一只青木呀 发布时间: 2020-07-09 22:36:50 网址:https://blog.csdn.net/weixin_45309916/article/details/107239119 配合这篇博文:安装ubuntu20.04并进行优化——安装vim,gcc,…

PureMVC(AS3)剖析:设计模式(二)

PureMVC(AS3)剖析:设计模式(二) 模式 上一篇中介绍了PureMVC中使用的3种设计模式:单例模式、观察者模式、外观模式。本篇将继续介绍剩下的3种设计模式: l 使用中介者(Mediator&…

FileZilla的下载与安装以及简单使用(Ubuntu和Windows之间互传文件需要下载——客户端)

参考:FileZilla的下载与安装以及简单使用(有图解超简单) 作者:一只青木呀 发布时间: 2020-08-04 13:20:59 网址:https://blog.csdn.net/weixin_45309916/article/details/107782070?ops_request_misc%257B…

基于Matlab的循环码实验报告,基于MATLAB的循环码实验报告

及g(x)|C(x)上述定理告诉了构造(n,k)循环码的方法如下: ① 对xn-1 (在二元域中等效于对xn1)实行因式分解, 找出其中的(n-k)次因式。② 以找出的(n-k)次因式为循环码生成多项式g(x),与信息多项式m(x)相乘,即得码多项式:…

如何解决Filezilla 与虚拟机连接不上的问题

摘自:如何解决Filezilla 与虚拟机连接不上的问题 作者:一只青木呀 发布时间: 2020-08-28 21:48:04 网址:https://blog.csdn.net/weixin_45309916/article/details/108287326?ops_request_misc%257B%2522request%255Fid%2522%253A…

php 访问 sharepoint列表,SharePoint—用REST方式访问列表

REST的定义与作用在SharePoint 2010中,基本上有如下几种数据访问方式: 服务器端对象模型LINQ to SharePointWeb Service客户端对象模型ADO.NET Data Service (REST协议)ADO.NET Data Service (强类型)REST是SharePoint中一种数据访问方式,这种…

Vmware虚拟机三种网络模式配图详解

目录Vmware虚拟机三种网络模式详解Vmware虚拟机三种网络模式详解 具体的文字描述参见博文:https://www.cnblogs.com/linjiaxin/p/6476480.html Linux——Vmware虚拟机三种网络模式详解

SQL SERVER 中identity

SQL SERVER 中identity用法: 在数据库中, 常用的一个流水编号通常会使用 identity 栏位来进行设置, 这种编号的好处是一定不会重覆, 而且一定是唯一的, 这对table中的唯一值特性很重要, 通常用来做客户编号, 订单编号等功能, 以下介绍关于此种栏位常用方式及相关技…

同步IO、异步IO、阻塞IO、非阻塞IO、复用IO

参考:同步IO 异步IO 作者:今天天气眞好 发布时间: 2021-04-19 09:42:29 网址:https://blog.csdn.net/qq_51118175/article/details/115857196?spm1001.2014.3001.5501 目录同步IO与异步IO的区别?1.POSIX2.IO模型阻塞I…

java线程之基础学习

java线程之基础学习总结 线程实现的两种方式:在java中可以有两种方式实现多线程操作,一种是继承Thread类,另外一种是实现Runnable接口。 继承Thread类Thread类是在java.lang包中定义的一个类只要继承Thread类,要覆写run()方法。简…

python反编译exe_实战 Python3.7+64位 Exe 反编译

记得有年在上海弘连培训,其中一个逆向题就是关于python的Exe,当时就想着写个文档,后来因为忙就拖延了下来;这里补上,而且是大补上:奉献一个干货,网上没有(我没发现)Python3.7的反编译教程&#…

树莓派外设开发之接入语音模块

参考:树莓派接入语音模块控制继电器组 作者:糯米啊啊 发布时间: 2021-04-18 17:07:08 网址:https://blog.csdn.net/weixin_43732386/article/details/115834317?spm1001.2014.3001.5501 目录1.前言2.思路3.材料4.二次开发语音模块…

图片圆角

2019独角兽企业重金招聘Python工程师标准>>> //切图为圆角 public static Bitmap removeYuanjiao(Bitmap bitmap,int pixels){ int width bitmap.getWidth(); int height bitmap.getHeight(); Bitmap creBitmap Bitmap.createBitmap(width, height, android.grap…