0%

深度学习应用

CV

图片识别 Image Classification

神经网络输入为图片数据,输出值为当前样本属于每个类别的概率
VGG系列, Inception系列, ResNet系列

目标检测 Object Detection

通过算法自动检测出图片汇中物体的大致位置,并分类出物体信息
RCNN, Fast RCNN, Mask RCNN,SSD,YOLO系列

语义分割 Semantic Segmentation

通过算法自动分割并识别图片中的内容,可以将语义分割理解成每个像素点的分类问题,分析每个像素点属于物体的类别
FCN, U-net, SegNet, DeepLab

视频理解 Video Understanding

视频分类,行为检测,视频主体抽取
C3D,TSN, DOVF, TS_LSTM

图片生成 Image Generation

通过学习真实图片的分布,获得高逼真的生成图片
VAE系列,GAN系列

NLP

机器翻译

Seq2Seq,BERT,GPT, GPT-2

聊天机器人

强化学习

虚拟游戏

机器人 Roboitcs

自动驾驶 Autonomous Driving

深度学习主流框架

  • TensorFlow
    Google 推出 TensorFlow 2 正式版本,将以动态图优先模式运行,从而能够避免
  • PyTorch
    是 Facebook 基于原有的 Torch 框架推出的采用 Python 作为主要开发语言的深度学习框架。采用命令式编程,使得搭建网络和 调试网络非常方便。

  • Keras
    是一个基于 Theano 和 TensorFlow 等框架提供的底层运算而实现的高层框架, 提供了大量方便快速训练,测试的高层接口,对于常见应用来说,使用 Keras 开发效 率非常高。但是由于没有底层实现,需要对底层框架进行抽象,运行效率不高,灵活 性一般。

  • Torch
    是一个非常优秀的科学计算库,基于较冷门的编程语言 Lua 开发。Torch 灵活性 较高,容易实现自定义网络层,这也是 PyTorch 继承获得的优良基因。但是由于 Lua 语言使用人群较小,Torch 一直未能获得主流应用。

  • Caffe
    主要面向使用卷积神经网络的应用场合,并 不适合其他类型的神经网络的应用。Caffe 的主要开发语言是 C++,也提供 Python 语 言等接口,支持 GPU 和 CPU。
    Caffe2 目前已经融入到 PyTorch 库中。

  • Scikit-learn
    是一个完整的面向机器学习算法的计算库,内建了常见的传统机器学习算 法支持,文档和案例也较为丰富,但是 Scikit-learn 并不是专门面向神经网络而设计 的,不支持 GPU 加速,对神经网络相关层实现也较欠缺。

  • MXNET
    由华人博士陈天奇和李沐等人开发,已经是亚马逊公司的官方深度学习框 架。采用了命令式编程和符号式编程混合方式,灵活性高,运行速度快,文档和案例 也较为丰富。

  • Theano
    是最早的深度学习框架之一,由 Yoshua Bengio 和 Ian Goodfellow 等人开发, 是一个基于 Python 语言、定位底层运算的计算库,Theano 同时支持 GPU 和 CPU 运 算。由于 Theano 开发效率较低,模型编译时间较长,同时开发人员转投 TensorFlow 等原因,Theano 目前已经停止维护。

图片识别 Image Classification

神经网络输入为图片数据,输出值为当前样本属于每个类别的概率
VGG系列, Inception系列, ResNet系列

目标检测 Object Detection

通过算法自动检测出图片汇中物体的大致位置,并分类出物体信息
RCNN, Fast RCNN, Mask RCNN,SSD,YOLO系列

语义分割 Semantic Segmentation

通过算法自动分割并识别图片中的内容,可以将语义分割理解成每个像素点的分类问题,分析每个像素点属于物体的类别
FCN, U-net, SegNet, DeepLab

视频理解 Video Understanding

视频分类,行为检测,视频主体抽取
C3D,TSN, DOVF, TS_LSTM

图片生成 Image Generation

通过学习真实图片的分布,获得高逼真的生成图片
VAE系列,GAN系列

语言类:
C++, Python, Java, Matlab, Js, C#, Delphi, VB, Swif

框架类:
前端:
React, Redux
后端:
Django, Spring MVC

服务器:
Tomcat, Nginx, uWSGI

机器学习框架:
TF2, pytorch, paddle paddle

数据库:
Mysql, Sql server, Postsql, DBF

应用开发:
微信小程序,智能卡片内系统开发, Windows服务

文档类:
Latex, MarkDown

工具:
Ubuntu, Docker

通过历史数据学习到一个模型,通过模型预测未来
f: x->y

机器学习分类:

  • 有监督学习:
    有监督学习的数据集包含了样本x与样本的标签y,算法学习需要学习到映射 $ f_{\theta}: x \rightarrow y$,其中 $ f_{\theta} $代表模型函数 $ \theta $为模型参数。在训练时, 通过计算模型的预测值$ f_{\theta}(x) $ 与真实标签 $ y $之间的误差来优化网络参数$ \theta $, 使得网络的下一次预测更精准。如线性回归, 逻辑回归, 支持向量机, 随机森林

  • 无监督学习:
    只有样本$x$的数据集, 算法本身需要自行发现数据的模态。如自编码器,生成对抗网络

  • 强化学习: 通过与环境进行交互来学习解决问题的策略。强化学习并没有明确的”正确的”动作监督信号,算法需要与环境进行交互,获取环境反馈的滞后的奖励。如DQN, PPO

1.计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂,时刻在运行。
2.假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。
3.进程就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。
4.一个车间里,可以有很多工人。他们协同完成一个任务。
5.线程就好比车间里的工人。一个进程可以包括多个线程。
6.车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。
7.可是,每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所。里面有人的时候,其他人就不能进去了。这代表一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。
8.一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。这就叫”互斥锁”(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。
9.还有些房间,可以同时容纳n个人,比如厨房。也就是说,如果人数大于n,多出来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用。
10.这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。这种做法叫做”信号量”(Semaphore),用来保证多个线程不会互相冲突。
不难看出,mutex是semaphore的一种特殊情况(n=1时)。也就是说,完全可以用后者替代前者。但是,因为mutex较为简单,且效率高,所以在必须保证资源独占的情况下,还是采用这种设计。
11.操作系统的设计,因此可以归结为三点:

以多进程形式,允许多个任务同时运行;

以多线程形式,允许单个任务分成不同的部分运行;

提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。

这个类比可以很形象的说明进程与线程的区别。
当然面试的时候你不可能说上这一堆,面试官估计要跟你急,时间宝贵,我们需要用最精简的语言说出两者的概念以及区别。
你可以这样分点回答(面试时需要逻辑条理清晰、语言简洁、直中要害):
(1)进程
进程是程序的一次执行过程,是一个动态概念,是程序在执行过程中分配和管理资源的基本单位,每一个进程都有一个自己的地址空间,至少有 5 种基本状态,它们是:初始态,执行态,等待状态,就绪状态,终止状态。
(2)线程
线程是CPU调度和分派的基本单位,它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
(3)联系
线程是进程的一部分,一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
(4)区别:理解它们的差别,我从资源使用的角度出发。(所谓的资源就是计算机里的中央处理器,内存,文件,网络等等)
根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位
在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)
内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。
包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

扩展阅读
为什么需要设计线程?
在传统进程模型中,进程的内涵可分为下面两个方面:
调度、执行的基本单位:每个进程都有自己的运行状态、优先级、寄存器等,是OS调度的基本单位。
资源所有权:包括程序、数据、文件等资源。一个进程拥有对这些资源的所有权,OS则提供保护功能,避免不同进程之间的资源冲突。
既然是两个独立的功能,可不可以把它们分离呢?这就出现了线程(thread)的概念:
执行与调度的基本单位:thread
资源所有权:process
那么执行与调度的基本单位是线程,这样设置有什么好处?
计算机操作系统里面有两个重要概念:并发和隔离。
并发是为了尽量让硬件利用率高,线程是为了在系统层面做到并发。线程上下文切换效率比进程上下文切换会高很多,这样可以提高并发效率。
隔离也是并发之后要解决的重要问题,计算机的资源一般是共享的,隔离要能保障崩溃了这些资源能够被回收,不影响其他代码的使用。所以说一个操作系统只有线程没有进程也是可以的,只是这样的系统会经常崩溃而已,操作系统刚开始发展的时候和这种情形很像。
所以:线程和并发有关系,进程和隔离有关系。线程基本是为了代码并发执行引入的概念,因为要分配cpu时间片,暂停后再恢复要能够继续和没暂停一样继续执行;进程相当于一堆线程加上线程执行过程中申请的资源,一旦挂了,这些资源都要能回收,不影响其他程序。

作者:风平浪静如码
链接:https://juejin.im/post/5e5cb893f265da570d736388
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

损失函数

损失函数(loss function)是用来估量模型的预测值f(x)与真实值Y的不一致程度,它是一个非负实值函数,通常使用L(Y, f(x))来表示,损失函数越小,模型的鲁棒性就越好。

损失函数分类

损失函数一般分为分类和回归两类
回归会预测给出一个数值结果而分类则会给出一个标签。
损失函数分类

常用回归损失函数

  1. 均方误差MSE, 平方损失 – L2损失
    是回归损失函数中最常用的误差,它是预测值与目标值之间差值的平方和
    公式: $ MSE = \frac{\sum_{i=1}^{n}(y_i-y_i^p)^2}{n} $
    特点: 平方损失函数是光滑的,可以用梯度下降法求解,但是,当预测值和真实值差异较大时,它的惩罚力度较大,因此对异常点较为敏感。

  2. 平均绝对误差 – L1损失
    常用的回归损失函数,它是目标值与预测值之差绝对值的和,表示了预测值的平均误差幅度,而不需要考虑误差的方向
    公式: $ MAE = \frac{|y_i - y_i^p|}{n} $
    特点: 绝对损失函数对异常点不那么敏感,其鲁棒性比平方损失更强一些,但是它在f = y 处不可导.

  3. Huber损失 – 平滑平均绝对误差
    相比于平方损失来说对于异常值不敏感,但它同样保持了可微的特性。它基于绝对误差但在误差很小的时候变成了平方误差。
    公式: Huber
    特点: Huber损失函数在 ∣f−y∣较小时为平方损失,在较大时为线性损失,且处处可导,对异常点鲁棒性较好

  4. log-cosh损失函数
    公式: $ L(f,y) = \log(cosh(f-y)) $ $ cosh(x) = (e^x + e^{-x})/2 $
    特点: log-cosh损失函数比均方损失函数更加光滑,具有huber损失函数的所有优点,且二阶可导。因此可以使用牛顿法来优化计算,但是在误差很大情况下,一阶梯度和Hessian会变成定值,导致牛顿法失效。

  5. 分位数损失函数
    公式: $ L(f,y) = \sum_{y_i<f_i}(1-\gamma)|y_i - f_i| + \sum_{y_i \beq f_i} \gamma|y_i - f_i| $
    特点: 预测的是目标的取值范围而不是值, $ \gamma $是所需的分位数,其值介于0-1之间

常用分类损失函数

  1. 0-1损失函数
    预测值和目标值不相等为1,否则为0
    公式: 0-1损失函数
    特点: 0-1损失函数可以直观的刻画分类的错误率,但是因为其非凸,非光滑的特点,使得算法很难对其进行直接优化

  2. Hinge损失函数(SVM)
    公式: $ L(f,y) = max(0, 1 - fy) $
    特点: Hinge损失函数是0-1损失函数的一个代理损失函数,也是其紧上界,当 fy≥0,fy≥0 时,不对模型做惩罚。因为在fy = 1处不可导, 因此不能用梯度下降算法对其优化,只能用次梯度下降法

  3. 对数损失函数(logarithmic loss)LR
    样本预测值和实际值的误差符合高斯分布,使用极大似然估计的方法,取对数得到损失函数
    经典的对数损失函数包括entropy和softmax,一般在做分类问题的时候使用
    公式: $ L(Y, P(Y|X)) = -\logP(Y|X) $
    特点:Logistic损失函数是0-1损失函数的另一个代理损失函数,它也是0-1损失函数的凸上界,且该函数处处光滑。但是该损失函数对所有样本点都惩罚,因此对异常值更加敏感

  4. 交叉商损失函数Cross-Entropy
    公式: $ L(f,y) = -log_2(\frac{1+fy}{2}) $
    特点: 交叉熵损失函数也是0-1损失函数的光滑凸上界

  5. 指数损失函数(AdaBoost)
    公式: $ L(f,y) = e^{-fy}$
    特点: 指数损失函数是AdaBoost里使用的损失函数,同样地,它对异常点较为敏感,鲁棒性不够

损失函数的选择

损失函数的选取依赖于参数的数量、异常值、机器学习算法、梯度下降的效率、导数求取的难易和预测的置信度等若干方面。

tf.keras.losses.BinaryCrossentropy(from_logits = True)
其中,当模型最后一层没有经过激活函数时from_logits设置为True,否则为False。
因为logits表示网络的直接输出 。如果网络输出的结果经过了sigmoid或者softmax的概率化,那么from_logits=False就表示把已经概率化了的输出,重新映射回原值。如果网络输出的结果没经过概率化,则from_logits=True,表示不进行任何操作。

激活函数的概念

神经网络中的每个神经元节点接受上一层神经元的输出值作为本神经元的输入值,并将输入值传递给下一层,输入层神经元节点会将输入属性值直接传递给下一层(隐层或输出层)。在多层神经网络中,上层节点的输出和下层节点的输入之间具有一个函数关系,这个函数称为激活函数(又称激励函数)。

激活函数的作用

不使用激活函数的话,神经网络的每层都只是做线性变换,多层输入叠加后也还是线性变换。因为线性模型的表达能力通常不够,所以这时候就体现了激活函数的作用了,激活函数可以引入非线性因素。

激活函数分类

饱和激活函数和非饱和激活函数
激活函数分类

饱和定义

假设 $ h(x) $ 是一个激活函数

  1. 若 $ \lim_{n\rightarrow+\infty} h^{\prime}(x) = 0 $ 称为右饱和
  2. 若 $ \lim_{n\rightarrow-\infty} h^{\prime}(x) = 0 $ 称为左饱和
  3. 当一个函数既满足左饱和又满足右饱称之为饱和函数

饱和激活函数(Saturated)

Sigmoid和tanh是饱和激活函数

非饱和激活函数(Non-Saturated)

ReLU(修正线性单元)及其变体则是“非饱和激活函数

非饱和激活函数优势

  1. 能解决所谓的“梯度消失”问题。
  2. 它能加快收敛速度。

常用激活函数

  1. Sigmoid
    公式为: $ f(x) = \frac{1}{1 + e^{-x}} $
    函数图像: Sigmoid
    导函数图像: Sigmoid导函数
    特点:

    1. sigmoid函数饱和使梯度消失。我们从导函数图像中可以看出sigmoid的导数都是小于0.25的,那么在进行反向传播的时候,梯度相乘结果会慢慢的趋近于0。这样,几乎就没有梯度信号通过神经元传递到前面层的梯度更新中,因此这时前面层的权值几乎没有更新,这就叫梯度消失。除此之外,为了防止饱和,必须对于权重矩阵的初始化特别留意。如果初始化权重过大,可能很多神经元得到一个比较小的梯度,致使神经元不能很好的更新权重提前饱和,神经网络就几乎不学习。
    2. sigmoid函数输出不是“零为中心”(zero-centered)。一个多层的sigmoid神经网络,如果你的输入x都是正数,那么在反向传播中w的梯度传播到网络的某一处时,权值的变化是要么全正要么全负。
    3. 指数函数的计算是比较消耗计算资源的.
  2. tanh
    tanh函数跟sigmoid还是很像的,实际上,tanh是sigmoid的变形,

    公式为: $ tanh(x) = \frac{1-e^{-2x}}{1+e^{-2x}} = 2sigmoid(2x)-1$
    函数图像: tanh函数图像
    优点:

    1. tanh解决了sigmoid的输出非“零为中心”的问题
      缺点:
    2. 依然有sigmoid函数过饱和的问题
    3. 指数函数的计算是比较消耗计算资源的.
  3. ReLU修正线性单元
    公式为: $ f(x) = max(0, x) $
    函数图像: Relu
    优点:

    1. ReLU解决了梯度消失的问题,至少x在正区间内,神经元不会饱和
    2. 由于ReLU线性、非饱和的形式,在SGD中能够快速收敛
    3. 算速度要快很多。ReLU函数只有线性关系,不需要指数计算,不管在前向传播还是反向传播,计算速度都比sigmoid和tanh快
      缺点:
    4. ReLU的输出不是“零为中心”
    5. 随着训练的进行,可能会出现神经元死亡,权重无法更新的情况。这种神经元的死亡是不可逆转的死亡
  4. Leaky ReLU
    Leaky ReLU是给所有负值赋予一个非零的斜率。
    公式为: Leaky ReLU
    函数图像: Leaky ReLU

    优点:

    1. 神经元不会出现死亡
    2. 神经元不会饱和
    3. 在SGD收敛很快
    4. 计算速度快
      缺点:
    5. 参数 $ \alpha $ 需要先验知识,人工赋值
  5. RReLU 随机修正线性单元

    公式为: RReLU
    函数图像: RReLU函数图像
    特点:

    1. 在训练过程中,α是从一个高斯分布中随机出来的值,然后再在测试过程中进行修正。在测试阶段,把训练过程中所有的取个平均值。
    2. 数学形式与PReLU类似,但RReLU是一种非确定性激活函数,其参数是随机的
  6. ELU 指数线性单元
    它试图将激活函数的输出平均值接近零,从而加快学习速度。同时,它还能通过正值的标识来避免梯度消失的问题。
    公式为: ELU
    函数图像为: ELU函数图像

    优点:

    1. ELU包含了ReLU的所有优点。
    2. 神经元不会出现死亡的情况。
    3. ELU激活函数的输出均值是接近于零的。
      缺点:
    4. 指数计算效率低

如何选择激活函数

在实践过程中更多还是需要结合实际情况,考虑不同激活函数的优缺点综合使用。

  1. 通常来说,不能把各种激活函数串起来在一个网络中使用。
  2. 如果使用ReLU,那么一定要小心设置学习率(learning rate),并且要注意不要让网络中出现很多死亡神经元。如果死亡神经元过多的问题不好解决,可以试试Leaky ReLU、PReLU、或者Maxout。
  3. 尽量不要使用sigmoid激活函数,可以试试tanh,不过感觉tanh的效果会比不上ReLU和Maxout。

keras.layers.normalization.BatchNormalization()

该层在每个batch上将前一层的激活值重新规范化,即使得其输出数据的均值接近0,其标准差接近1

BN层的作用
(1)加速收敛
(2)控制过拟合,可以少用或不用Dropout和正则
(3)降低网络对初始化权重不敏感
(4)允许使用较大的学习率

机器学习领域有个很重要的假设:IID独立同分布假设,就是假设训练数据和测试数据是满足相同分布的,这是通过训练数据获得的模型能够在测试集获得好的效果的一个基本保障。BatchNorm就是在深度神经网络训练过程中使得每一层神经网络的输入保持相同分布的。

BN不是凭空拍脑袋拍出来的好点子,它是有启发来源的:之前的研究表明如果在图像处理中对输入图像进行白化(Whiten)操作的话——所谓白化,就是对输入数据分布变换到0均值,单位方差的正态分布——那么神经网络会较快收敛,

TF2三大功能

  1. 加速计算
  2. 自动梯度
  3. 常用神经网络接口

[tf.keras 内置数据集] (https://keras.io/zh/datasets/)

概念理解

  1. keras和tf.keras

常用API说明

  1. tf.data.Dataset.from_tensor_slices
  2. keras.layers.normalization.BatchNormalization
  3. tf.ones_like 和 tf.zeros_like

实战

  • 线性模型实战
  1. fashion-mnist分类实战
  2. GAN手写数字生成实战