您的位置:首页 > 其它

关于深度学习入门需要掌握的技能

2017-07-19 09:24 344 查看
如果你想进入这一领域,你应该首先学习 Python。尽管这一领域还支持其它很多语言,但 Python 是应用范围最广而且最简单的一个。

但是为什么要选择 Python 呢——毕竟 Python 速度这么慢?

因为大多数的深度学习的库都使用的是符号式语言(symbolic language)方法而非命令式语言(imperative language)方法。

命令式编程:命令 “机器” 如何去做事情 (how),这样不管你想要的是什么 (what),它都会按照你的命令实现。
声明式编程:告诉 “机器” 你想要的是什么 (what),让机器想出如何去做 (how)。

解释一下也就是说:不是一条接一条地执行你的指令,而是根据你给出的所有指令创建一个计算图(computing graph)。这个图被内部优化和编译成可执行的 C++ 代码。这样你就能同时利用上两个世界的最优之处:Python 带来的开发速度和 C++ 带来的执行速度。

人们对深度学习的兴趣越来越大了,但人们并不愿意等待算法训练所需的大量计算时间(而且我说的是 GPU,想都不要想只使用 CPU)。这也是多 GPU 支持、多机器上的水平扩展甚至定制硬件最近开始得势的原因。

神经网络本质上是一种语言,我们通过它来表达对应用问题的理解。例如我们用卷积层来表达空间相关性,RNN 来表达时间连续性。根据问题的复杂性和信息如何从输入到输出一步步提取,我们将不同大小的层按一定原则连接起来。近年来随着数据的激增和计算能力的大幅提升,神经网络也变得越来越深和大。例如最近几次 imagnet 竞赛的冠军都使用有数十至百层的网络。对于这一类神经网络我们通常称之为深度学习。从应用的角度而言,对深度学习最重要的是如何方便的表述神经网络,以及如何快速训练得到模型。
对于一个优秀的深度学习系统,或者更广来说优秀的科学计算系统,最重要的编程接口的设计。他们都采用将一个_领域特定语言 (domain specific language) 嵌入到一个主语言中。例如 numpy 将矩阵运算嵌入到 python 中。这类嵌入一般分为两种,其中一种嵌入的较浅,其中每个语句都按原来的意思执行,且通常采用_命令式编程 (imperative programming),其中
numpy 和 Torch 就是属于这种。而另一种则用一种深的嵌入方式,提供一整套针对具体应用的迷你语言。这一种通常使用_声明式语言 (declarative programing)_,既用户只需要声明要做什么,而具体执行则由系统完成。这类系统包括 Caffe,theano 和刚公布的 TensorFlow。
这两种方式各有利弊,总结如下



目前现有的系统大部分都采用上两种编程模式的一种。与它们不同的是,MXNet 尝试将两种模式无缝的结合起来。在命令式编程上 MXNet 提供张量运算,而声明式编程中 MXNet 支持符号表达式。用户可以自由的混合它们来快速实现自己的想法。例如我们可以用声明式编程来描述神经网络,并利用系统提供的自动求导来训练模型。另一方便,模型的迭代训练和更新模型法则中可能涉及大量的控制逻辑,因此我们可以用命令式编程来实现。同时我们用它来进行方便的调式和与主语言交互数据。
举个简单例子

声明式编程

公司开年会需要买道具,HR 告知每一个节目负责人:“你们节目需要什么道具?告诉我,我会去买。”

然后,每个节目负责人会和自己的组员商量节目内容,最后给 HR 一个道具列表,之后就等着 HR 通知去领道具就行了。

结束了!这就是声明式编程的思想。

命令式编程

HR 告知每一个节目负责人:“要开年会了,你们有 XXXXX 元的预算,自己想办法去买,怎么买去哪买自己搞定,记得要发票,拿发票填报销申请,清楚了吗?”

各节目负责人:“好吧。”

HR 又补了一句:“对了,买完之后记得告诉我道具有多大,不然不知道租多大车运去年会现场。”

各节目负责人齐声说:“知道了。”

然后,每个节目负责人就去淘宝天猫或者京东上去找道具,和店家讨价还价,下单,要发票,回来之后填报销申请,然后还要告诉 HR 道具有多大,嗯,每个节目负责人都要忙这么一圈。

我真心希望,你所在公司不是用这种命令式编程的方式来采购年会道具的。

现在,你看到了 “声明式编程” 和 “命令式编程” 的差别了吗?

在声明式编程中,开发者要做的事情只是描述 “我要的是什么样子”,至于具体怎么做,并不是开发者要关心的事情。在 React 中,每个组件通过 render 函数返回 “这个组件应该长得什么样”,而不去描述 “怎么样去让这个组件长成这个样子”。

在声明式编程的 Hulu 年会道具采购方式中,HR 相当于 React,各节目负责人相当于基于 React 开发的组件,各节目负责人只描述自己需要什么,而具体的采购、报销、运输事务都由 HR 完成。

与此相对的,在命令式编程的方式下,每个节目负责人都操碎了心,处理的事务很多,各组重复劳动不说,还容易出错。


声明式编程的好处

声明式编程让开发者的工作简化了

在年会的例子里,HR 和各节目负责人的接口清晰而简单,节目负责人不用操心怎么买,不用操心怎么报销,不用操心怎么运输,专心搞艺术创作就行。

当然,有人也许要抬杠,说:不还是有 HR 在操这些心吗?

一个人操心总好过一群人操心吧,而且,我相信 HR 比你更会讨价还价,也更会买。

React 也一样,也许你能够用 jQuery 写出超厉害的代码,但是 React 处理 DOM 更专业,不会比你处理得更差。

声明式编程减少了重复工作

各节目负责人的采购和报销,其实都是重复的劳动,毫无创意可言,这种事情交给 HR 统一来操作,肯定会效率更高,而且不容易出错,简单说,HR 干这些事情专业啊,专业的事情就交给专业的人去做。

React 让开发者不用再记忆 jQuery 那变幻无穷的 DOM 操作方式了,一样也是避免了重复劳动,减少了出 bug 的可能。

声明式编程留下了改进的空间

假如说,突然发现我司突然有人贡献了一个超级会员卡,在某电商网站上买东西一折优惠,我们当然想要用上,因为这是一个巨大的改进。

在命令式编程风格下,因为每个节目负责人自己操作采购,那就要把这张超级会员卡送到每一个节目负责人手上去买;在声明式编程风格下,各节目负责人不操心采购,只要把这张卡交给 HR 一个人就搞定了。

在 React 的世界里,如果 React 有一个重大的内部结构改进,比如 React Fiber,虽然算法改头换面,但是组件却几乎不用改,因为组件只操心 “显示什么” 而不操心 “如何显示” 啊,当然不受影响了。

声明式编程提供了全局协调能力

还是举个例子,假如我们的年会节目预算有一百万(我说的是假如),在命令式编程的风格下,HR 怎么确保不要超了预算呢?如何防止预算没有被充分使用呢?

似乎没有好办法,要是完全靠各组负责人自觉,保不准某个组真的买了九十九万的道具,那就完了,所以,一般 HR 用平均分或者给按人头给每个组一个报销额度上限,超额部分不给报销,这样当然可以避免超支。

但是,也有可能某些组比较朴素,群口响声,道具只买了十几个折扇,这样就白白浪费了预算,HR 完全不知道如何协调,因为这些采购操作都是各组操作的,不到报销的时候她不知道钱怎么花的呀。

在声明式编程的风格下,各组的采购都由 HR 来控制,HR 就能够全局控制一下,发现某组实际想要买的道具价格很低,那其他组的道具就可以多花一些钱,这样一百万基本都能花光,这样一来,预算就充分发挥作用了。

HR 也不用要求各节目负责人上报道具大小,因为收货人是 HR,她自然知道道具是多大。

在 React 的未来,每个组件还是只声明 “想要画成什么样子”,但 React 却可以改进协调算法,让 React 组件根据不同优先级来渲染,提高用户感知性能,但是 React 组件的代码不需要改变,也是一样的道理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: