深度学习食用指南

Posted Debroon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度学习食用指南相关的知识,希望对你有一定的参考价值。

深度学习食用指南

 

什么是神经网络

你看一只苍蝇的大脑只有10万个神经元,能耗那么低,但是它能看、能飞、能寻找食物,还能繁殖。而一台的超级计算机,消耗极大的能量,有庞大的体积,可是它的功能为什么还不如一只苍蝇?

这是因为苍蝇的大脑是高度专业化的,进化使得苍蝇的大脑只具备这些特定的功能,而我们的计算机是通用的,你可以对它进行各种编程,它理论上可以干任何事情。

这个关键在于,大脑的识别能力,不是靠临时弄一些规则临时编程。大脑的每一个功能都是专门的神经网络长出来的,那计算机能不能效法大脑呢?

这就给计算机科学家们带来了一些暗示:

  • 大脑是一个强大的模式识别器。人脑非常善于在一个混乱的场景之中识别出你想要的那个东西。比如你能从满大街的人中,一眼就认出你熟悉的人。
  • 大脑的识别功能可以通过训练提高。
  • 大脑不管是练习还是使用识别能力,都不是按照各种逻辑和规则进行的。我们识别一个人脸,并不是跟一些抽象的规则进行比对。我们不是通过测量这个人两眼之间的距离来识别这个人。我们一眼看过去,就知道他是谁了。
  • 大脑是由神经元组成的。我们大脑里有数百亿个神经元,大脑计算不是基于明确规则的计算,而是基于神经元的计算。

这就是神经网络计算做的事情,而后计算机科学家们就模拟出了一个神经网络。

人类大脑神经元细胞的树突接收来自外部的多个强度不同的刺激,并在神经元细胞体内进行处理,将其转化为一个输出结果。如下图所示。

人工神经元也有相似的工作原理。如下图所示。


上面的x是神经元的输入,相当于树突接收的多个外部刺激。w是每个输入对应的权重,它影响着每个输入x的刺激强度。

假设周末即将到来,你听说在你的城市将会有一个音乐节。我们要预测你是否会决定去参加。音乐节离地铁挺远,而且你女朋友想让你陪游。

首先确定影响结果的几个要素,像天气(天气好不好)、性格(内向或者外向)、兴趣(对音乐的喜欢),也就是说有3个因素会影响你的决定,这3个因素就可以看作是3个输入特征。那你到底会不会去呢?你的个人喜好——你对上面3个因素的重视程度——会影响你的决定,这3个重视程度就是3个权重。

如果你觉得地铁远近无所谓,而且你很喜欢蓝天白云,那么我们将预测你会去音乐节。这个预测过程可以用我们的公式来表示。

我们假设结果 z > 0 z>0 z>0 的话就表示会去,小于 0 0 0表示不去。又设偏移值 b = − 5 b = -5 b=5

又设3个特征 ( x 1 , x 2 , x 3 ) (x1,x2,x3) (x1,x2,x3) ( 0 , 0 , 1 ) (0,0,1) (0,0,1),最后一个是 1 1 1,它代表了好天气。

又设三个权重 ( w 1 , w 2 , w 3 ) (w1,w2,w3) (w1,w2,w3) ( 2 , 2 , 7 ) (2,2,7) (2,2,7),最后一个是 7 7 7表示你很喜欢好天气。

那么就有 z = ( x 1 ∗ w 1 + x 2 ∗ w 2 + x 3 ∗ w 3 ) + b = ( 0 ∗ 2 + 0 ∗ 2 + 1 ∗ 7 ) + ( − 5 ) = 2 z = (x1 * w1 + x2 * w2 + x3 * w3) + b = (0 * 2 + 0 * 2 + 1 * 7) + (-5) = 2 z=(x1w1+x2w2+x3w3)+b=(02+02+17)+(5)=2

预测结果 z = 2 z=2 z=2 2 > 0 2>0 2>0,所以预测你会去音乐节。

如果你本质就是宅,并且对其它两个因素并不在意,那么我们预测你将不会去音乐节。

这同样可以用我们的公式来表示。设三个权重 ( w 1 , w 2 , w 3 ) (w1,w2,w3) (w1,w2,w3) ( 2 , 7 , 2 ) (2,7,2) (2,7,2),w2是7表示你就是特别喜欢呆在家里。

那么就有 z = ( x 1 ∗ w 1 + x 2 ∗ w 2 + x 3 ∗ w 3 ) + b = ( 0 ∗ 2 + 0 ∗ 7 + 1 ∗ 2 ) + ( − 5 ) = − 3 z = (x1 * w1 + x2 * w2 + x3 * w3) + b = (0 * 2 + 0 * 7 + 1 * 2) + (-5) = -3 z=(x1w1+x2w2+x3w3)+b=(02+07+12)+(5)=3

预测结果 z = − 3 z=-3 z=3 − 3 < 0 -3<0 3<0,所以预测你不会去,会呆在家里。

神经元的内部参数,包括权重w和偏移值b,都是可调的(开始时我们会随机初始化)。用数据训练神经网络的过程,就是调整更新各个神经元的内部参数的过程。神经网络的结构在训练中不变,是其中神经元的参数决定了神经网络的功能。

反复学习是刺激神经元,相当于加大权重的确定程度(不是加大权重的大小)。一开始神经元给这个输入数据的权重是0.9,但这是一个随机的分配,有很大的不确定性。随着训练的加深,神经网络越来越相信这个权重应该是0.11,参数稳定在这里。数值,增大或者减小了不重要,关建是确定性大大增加了。

对比到人,这就好比篮球,训练的目的不是让投篮的用力越来越大,而是越来越准确。

这的确相当于大脑神经元之间的连接越来越稳固!有句话叫 fire together, wire together —— 经常在一起激发的两个神经元会“长”在一起,它们之间的电信号会更强。但是请注意,电信号强并不对应参数权重的数值大,而是对应参数更确定。这就好像发电报汇款,我收到一个很强很强的汇款信号,但这只是一笔很小的钱 —— 信号强烈只是确保钱数不会错。

本质上,神经元做的事情就是按照自己的权重参数把输入值相加,再加入偏移值,形成一个输出值。如果输出值大于某个阈值,我们就说这个神经元被“激发”了。当然,人脑的神经元不一定是这么工作的,但是这个模型在计算中很好用。

这就是神经元的基本原理。真实应用中的神经元会在计算过程中加入非线性函数的处理,并且确保输出值都在 0 和 1 之间,这个非线性函数被称为激活函数,记录在下文。

这是单个神经元的计算,而在我们的大脑中,有数十亿个称为神经元的细胞,它们连接成了一个神经网络。


人工神经网络正是模仿了上面的网络结构。下面是一个人工神经网络的构造图。每一个圆代表着一个神经元,他们连接起来构成了一个网络。


它从左到右分为三层,每一个圆点代表一个神经元。

  • 第一层是“输入层”,代表输入的数据。
  • 第二层叫“隐藏层”,所谓深度学习就是中间不只有一个隐藏层。
  • 第三层是“输出层”,得到一个输出值。

数据输入进来,经过隐藏层各个神经元的一番处理,再把信号传递给输出层,输出层神经元再处理一番,最后作出判断。

对于多神经元网络,拆分看就是一个个单独的神经元,神经元网络的计算就是重复单神经元的计算。

从下面这张图,你可以看到它的运行过程。

在这里插入图片描述

神经网络预测的准确与否,由权重w和偏移值b决定,所以神经网络学习的目的就是找到合适的w和b。

任何一个机器学习的过程,其实都是不断地调整数学模型参数的过程,直到参数收敛到最佳点。

每一次调整被称为是一次迭代,调整的幅度被称为迭代的步长。一开始的时候,迭代的步长要比较大,这样能够很快地确定大致范围,效率比较高。

但是,如果总是把步长设计得很大,那么最后可能会找不到最佳的参数,因为要么走过头了,要么没有走到。因此,机器学习到最后需要缩小步长,进行精调,以保证最后收敛到最佳点。

世界上每年有很多机器学习方面的论文,都是围绕提高学习效率展开的,而其中的核心其实就是怎样用最少次迭代,完成模型的训练——当然,任何好的机器学习算法都不是事先人为设定步长,而是在学习的过程中,自动找到合适的步长。

我们可以通过一种叫梯度下降的搜索方法,TA会一步步的改变w和b的值,新的w和b会使损失函数的输出结果更小,即一步步让预测更加精确。
 


损失函数:怎么验证神经网络的预测结果

损失函数用来评价模型的预测值和真实值不一样的程度,损失函数越好,通常模型的性能越好。

啥意思呢?我们人类学习同理,如果一个人一直不停的学,但是不验证自己的学习成果,那么有可能学的方向或者学习方法是错误的,不停的学但结果都白学了。要验证学习成果,就要判断预测结果是否准确,损失函数就是做这个的。

不同的模型用的损失函数一般也不一样,所以损失函数有几种, J ( ) 、 L ( ) J()、L() J()L()
 


激活函数:神经网络的智商怎么蹭的一下就涨了呢

神经网络其实就是线性函数,函数就是一条直线,能处理的问题也只是线性函数可以处理的问题。

激活函数是非线性函数,不同的激活函数的样子不同,可能是曲线等等,而后就可以让神经网络处理各种问题了。


但这个激活函数用的较少,一般用改进的 tanh。


tanh 图像和 sigmoid 的形状是一样的,只不过整体往下移了一点。

sigmoid 输出值是在 [ 0 , 1 ] [0,1] [0,1],平均值是0.5,tanh 输出值是在 [ − 1 , 1 ] [-1,1] [1,1],平均值是0。

改进就在这里,将靠近0的输出值传给下层神经网元,就会更有效。

俩者都有一个不足,数据大时,神经网络学习速度就很慢。

学习速度和偏导数大小相关,偏导数就是斜率(变化比例),斜率(变化比例)越大偏导数越大,学习速度越快。

通过观察俩者的图像发现,当输入值越来越大时,曲线的斜率(变化比例)是越来越小的。

为了解决这个问题,后来创造了relu。

relu 图像:

  • 在输入为正时,斜率(变化比例)很大。
  • 在输入为负时,就会输出 0,神经元就不会被激活 — 说明同一时间里,只有部分神经元会被激活,从而使得网络很稀疏,进而计算更高效,但没有斜率(变化比例)。

为了解决没有斜率(变化比例)的问题,又创造了一种激活函数:leaky relu。

leaky relu 的优点将 0 的梯度去掉,换成一个非0的梯度,比如0.1等,这样把0梯度变成一个很小不为0的梯度。

sigmoid 类的激活函数,只可以处理二元分类问题,神经网络只能判断是或否。

softmax 可以让神经网络的预测更加丰富,从二元判断到多元判断。

比如,之前只能用来判断图中有木有猫,现在可以同时判断出猫、狗、鸡。

常用的激活函数:

  • sigmoid:特别适用于,二元分类的输出层,其他方面不如tanh
  • tanh:sigmoid改进
  • relu:首选,用的最多,但只在隐藏层使用
  • leaky relu:relu改进
  • softmax:N元分类的输出层,输出层神经元要有N个

 


如何计算神经网络的前向传播:计算权重参数把输入值相加,再加入偏移值,形成一个输出值

 


如何计算神经网络的反向传播:先计算第N层的变化比例,再计算第N-1层的,反向往前推

激活函数的偏导数

 


向量化:人工智能编程和传统编程不一样的地方

假设您已经有了Python基础。

人工智能编程和传统编程不一样的地方,在于训练一个智能模型需要非常多的数据,计算量很大,需要很长的时间,所以我们会向量化,来提高计算速度。

“向量化”(简化)是重写一个循环的过程,这样它可以不处理数组N次的单个元素,而是同时处理(比方说)数组的4个元素N/4次。

传统编程:

for(int i=0; i<10000; i++)
	a[i] = 1

向量化:

for(int i=0; i<10000; i++){
	a[i] = 1; a[i+1] = 1; a[i+2] = 1; a[i+3]=1;
	i = i + 4;
}

判断和赋值就减少了 3 4 \\frac{3}{4} 43

因为现在的CPU都有“向量”或“SIMD”指令集,它们同时对两个、四个或多个数据进行相同的操作。如果使用 for 循环,那一条指令的for循环里并没有使用并行计算,也就没有充分利用计算机的资源。

举个例子, ∑ i = 1 3 a i ∗ b i \\sum\\limits_{i=1}^3 a_{i} * b_{i} i=13aibi

传统编程:

a = b = [1, 2, 3]
ans = 0
for x in range(0, 3):
	ans = a[i] + b[i]

向量化:

import numpy as np
a = b = [1, 2, 3]
np.dot(a, b)
# dot函数是如何对矩阵进行运算,里面的代码是用C语言实现的,比Python自身实现的要快得多
# 如果是向量,返回的是两向量的点乘:A*B = A1*B1 + A2*B2 ··· +An*Bn(需要检查边界:俩个向量维度相等),结果是一个数
# 如果是矩阵,返回的是俩矩阵的乘积:矩阵乘法内容,(需要检查边界:乘号前的矩阵的列数要等于后面矩阵的行数),结果是一个矩阵

扩展知识:向量矩阵

基本上,我们每个算法里都会想怎么向量化。

def sigma(x):
	return 1 / ( 1 + pow(e, x) )

z = a = y = dz = []
for i in range(1, m):      									# 遍历所有样本
	temp = 0
	for j in range(1, n):  									# 遍历样本里的输入特征
		temp += w[j] * x[i][j]
	
	z[i] = temp + b										    # 输出值z = 权重 + 偏移值
	a[i] = sigma (z[i])    									# 每一个神经元得出的z都需要通过激活函数变成激活值/预测值a
	J += -( y[i] * log(a[i]) + (1 - y[i]) * log(1 - a[i]) ) # 通过预测值和真实值构建一个损失函数J来计算损失
	dz[i] = a[i] - y[i]                                     # 
	for j in range(1, n):                                   
		dw[j] += x[i][j] * dz[i]
	db += dz[i]

# m是样本数量,除以m是求平均值
J = J / m, db = db / m 
for j in range(1, n):
	dw[j] = dw[j] / m

向量化后:

[牛刀小试:识别猫的项目]

[牛刀小试:构建浅层神经网络]

 


深层神经网络:信息技术的核心思想是分层,用分层解决复杂性

层次特性:有关于深度学习内部如何学习的猜想

核对矩阵维度:如何编程正确的程序

参数和超参数:神经网络调音师,要想悦耳如音乐,就得精准如数学

[牛刀小试:构建深层神经网络]

 


实战基础

配置数据集

欠拟合和过拟合

正则化

dropout

数据增强

梯度消失与梯度爆炸

如何判断网格中有bug

H5文件

[牛刀小试:参数初始化]

[牛刀小试:正则化]

[牛刀小试:梯度检验]

 


优化算法

mini-batch

指数平均加权

动量梯度下降

RMSprop

Adam优化算法

学习率衰减

局部最优

[牛刀小试:mini-batch梯度下降]

[牛刀小试:动量梯度下降]

[牛刀小试:Adam]

[牛刀小试:对比不同的优化算法]

 


调试神经网络

为调参选择采样标尺

各种调参经验

调参模式和工具

规范化隐藏层的输入

BN的好处

softmax

[牛刀小试:Tensorflow实战]

 


智能视觉

[牛刀小试:自动驾驶之车辆检测]

[牛刀小试:风格转换]

[牛刀小试:人脸识别]

[牛刀小试:AI换脸]

 


语音识别

[牛刀小试:智能写作]

[牛刀小试:智能音乐]

[牛刀小试:智能作曲]

[牛刀小试:唤醒词检测]

 


自然语言处理

[牛刀小试:类比推理]

[牛刀小试:智能表情]

[牛刀小试:机器翻译]

以上是关于深度学习食用指南的主要内容,如果未能解决你的问题,请参考以下文章

智能视觉食用指南

《动手学深度学习》(PyTorch版)

给JAVA转行初学者的eclipse最佳食用指南

虚拟机与 NOI Linux 食用指南

分享《TensorFlow学习指南:深度学习系统构建详解》英文PDF+源代码+部分中文PDF

语音识别食用指南