作者归档:admin

微积分——自动微分

  梯度下降法(Gradient Descendent)是机器学习的核心算法之一,自动微分则是梯度下降法的核心;
  梯度下降法用于求损失函数的最优值,前面的文章中我们说过梯度下降是通过计算参数与损失函数的梯度并在梯度的方向不断迭代求得极值;但是在机器学习、深度学习中很多求导往往是很复杂的,手动使用链式法则求导很容易出错,借助于计算机也只能是硬编码;
  这时候就需要借助于自动微分了,求导主要有这么四种:手动微分法数值微分法符号微分法自动微分法,这里分别说说这几种求导方法;

手动微分法(Manual Differentiation)
  手动微分法需要我们手动编写出代价函数激活函数的求导代码,硬编码这些函数的求导方法,如果这些函数后面有调整该函数的求导方法又要重新实现,可以说是又麻烦又容易出错;
数值微分法(Numerical Differentiation)
  通过使用函数值来估计函数的导数,该方法主要是计算速度慢,精度差等问题;
符号微分法(Symbolic Differentiation)
  符号微分广泛用在各种数学软件中如Matlab、Octave等,它通关过使用符号表达式进行求导,符号微分是基于求导法则进行的;

  如表达式:f(x) = 2y + x^2
  表达式树为:
    enter image description here

  通过符号微分法求得:

  enter image description here

  符号微分有个缺陷就是得到的导数不一定是最简的,函数较为复杂时表达式树会很复杂,可能会出现表达式爆炸的情况出现;

自动微分法(Autodiff)

  自动微分法介于数值微分符号微分 之间,数值微分是直接代入数值近似求解而符号微分为直接通过表达式树对表达式进行求解;自动微分先将符号微分用于基本的算子,带入数值并保存中间结果,后应用于整个函数;自动微分本质上就是图计算,容易做很多优化所以广泛应用于各种机器学习深度学习框架中;
  自动微分又分为前向模式(Forward mode Autodiff)反向模式(Reverse-Mode Atuodiff)求导;

前向模式(Forward mode Autodiff)

  前向模式引入二元数(dual number),同时会先将表达式转换为计算图然后会依次从下往上计算每一步的导数,由于每步都使用了上一步的导数所以不会导致重复计算不会出现像符号微分一样的表达式膨胀问题,但由于深度学习的参数比较多所以前向模式的效率还是有些差;一个前向过程就可以求出其函数值与导数,下面简单举个例子:

  二元数:a+bꜫ
  a与b都是实数,ꜫ为无穷小的数,且ꜫ^2=0,并满足加分与乘法法则,且还有:
    enter image description here
  这样是要求出f( a+ꜫ)就可以得出f(a)与f(a)的导数;
  还是上面的表达式:f(x) = 2y + x^2

    enter image description here

  如上图当x=2,y=3时,我们可以得出:二元数 10+4ꜫ,即函数f(x)关于x的偏导数为:4,函数值为10;

反向模式(Reverse mode autodiff)

  反向模式为先通过正向遍历计算图求出每个节点的值,然后通过反向遍历整个图,计算出每个节点的偏导,其原理为微积分链式法则,这里所说的反向模式其实也就是我们在深度学习中所说的BP算法(反向传播算法),只需要一个前向传播、一个反向传播就可以求得所有参数的导数,所以性能很高,非常适用于深度学习中的自动求导;

          enter image description here

  上图为经过反向传播的计算图,根据链式法则:
enter image description here
enter image description here

  正如上面所说的,经过一次正向传播求出所有的节点值后再经过一次反向传播就求得了所有输入参数的导数效率很高,而且避免符号微分、数值微分所带来的问题;目前Tensoflow、MXNet等深度学习框架中也都使用了反向模式实现自动微分只是各种具体算法还是有不少差异;

参考资料:
https://blog.csdn.net/aws3217150/article/details/70214422
https://arxiv.org/pdf/1502.05767.pdf

使用Skaffold一键将项目发布到Kubernetes

  当前skaffold版本为v0.4,还未发布正式版本,不建议在生产环境中使用;
  skaffold用于开发人员快速部署程序到Kubernetes中;skaffold提供了dev、run两种模式;使用skaffold需先编写skaffold配置文件,该文件为定义skaffold的工作流;
  Skaffold工作流定义了三个主要阶段Build、Push、Deploy

enter image description here

一、Build
  在构建阶段,Skaffold通过Dockerfile使用源码生成Artifacts,Skaffold中目前Docker镜像、bazel这两种Artifacts,这里使用的是Docker镜像所以也可以成称为Docker镜像,该镜像用于应用程序的运行,Build阶段的输出就是Artifacts;
二、Push
  在推送阶段,Skaffold将把构建阶段生成的Docker镜像推送到Docker镜像仓库中,并使用所配置的镜像名称;在运行Skaffold时需确保镜像能够推送到镜像仓库中;
  但如果使用的是Minikube或 Docker for Desktop本地Kubernetes集群时默认是不推送到镜像仓库的,跳过推送阶段,因为本地已经存在了该镜像所以是可以正常运行的;
三、Deploy
  部署阶段,将最新的Docker镜像部署到k8s中,该阶段可以使用不同的部署工具如kubectl或helm,每个工具都有不一样的参数用于定义如何安装与更新应用程序;

概念介绍

Artifacts
  在Build阶段通过运行一系列步骤来创建Artifacts,在Skaffold中Artifacts分为bazel与Docker镜像,可以定义Skaffold生成多个Docker镜像,Skaffold在开发模式运行时,Skaffold只会重新生成源码已经更改的Docker镜像,通过在Skaffold配置中指定Dockerfile来生成Docker镜像,并指定其名称;

标签策略
  标签策略在Build阶段进行配置,用于配置Skaffold在推送Docker镜像时如果对镜像进行打标签,目前Skaffold支持三种标签策略:sha256标签生成器、git标签生成器、自定义标签生成器策略
  在开发过程中,推荐使用基于内容的标签策略sha256,方便在源代码变更时Skaffold会使Kubernetes重新部署新Docker镜像;

运行模式

  Skaffold有dev、run两种运行模式,也就是开发模式与发布模式,在dev模式下Skaffold会监控项目的源码随着代码的变更会实时的重新生产镜像并将变更更新部署到Kubernetes中;还可在CI/CD管道中运行Skaffold;

  dev模式默认使用sha256标签生成器
  run模式默认使用git标签生成器

  所以注意如果使用run模式又没配置git则Skaffold是无法跑下去的,需配置标签策略(TagPolicy),或配置git即可;

使用流程:

  开发环境使用skaffold部署项目到远程k8s中;
  1、下载skaffold
https://github.com/GoogleCloudPlatform/skaffold/releases/download/v0.4.0/skaffold-windows-amd64.exe
  2、下载kubectl、服务端开放Docker远程连接
在服务端Docker配置中加上: -H tcp://0.0.0.0:2375
  在开发端在创建C:\Users\xin.docker\config.json文件,内容如下:

 {
    "auths" : {
    }
 }

  3、开发端kubectl 配置
  创建C:\Users\xin.kube\config.json文件,配置k8s的连接与密钥,文件内容如下:

 apiVersion: v1
 clusters:
 - cluster:
     server: http://182.61.xx.xxx:8001
   name: minikube
 contexts:
 - context:
     cluster: minikube
     user: minikube
   name: minikube
 current-context: minikube
 kind: Config
 preferences: {}
 users:
 - name: minikube
   user:
 as-user-extra: {}

  4、服务端kubectl使用开启代理
  kubectl proxy –address 0.0.0.0 –accept-hosts ‘.*’
  5、环境变量配置
  需要在环境变量中配置Docker的链接信息:

 DOCKER_HOST = tcp://xxx.xxx.xxx.xxx:2375
 DOCKER_TLS_VERIFY = 0

  下载Demo并使用Skaffold将其部署到Kubernetes中;

  git clone https://github.com/GoogleCloudPlatform/skaffold
  cd examples/getting-started

运行:skaffold dev

enter image description here
enter image description here

  可以看到由于使用的是Minikube所以只有Build、Deploy两个阶段跳过了Push阶段,与我们上面的说法是一致的;
修改main.go的内容即可看到Skaffold检测到了变化,并重新把项目更新到Kubernetes中;

enter image description here
enter image description here

  常见异常信息:

 WARN[0005] run: build: build step: running build: read auth configs: docker config: opening docker config: 
 open C:\Users\xin\.docker\config.json: no such file or directory   

不存在.docker\confog.json文件,在用户目录下添加上即可;

 open //./pipe/docker_engine: The system cannot find the file specified. In the default daemon configuration on 
 Windows, the docker client must be run elevated to connect. This error may also indicate that the docker 
 daemon is not running.  

  未配置Docker环境变量,加上DOCKER_HOST、DOCKER_TLS_VERIFY环境变量即可;

本文使用的环境为:minikube、skaffold v0.4、windows

参考资料: https://github.com/GoogleCloudPlatform/skaffold/blob/master/docs/concepts.md