机器学习系统或者SysML&DL笔记(一)

前言

在使用过TVM、TensorRT等优秀的机器学习编译优化系统以及Pytorch、Keras等深度学习框架后,总以为有必要从理论上对这些系统进行一些分析,虽说在实践中学习是最快最直接的(指哪儿打哪儿、不会哪儿查哪儿),但恶补一些关于系统设计的一些知识仍是很是有用了,权当是巩固一些基础了。node

所以,有必要学习了解一下机器学习系统的设计和思想。若是不是很了解机器学习系统的设计,能够看下知乎上关于这个问题的回答:相比AI算法研究,计算机系统研究没落了吗?python

如下是本系列文章的笔记来源:git

注意,这一系列文章并非传统的深度学习或者机器学习讲解,关于这部分的讲解能够看CS231n或者吴恩达的入门课,该系列文章适合在深度学习方面有经验有了解的童鞋。github

附一张CSE 599W这门课(偶像tqchen主讲)一开始的讲解说明:算法

TIM截图20190509181944

这门课主要的重点不在深度学习理论算法,而是与深度学习有关,机器学习系统方面的讲解。数据库

什么是深度学习

简单说下深度学习。编程

TIM截图20190509182437

由上图可知,深度学习所包含的基本内容,也就是如下四大部分:api

  • 模型的设计(最核心的地方,不一样的任务设计的模型不一样,使用的具体算法也不一样)
  • 目标函数,训练策略(用于训练模型权重参数的目标函数,也就是损失函数,以及一些训练的方法)
  • 正则化和初始化(与训练过程当中的模型权重信息有关系,加快训练的收敛速度,属于训练部分)
  • 足够多的数据(机器学习亦或深度学习都是由数据驱动着了,没有数据的话就什么都不是)

咱们在学习深度学习的过程当中,不免会有一些实践,因而咱们就利用如下这些优秀的深度学习库去实现咱们本身设计的模型,而且设计好损失函数,一些正则化策略,最终利用这些库去读入咱们须要新联的数据,而后运行等待便可。网络

TIM截图20190509190226

这些优秀的深度学习库(caffe、Mxnet、TF、Pytorch)咱们应该都耳熟能详了,那么这些深度学习库的大概结构都是什么呢?架构

大部分的深度学习库都是由如下三个部分组成

  • 用户API
  • 系统组件
  • 底层架构

大多数的咱们其实并不须要接触除了用户API之外的其余两个部分,而用户API也是深度学习库最顶层的部分。

TIM截图20190509191530

Logistic Regression

拿个例子简单说一下用户的API,首先咱们有一个逻辑回归的任务,就拿最熟悉的MNIST数据集来进行演示,咱们经过输入每一个数字的向量化数据,而后经过全链接层去计算这些向量而且利用softmax函数进行预测。整个网络模型很简单已有一层全链接层。

TIM截图20190509191558

接下来咱们看一下使用numpy和tinyflow(这是一个迷你的深度学习系统库,麻雀虽小五脏俱全,值得咱们去学习)去训练一个简单的神经网络识别MNIST手写数据库的例子:

上述代码中最重要的也就是三个部分(在上图右侧已经列了出来):

  • 前向计算:由于只有一个全链接层,因此咱们的计算也很简单$h_{k}=w_{k}^{T} x_{i}$,其中$ x_{i}$为输入的数据,$w_{k}^{T}$为权重,$h_{k}$为权重向量和数据向量点乘的结果。计算出来结果后咱们使用softmax函数对其进行分类计算获得对应十个数字的几率向量(最后输出的向量包含10个元素,分别为每一个数字的可能性)
  • 反向求导:咱们求出权重W关于极大似然损失的导数,这里咱们人工写了出来,在右图第二部分
  • 梯度更新:咱们简单对权重W进行更新,更新值为学习率乘以W的梯度,即$w \leftarrow w-\eta \nabla_{w} L(w)$,也就是咱们常常用的SGD

整个深度学习库中最重要的也就是上述三个部分,大部分的深度学习库已经帮咱们实现了上述的代码,咱们不须要重复造轮子,直接使用便可。

尝试使用TensorFlow like API

接下来,咱们使用相似于TensorFlow的API来对上述描述的代码进行重构,使用TensorFlow的API格式来实现上述代码实现的训练过程。

那么,为何要使用TensorFlow类型的API进行演示而不是采用Pytorch呢?其实TensorFlow与Pytorch构建的图类型很不同,虽然在最近一段时间TensorFlow已经出现了eager mode,但经典的TensorFlow是采用静态图来构建整个训练过程的。

也就是说,在TF中构建的是静态图,而在Pytorch中构建的是动态图:

Computation_model

其实关于静态图和动态图对于这个话题已经通过了不少的讨论,动态图灵活多变,而静态图虽然没有动态图灵活,可是由于提早都肯定好了输入参数,计算方式等等过程,系统能够针对这些特色来对计算进行规划,因此在计算过程当中的性能比动态图是要高一些的。

首先咱们肯定要进行的前向数据以及操做算子:

  • 输入x为float32类型的向量,[None,784]中None表示当前输入的batch-size未知
  • W为权重信息,维度为[784,10]
  • y为前向计算函数,利用算子函数嵌套定义了整个计算过程。

tinyflow-1

接下来设定了损失函数,能够看到

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y), reduction_indices=[1]))

这句中声明了一个损失函数,使用的是分类任务中最经常使用的交叉熵损失,注意y_表明存放么一个数据的分类label,每个数据的分类标签是一个元素数量为10的向量,用于与预测出来的值进行比对。具体的公式在下图右侧。

tinyflow-2

接下来设定了自动求导的过程,这一步中咱们要求的是权重向量对损失值(也就是交叉熵损失后计算出来的值)的梯度,这里咱们只是声明了一个函数,可是其中的计算过程是比较复杂的(也就是咱们常说的自动求导的过程),这个以后会进行讲解,自动求导是咱们必需要掌握的,直接手撸是必须的。

tinyflow-3

设定好了损失函数,接下来咱们就要拿计算出来的梯度值来更新网络的权重信息了,在这个例子中使用SGD随机梯度降低的方式进行权重更新,咱们只须要设定学习率这个超参数就能够。

tinyflow-4

由于在TF中,全部的声明式都仅仅是对要计算的流程进行声明,实际上并无计算(这里能够称为一个懒计算的方法),也就是所谓的静态图方式定义好了整个网络以及训练的步骤,只是没有开始运做而已。

在运行完sess.run一句后,整个网络才开始正式执行起来。

tinyflow-5

这几张ppt的内容讲述了一个典型的神经网络库的运行流程(TF类型的,若是是Pytorch的话略有不一样),经过这个咱们能够知道一个深度学习框架的基本做用。接下来要说的就是上述过程当中最为重要的自动求导过程。

计算图(Computation Graph)

计算图是实现自动求导的基础,也是每一个深度学习框架必须实现的部分,接下来咱们简单说说计算图是什么?

要提及计算图首先简单提一下声明式编程,正以下图中所展现的,计算图本质上是一种声明式语言,怎么说比较合适,这种语言不一样于咱们平时所说的python和C++,它是一种DSL(领域语言)或者一种迷你语言,这种语言深刻嵌入到Python和C++中,也就是咱们使用Python去操做,使用C++去具体实现。

是声明式编程不是简单地一条接一条地执行咱们的指令,而是根据咱们给出的全部指令建立一个计算图(computing graph)。这个图被内部优化和编译成可执行的 C++ 代码。这样咱们就能同时利用上两个世界的最优之处:Python 带来的开发速度和 C++ 带来的执行速度。

最终形态就是咱们提早设定好了计算逻辑,其余的交给系统就好了,具体怎么优化就不用咱们去操心。

下图中就是一个简单的例子,咱们定义计算的逻辑a*b+3这个逻辑,其中node表示计算内容,箭头表示依赖关系。

computation_graph1

下图中咱们就利用TF-like API去实现一个简单的$t=softmax(W*x)$的过程,这个过程须要的数据(x、W)和算子(matmult、softmax)都已经提早定义好了。

computation_graph2

接下来是设置损失函数的计算部分:

computation_graph3

而后设定与自动求导相关的梯度降低部分:

computation_graph4

接下来是设定梯度更新的方式:

computation_graph5

在设定玩全部的计算逻辑后,这里正式开始计算的过程,只有执行完sess.run这句后,整个计算图才开始真正的进行计算了。

computation_graph6

上面关于自动求导的具体过程并无展现,这个过程将在下一节中进行讲解,不过关于自动求导的具体流程也能够在CS231n这门课中见到,具体在Backpropagation and Neutal Networks这一节中。

numpy 与 TF-program 的比较

以前咱们使用了numpy与TF-like API的方式模拟了一个简单的Logistic Regression的过程,也就是实现利用一个简单的全链接网络去识别手写数字集MNIST的过程,这个过程当中咱们使用了两种不一样的方式去构建,用计算图来讲就是动态图(numpy)与静态图(TF),而用语言类型来讲就是命令式编程(numpy)和声明式编程(TF)

其实上述的numpy的例子也可使用Pytorch作演示,由于Pytorch是一个类numpy的深度学习库,其操做的算子逻辑和numpy几乎一致,能够说是一个利用动态图结构的领域语言。

也就是说关于numpy与 TF-program 的比较,能够等同于关于动态图和静态图的比较,二者各有优缺点,可是若是追求性能和开发效率的话,静态图更胜一筹,可是若是追求灵活性和可拓展性,那么动态图的优点就展示出来了。

discuss_numpy_and_tf

未完待续

这节课的末尾提出了一些后续要讲的内容,首当其冲的就是计算图的优化。

计算图优化在TVM中这个深度学习编译器中占了很大的篇幅,正以下面所说,咱们创建了计算图,由于这个计算图是静态的,因此咱们能够在底层对其进行尽量地优化,从而加快神经网络运行的速度,那么如何去优化呢?这可就是一个大学问,总之就是咱们可优化的空间很大,而关于优化的具体细节放在以后进行描述。

TIM截图20190512165609

另一点,数据并行也是重点解决的问题之一,毕竟如今的数据愈来愈多,显卡计算能力虽然每一年提高,可是内存(具体点就是显存)的提高有限。那么如何更高效更快地训练大量的数据,直接的途径就是并行分布式训练,如何处理并行期间出现的问题也是一个重点的方向。

parallel_scheduling

相关参考

http://dlsys.cs.washington.edu/schedule
https://ucbrise.github.io/cs294-ai-sys-sp19/
http://www.javashuo.com/article/p-zvtrboqt-rc.html

撩我吧

  • 若是你与我志同道合于此,老潘很愿意与你交流;
  • 若是你喜欢老潘的内容,欢迎关注和支持。
  • 若是你喜欢个人文章,但愿点赞👍 收藏 📁 评论 💬 三连一下~

想知道老潘是如何学习踩坑的,想与我交流问题~请关注公众号「oldpan博客」。
老潘也会整理一些本身的私藏,但愿能帮助到你们,点击神秘传送门获取。

相关文章
相关标签/搜索