首页 > 其他分享 >深度 学习

深度 学习

时间:2024-07-24 21:41:59浏览次数:8  
标签:函数 梯度 学习 神经网络 参数 深度 数据

深度学习入门

数据是学习的核心

神经网络借鉴人类脑神经的工作原理, 但是对于“神经网络就是模仿人脑神经”这样的言论我们是非常抵触的。

引入:

深度学习是机器学习的一个子领域,而机器学习的研究目标是让人工智能具备学习的能力。深度学习,机器学习,人工智能字里行间透漏着理性和高大尚的味道。(对于这种看着高大尚感觉距离现实很远的东西一般下一句都是“其实就在身边”吧)其实,图像识别(人脸识别技术),手写识别(手机输入法的手写输入)等技术中都有深度学习的贡献。

人工智能诞生伊始,其所谓的“智能”体现在它可以轻松准确地解决一些对于人类而言非常困难那的问题,但是这里所说的问题必须是”公式化““套路化”“数学化”的,在这些条件的限制下,人工智能的优势相比于人力也就没有那么突出了。并且,当时的人工智能无法完成一些对于人类而言非常简单的非形式化问题,它没有五感,只能通过输入获得外界信息。他就像人的脑子,但没有五感他只是不完整的脑子。

笛卡尔说:“一切问题都是数学问题。”

如果是在其他学科,那可能是有歧义的,但是对于计算机这个由01语言构成的物体上,若要”相信“人工智能可以解决一切问题,那我们首先就要“相信“笛卡尔的这句话,将我们想要解决的现实问题转化为数学问题,在此期间,实话说,相比于说我们在研究数学,不如说我们在研究一门名为”数学“的外语,我们要给计算机当翻译。

我们从小学到现在,对学习应该也有了一定的认识,学习是进步的唯一途径(直到现在应该还没有罐装知识这种东西)!学习的途径很广泛,我们通过书本获得知识这叫做学习,我们通过反思自己的过去,他人的经理,获得道理和经验这也叫做学习,我们模仿榜样的行为来提升自己也叫学习。如果要让计算机学习解决对人而言很简单的问题比如说获得感知的能力,不如先模仿人。

在接下来的介绍中,我们以视觉为例。

大脑上没有传感器,人工智能也无法单单依靠一颗大脑感知世界,他需要接收装置比如说实现视网膜功能的感光底片。

感光底片接受光信息转为数学参数,由线路传导至计算机进行参数加工,分析,处理成像。

视网膜接受光信息,转为电信号,电信号经神经传到至大脑,在大脑中进行分析处理成像。

(甚至在解决某些问题时计算机有更高的潜力,比如一只四足兽(假设是猫),人判断的判断过程是在上述过程后加一步判断,而计算机可以省略成像这一步,直接通过传入的数据进行判断。但从这一点来看,人工智能在图像识别方面有着得天独厚的优势)

在这个过程中,就完成了对图像的数学化过程,照片以数学数据的形式被储存进了计算中,照片作为一个大的整体是由更小的组成单位像素决定的,也就是将一个照片分成数以万计的的像素点,而根据像素点的参数(每个像素的配色)以及相邻参数,或者某个区域的像素的组合,可以对图像进行初步判断。

而其他感官也可以以此类推,听觉所听到的声音参数可以是振幅,音调,音色。嗅觉影响因素是其中的化学物质。触觉的参数可以是一定范围内的压力分配……

这样,对自然世界的数学化就完成了,但即便是完成了问题的数学化,在人工智能的判断过程中,仍然很难离开人的作用,也就是说,即便计算机完成了图片数据的记录,分析,但是在判断的过程中,人需要标定什么样的数据结果代表什么样的判断结果,人需要来划定界限。

思考一下在人类的婴儿时期的教学,当我们经过多次(可能在10-100次不等)对着实物告诉孩子这是一只猫,当孩子以后遇到猫时也就知道这是一只猫了,尽管以后遇到的这只猫与之前遇到的猫不尽相同,甚至是不曾出现的特点,仍然能够做出比较准确的判断,这是人类的学习存在的学习行为。

人工智能当然也要掌握“学习”这门本领,毕竟我们不可能天天像看孩子一样看一样工具,因为这样的需求,机器学习应运而生。机器学习是实现人工智能的途径。

人工智能与生物学:

日本北海道大学的粘液霉菌实验(称之为生物计算机)。粘液霉菌是没有大脑神经的单细胞生物,实验中,将粘液霉菌分散放置在迷宫中,他们能够迅速找到彼此融合成大粘液霉菌团并迅速找到通向迷宫出口的最短路径。对于迅速的原因----对于细胞团成员走过的路径他会放弃搜索----遍历的特性。

利用粘液霉菌的避光性,研究人员在几个东京地铁站的重要站口防止食物,散步的粘液霉菌在26小时间遍历了整个东京地铁路线,基本没有遗漏。通过对粘液霉菌的定位,完成了东京地铁路线的记录,事实上,人为测绘东京地铁路线经历了70+年。

概念梳理:

1.感知机:

感知机是二分类的线性分类模型,感知机的目的是求出将输入数据划分为两类的分离超平面。

他需要合适的,符合预期的权重才能够正常工作。

感知机是构成神经网络的最小构成单位。可以理解为神经元的仿生结构。

2.神经网络:

历史:

1958年,计算科学家Rosenblatt提出了由两层神经元组成的神经网络。他给它起了一个名字--“感知器”(Perceptron)(有的文献翻译成“感知机”,下文统一用“感知器”来指代)。

  感知器是当时首个可以学习的人工神经网络。Rosenblatt现场演示了其学习识别简单图像的过程,在当时的社会引起了轰动。

  人们认为已经发现了智能的奥秘,许多学者和科研机构纷纷投入到神经网络的研究中。美国军方大力资助了神经网络的研究,并认为神经网络比“原子弹工程”更重要。这段时间直到1969年才结束,这个时期可以看作神经网络的第一次高潮。

模拟人类神经元的工作机理。由输入,输出和计算功能组成,分别照应了人类神经元中树突,轴突,细胞核的功能。输入接受信号由计算做出反应并将反应信号输出。--摘抄

在形式上,神经网络是节点与连接构成的网络,每个连接上存在一个“权重”,将输入的信号计算加权后输出给下一个神经元便完成了一次神经传递。

神经网络可分为单层神经网络(即为感知机),和多层神经网络,层数=输入层+隐藏层+输出层-1在意义上感知机层数与实际与权重有关,也有些人会层数=输入层+隐藏层+输出层与层的数目有关,本书使用的是前者。感知机没有隐藏层,只有单次权重。

3.权重

权重是神经网络中最重要的东西。权重的合适程度直接决定了神经网络是否是优良的。训练一个神经网络就是使其权重达到最佳的过程。

在权重作用的过程时,即节点与节点间传输信号的过程中偏值也起了一定的作用,偏值会改变神经元被启动的难易程度。

神经元能否被启动取决于传入的信号是否达到峰值,偏值影响峰值大小。

4.计算

计算在神经元中进行,神经元具备存储和计算的功能。将输入(x)与输出(y)挂钩的函数(f(x))我们称之为激活函数,激活函数代表的神经元中枢细胞体对输入的数据进行反应的过程。

正常神经的反应过程是:输入的信号传至细胞体,细胞体对信号进行判断后输出新的信号并输出。

5.激活函数

激活函数旨在帮助神经网络学习数据中的复杂模式。在神经元中,输入的input经过一系列加权求和后作用 的另一个函数

----摘抄[深度学习笔记:如何理解激活函数?(附常用激活函数) - 知乎 (zhihu.com)]

激活函数可以适用在复杂环境中,人类神经元的传递过程是复杂的,倘若只用权重来改变输入和输出,那么无论电脑神经网络在形式上(隐藏层数目多少)有多么复杂,其最后的结果仍会是线性相加的结果,其复杂度难以达到人类神经网络的复杂程度。

插入片段:文本内容记录:

回归问题和分类问题。

不管是分类,还是回归,其本质是一样的,都是对输入做出预测,并且都是监督学习。说白了,就是根据特征,分析输入的内容,判断它的类别(分类),或者预测其值(回归)。

两者的含义近似对立,分类问题即将事物归类,就像把人按照性别分为男女,按照身高规定大于1.7米为高否则为低,其结果是离散的。而回归问题则是根据已有数据进行预测

两者都可以用来判断:对于身高,分类问题的判断会根据标准给出这个人是否可以被分到高的一组,其输出的结果只能为是或否。而回归问题则是根据视觉感受判断这个人的身高,其输出的结果可以是连续的一串数字。

两者都可以用于预测:在天气预报中,预测天气,只能在晴,雨,阴,雪中选择,此为分类问题。而在预测气温时,通常给出的是一个区间,此为回归问题。

结果的离散和连续为结果特征的差别,其本质区别在于损失函数的形式不同

6.损失函数:

当大学生在宿舍中攀比谁的电脑性能更好时,如果我们只是说电脑的价格,电脑的硬件,不太清晰的人是无法听懂的,也不明白其中的价值,但如果使用类似某大师的跑分程序,我们可以获得直观的电脑评分,通过电脑的评分我们能够轻松选看出谁的电脑的性能更高。

损失函数在这里就起到了一个跑分的作用,不过损失函数的结果表明的是神经网络的恶劣程度,即损失函数的结果越大,神经网络的准确性越差。

损失函数表明的是神经网络返回预测值与真实值的差异程度。预测值与真实值之间的差异值被称为损失值

损失函数的工作原理:损失函数利用于训练神经网络的过程中。测试数据()被送入神经网络并且返回预测值,损失函数利用预测值和真实值求出损失值,之后神经网络根据损失函数的结果反向传播更新各个参数,使得后来的损失值减小,使得神经网络向真实靠拢,达到学习的效果。

将神经网络的准确率具象化为损失函数的结果,通过损失函数计算神经网络调整前后的结果来判定对神经网络的调整是否是进步的。同时,将神经网络进步这个抽象问题转化为损失函数缩小这个具体的数学问题,同时函数的性质也为如何提高神经网络的准确率提供了依据。

作为函数,损失函数可以通过求某一点的导数(具体来说是梯度)来了解该点的走势,然后以这个导数为指引,逐渐更新参数。

7.one-hot表示
y =  [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
t = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
# t是用one-hot表示的真实值,y是用softmax函数生成的预测值(概率值)。
# one-hot表示中只有正确选项标记为1错误选项标记为0
# 在10个数中,只有“2”数字是正确的(从0开始数)其概率是0.6也就是说该神经网络在
# <此次>测试中有0.6概率正确。
8.梯度法:

为了了解梯度,我们先了解导数以及导数在程序中的实现。

导数表明可以表明函数图形中某个点的变化趋势,包括变化方向(增大还是减小),导数大于0,则此处的函数值随着自变量的增大有增大的趋势;变化速率,导数的绝对值越大,则表明该点函数值的变化快。

如果要在程序中利用导数,了解导数的图形含义是必要的,因为程序中求导的方法就是利用的图形意义。

导数的图形意义:导数的值等于函数图像中以该点为切点的切线的斜率。

如果是直线,该点的切线斜率也就是直线斜率,曲线的斜率我们会利用微分的方法求得

      		f(x+Δx) - f(x)
k =  lim	---------------# 将x+Δx 和x两个函数点连线,当Δx趋向于0时,该
	Δx->0	       Δx		 连线近似趋向于点x处的切线。
	
	
上式为导数的图形理解
但是在深度学习中,我们一般使用下式


      		f(x+Δx) - f(x-Δx)
k =  lim	---------------
	Δx->0	       2*Δx		 
	

OIP-C

导数的程序实现:
def numerical_diff(f, x):
	h = 0.0001
	return (f(x+h) - f(x-h)) / 2h
	
在上面的解读中,我们提出要求h无限趋近于0,但是因为在程序中存在舍入误差的缘故(是指因省略小数的精细部分的数值(比如,小数点第8位以后的数值)而造成最终的计算结果上的误差)
即 h = 1e-50
   print(h)
   >>>0.0
   因为h数字极小导致最后结果变为0.0使得导数的结果与正确值相差甚远。
   同时,因为h并不能像理想的那羊无限接近于0,所以如果最后➗h的结果的误差也会变大,为了缩小误差,取x前后各一个h的距离的两个点所连成的直线的斜率近似表示为x处的切线的斜率。这种算法也成为中心差分。
9.批mini-batch(小批量处理):

批是一种处理数据的方式,用通过样本近似代替整体的方法缩小计算量。

批大小的选择必须合适,过小的数据量难题代表整体,过大的数据量又无法显著达到减小计算量的目的。

减小计算量的益处:

1.当有1000个测试数据时,如果直接把1000个数据投入神经网络中计算,可能会对计算机的配置提出更高的需求,其次即便配置过关,其运行速度也不一定能达到理想状态。但如果将1000个数据分成10组,每次只投入100个数据,其对电脑的配置要求更低,同时,通过矩阵的并行性来缩短计算的时间,也可以使用多线程的方法来缩短计算时间(同时进行多个批次的处理,占用不同的进程,所以时间线上不冲突)。(当然,如果你只有10个小数据,那么再分成10个1份明显有些画蛇添足,所以要考虑每批的大小,和数据总量的大小问题)

2.如果数据的量级过大,比如上百万,上千万甚至是上亿的程度,我们也可以用分批的方法,随机选择一部分数据作为样本数据,用这部分样本数据作为测试数据进行操作。即将测试数据分批,但是只选取其中几批进行操作。

10.参数

参数包括:

​ 模型参数:

​ 从数据中学习和估计得到。

​ 超参数:

​ 人为设定的参数

超参数的设定很大程度上会影响神经网络学习的结果。

常用激活函数:

恒等函数:将输入的值原封不动的输出

阶跃函数:

# 类比人类神经元,可以理解为只有当传入神经元的信号强度高于阙值才会使细胞体做出相应的反应。

而在阶跃函数中,阶跃代表这里输出的结果是具有跳跃性的,于分类问题性质类似。

--f(x) = 0   x <= 0

--f(x) = 1   x > 0

Sigmoid(Logistic)函数:

# f(x) = 1/1+exp(-x)
# exp(-x)表达的是e的-x次(e**-x)
# 不难看出这个激活函数的返回值介于(0:1)之间

缺点:将输出的结果定于0到1之间,实现了神经元输出结果的归一化。

这个梯度平滑,且函数可微分,前者能够避免了输出值的大幅度变化并利于后续神经网络的学习,后者是梯度下降法的基础。

不足:

其函数图形呈现”s“形,两端趋向于水平,即两端的导数结果极小,此处在神经网络学习过程中,权重可能出现不更新的结果,同时与之相连的神经元的更新速度也会被减慢。

计算成本高,因为此处使用了exp。

不以0为中心。

20191015192015699

Tanh(双曲正切函数):

f(x) = 2/(1+exp(-2*x)) - 1

Tanh(x) = 2*Sigmoid(2x) -1

这个函数与sigmoid函数的一些区别

首先,该函数的输出结果介于(-1,1)之间,并以0为中心。

但依然保留了Sigmoid函数两端的导数偏向0的问题(梯度消失问题)

Softmax函数:

>>> a = np.array([0.3, 2.9, 4.0])
>>>
>>> exp_a = np.exp(a) # 指数函数
>>> print(exp_a)
[  1.34985881  18.17414537  54.59815003]
>>>
>>> sum_exp_a = np.sum(exp_a) # 指数函数的和
>>> print(sum_exp_a)
>>> 74.1221542102
>>> y = exp_a / sum_exp_a
>>> print(y)
"""
		e**ak
yk =  --------   分母代表所有输入数据经此括号内运算后求和
		sum(e**ai)  
		
将上一层的原始数据进行处理,返回一个介于0.1之间的数字,通常用来标识概率问题。

softmax处理数据的意义:
softmax将数据的原始输出转化为概率分布只能作为softmax的特征,而不能作为softmax的意义,意义应该表明其益处,也就是说,softmax的意义应该包括但不仅限于转化为概率分布所带来的便利性。防止有人将只看到softmax的概率归一化处理而忽略其他优点。

包括后续对交叉熵损失函数使用的遍历以及求导的裨益,视觉上的直观性。



"""

RELU函数:

-----f(x) = 0   x <= 0
-----f(x) = x   x  > 0

# 当 x 大于0时x不变,小于等于0变为0

优点:

一定程度上避免了Tanh和Sigmoid函数中梯度消失的问题。

计算速度更快。

被认为具有生物学合理性(Biological Plausibility),比如单侧抑制、宽兴奋边界(即兴奋程度可以非常高)

不足:

当输入为负数时失效

不已0为中心

【Dead ReLU问题】ReLU神经元在训练时比较容易“死亡”。在训练时,如果参数在一次不恰当的更新后,第一个隐藏层中的某个ReLU 神经元在所有的训练数据上都不能被激活,那么这个神经元自身参数的梯度永远都会是0,在以后的训练过程中永远不能被激活。这种现象称为死亡ReLU问题,并且也有可能会发生在其他隐藏层。

恒等函数:

f(x) = x
即为恒等。

细节:

softmax与sigmoid函数类似,其返回的结果都是介于0~1之间。其中softmax函数各项结果之和为1,因为这个特性,softmax又被称之为概率函数。在"softmax"这个单词中,“soft”意思是软的,“max”代表最大值。

softmax适合用于解决二分类问题。二分类是一种特殊的分类问题,其结果只有对错,好坏两种分类。在二分类问题中,softmax可以将概率转化为两种结果的概率。

当激活函数使用softmax函数时,损失函数常常使用交叉熵函数:

交叉熵函数常用于评估概率分布之间的差异,与softmax得出概率的性质相适应。

在神经网络输出的值非常大的时候,直接使用这些数值进行计算容易造成的数值溢出的结果,通过softmax归一化处理可以有效避免这种情况。

常用的损失函数:

--->y为预测值

--->t为真实值

--->k为总数

均方误差损失函数(MSE):

res = 0 
for i in range(k):
	res += (y-t)**2
return res/k
"""
形式与方差类似,不同的是y为预测值,t为真实值。
"""
	

交叉熵误差损失函数:

E = -t1 * ln( y1 ) - t2 * ln( y2 ) - …… - tk * ln ( yk )

神经网络的学习随机梯度下降法(SGD):

关于数据对于神经网络学习的重要性:

神经网络的特征就是可以从数据中学习,数据是神经网络学习的基础。

从数据中寻找答案、从数据中发现模式、根据数据讲故事……这些机器学习所做的事情,如果没有数据的话,就无从谈起。因此,数据是机器学习的核心。这种数据驱动的方法,也可以说脱离了过往以人为中心的方法。--《深度学习》

学习意味着神经网络可以根据已有数据对网络中的权重进行调整。

在第三章中,神经网络的学习体现在神经网络的函数的值从当前位置沿着梯度方向前进一定的距离的过程,这里我们用二维状态下的球过坡来描述这个问题。

其中学习率(lr-->learning rate)决定前进的速度。

step_num表示前进移动的次数

为了方便接下里的理解,我们引入一个现实问题:这里有一个小球放在斜坡上,受到重力和摩擦力影响,小球会在斜坡底部往复运动且其运动的高度会不断降低,假如时间无限延长下去,小球总会有停下的时刻。

我们将现实问题映射在神经网络的学习中:斜率的绝对值代表滚动的速度,斜率的正负代表滚动的方向,由learning rate(下文写作lr) 和 setp-num(sn代替),这里的时间是分段的lr代表每一段的时间有多少,而sn代表时间段数的多少,速度的大小只会在时间节点的开始发生变化,并且是瞬时变化,即每一段lr会存在一个不变的速度。因为时间的定义问题产生了一些与上文引述的现实问题不同的现象。比如:

1.在这里小球的运动状态会存在这样的几种情况。若lr的数值很小,如果sn也很小那么会出现小球还没怎么动,距离谷底仍然有较打距离时结束,学习的结果不佳。如果要通过增大sn的数值来提高学习的最终效果,以下面这个例子来介绍

# 一个简单的f(x) = x**2 的例子来介绍
a1 = 3
for i in range(sn):
    a1 -= lr * (a1 * 2)

    print(a1 , i)
# 不难知道,这个函数的谷底是当x = 0时,那么x = 0就是我们的目标了
# 条件1:如果lr = 0.02 , sn = 100,最后的结果大约是0.05
# 2:但如果设置lr为0.01 sn = 100 最后的结果是0.397     # 这里的结果省略了小数
# 如果lr = 0.01想到达到和条件1一样的效果需要200次数
# 如果lr = 0.005,则需要400次
# lr = 0.0025需要800次
# 这个简单的函数中,不完全统计可以推测lr每少一半,sn要提高一倍。

2.学习率过大,小球每一步的跨度过大,导致本该在谷底附近减速的小球没有减速而穿过谷底后又再次上升。此时,如果小球能够停在谷底附近,那么接下来小球仍会被约束在谷底附近且靠近谷底,但是另一种情况如果小球攀升的高度过大,这意味着小球从右坡向下走的速度仍会较大,如果在这段lr中小球再次经过了谷底并且超过了起始位置,这意味着小球很有可能会不断偏离谷底,而无法达到学习的目的。

QQ截图20240314145105

为了让小球最后停止的位置接近于谷底,从理论上讲,如果时间可以无限延长,那么学习率越小越好,但事实上却存在一个时间上的取舍问题。如果只是减小学习率,会减慢学习的效率,同时,如果学习提前停止了,那么学习的效果差-->需要提高学习次数,但是学习次数的提高同样伴随着学习时间的提高(计算成本与时间-->学习成本)。

同时,学习效果过强同样面临着过拟合的结果,特别是在训练数据中,如果损失函数结果过低,导致神经网络在特别适应训练数据的情况下排斥后来的测试数据,使得其对数据处理的泛化能力降低。在真实世界的数据还包括噪声和许多不确定性因素,过拟合的表现可能会导致神经网络对这些不确定因素的处理能力下降。

当然,神经网络中损失函数结果过低也不意味着一定会出现过拟合现象,这取决于算法的复杂度,训练策略和训练数据的特征。

误差反向传播:

反向传播算法是梯度下降算法在神经网络中的实现方式,由于深度学习网络是按层深入,层层嵌套,对深度学习网络目标函数计算梯度的时候,需要使用反向传播的方式由深到浅倒着计算以及更新参数。

随机梯度性下降法中:我们要求的是损失函数的结果对权重的微分,但是在多层神经网络中,权重的数量并不唯一,而我们需要的是损失函数结果对所有权重的微分,我们知道,神经网络以层划分,层与层之间是相互关联,这种情况下合理利用链式法则的特性大有裨益。

链式法则的应用:在神经网络的学习中,我们将神经网络看作是一个复合函数,其中每一层看作复合函数中的一个单独函数,利用下述导函数的特性可以关联每一权重对损失函数结果的影响。

# 导函数的特性:
# 对于f(x)而言
# f(x)对x的导数等于df(x)/dx,*此处的df(x) and dX都可以看作是一个独立的数值*
# 假如此时还有一个变量名为y.记f(x)的导数为z
       df(x)         df(x)      dy       df(x)     dy
z = ---------  =  -----------*------ = ------- * -------
	   dx	          dx        dy        dy       dx
也就是最终f(x)对x求导的结果变为了f(x)对y求导的结果乘以y对x的求导结果反过来也是如此的
当f(x)为最终的损失函数,y、x……代表每一层输出的结果,相邻结果的导数为权重。

如此,从输出层开始反向递归每一层的梯度并储存起来,再根据梯度下降等优化算法来更新模型的权重。

利用梯度下降法关于权重和偏值的变化:变化后 = 变化前 - 学习率✖反向传播到这一步的数值

神经网络输出的结果是一个数据,可能是一个单纯的数字,也可能是一个矩阵

仿射函数(Affine):

变量为多维数组(矩阵),当面对这种情况进行反向传播时,一般利用组件的方式先构造出dot(矩阵乘法)前两个矩阵的形状。

梯度确认:

通过数值微分的方法来确认误差反向传播的正确性。两者的结果并一定是完全相等的,只要处于一定的范围内即可。

与学习相关的技巧

参数的更新:

提出了不同于SGD(随机梯度下降法)的三种最优化方法:

我们需要介绍SGD和其他三种方法的优点和不足,这是我们学习多种方法的原因:

优点 : SGD在实现的过程中比较简单。

缺点: 这与梯度的含义相关,某个点的梯度是指该点函数结果下降最快的点而并不是指向整个函数最小的点虽然这可能并不会影响最后该函数会到达最小值的结果,但是其前往最小值的路径会增长。使得SGD优化效率下降。

其次,对于学习率的选择会在一定程度上影响学习的结果超参数不佳可能会使学习效率不佳甚至学习错误。

1.Momentum学习法:

介绍:

momentum的核心思想在于模拟物理学中的动量概念,通过积累历史梯度信息来加速优化过程,并帮助算法更快速地收敛到最优解。在模拟的过程中,它不仅会考虑此时的梯度问题,还会综合考虑历史梯度的问题,(简单理解)当历史梯度都是正数且此时的梯度也是正数,它将放大这个正数的效果,如果历史梯度都是负数,但此时的梯度为正数,它将会削弱此时梯度的作用。(困难理解)历史参数会乘以一个权重(超参数)并被保存在一个列表中待用,当计算当前时刻的梯度时,需要添加这个列表中的各数据。

优点:

通过引入Momentum算法能够在相关方向上加速学习,同时抑制振荡,从而加速收敛速度。此外,Momentum优化方法还有助于解决Hessian矩阵病态条件问题,即梯度在某些方向上高度敏感的问题。

缺点:

在该优化算法中存在一个超参数,需要人为设置良好的超参数才能体现出该优化方法的效果,超参数的选择对学习效率有影响。

AdaGrad:

介绍:这个优化方法是建立在SGD的基础上。

(简单理解)学习率过大可能导致学习失败,学习率过低可能会导致学习效率低,而该优化方法在开始时使用较大的学习率,学习效率高,随着学习的进行,学习率会逐渐降低,从而一定程度上避免了因学习率过高和过低带来的问题--一种动态学习率的方法。

(困难理解)这个优化方法通过引入一个新的动态变量h(h在数值上等于历史梯度的平方和)并以->lr/h**0.5<-作为学习率,进行学习。

优点:

降低超参数敏感程度:削弱了学习率取值是否合适对SGD的困扰

缺点:

后期学习率过低:导致当学习进行到后期的时候,神经网络可能很难再学到新的东西。

Adam:

介绍:

Adam优化方法学习了上文中Momentum方法(M)和AdaGrad(AG)优化方法的特点和优点。

保留了M模拟物理动量的思想,同时利用了AG的动态思想。有望成为能够快速找到最佳结果的优化方法。

优点:

计算高效:参数更新更加稳定和高效。

内存需求适中:相对于其他一些优化算法,Adam的内存需求相对适中,使得它适用于大规模数据集和参数空间。

自适应学习率:Adam通过计算梯度的一阶和二阶矩估计来自动调整每个参数的学习率,这使得它对于不同的参数和训练阶段具有更好的适应性。

适合非平稳问题:由于Adam能够动态调整学习率,因此它特别适合处理非平稳目标函数和噪声较大的问题。

缺点:

超参数敏感:Adam引入了几个超参数(如学习率、β1、β2等),这些超参数的选择对算法的性能有很大影响。如果设置不当,可能导致算法收敛速度变慢或陷入局部最优。

可能收敛到非最优解:在某些情况下,Adam可能收敛到非最优解,尤其是在某些特定的损失函数和模型结构下。这可能是由于Adam的自适应学习率调整策略在某些情况下过于激进或保守。

早期停止:由于Adam的学习率调整机制,有时算法可能在达到全局最优之前过早地停止更新。

初始权重的设置

在神经网络中,初始参数的设置会直接影响最终的学习成果。

后文会介绍一种抑制过拟合提高泛化性的方法----权重衰减,一种有效的正则化衰减,通过每次参数更新的过程中引入一个衰减系数来减小权重的值为目的进行学习的方法。因此,在设置初始权重时,一个较小的初始权重会比较好。在设置初始权重时,应该保证权重的多样性。

如果所有权重相同,无论更新多少次同一层神经网络的权重数值做相同的变化,权重被更新为相同的值。这就要求,避免每一层神经网络的权重出现对称的值。

个别权重为0是允许接受的,并且也是广泛存在的,在神经网络的学习中,权重为0的神经网络也可能在学习过程中变为非0的值。

----------------------------------------------------------------------------------------------------------------------------上次上传的笔记中标题处的ReLU打错了

图片还不会上传。


解决过拟合问题:

深度学习是通过测试数据使模型拟合现实问题的过程,其最终目的应该立足于解决实际问题。过拟合的现象表现在模型可以很好的拟合测试数据,但是对于现实问题拟合较弱,即过度拟合测试数据。

过拟合对于人工智能而言,代表着其泛化能力的下降,只能识别测试数据,或者与测试数据相差不大的数据,对于与测试数据相差较大的数据则难以识别。

过拟合产生的原因:

训练数据过小,且特征性强:训练数据小,人工智能未能在训练数据中找到属于该项数据的内在规律(就好像语文刷题找答题模板,每道题有共性有特性,如果数据量少,可能会把特性当共性处理)。噪声影响过大,训练数据具备某项特征,使得人工智能认为这项特征是必备的,在现实数据中没有这一特征的数据被排除。

模型复杂度过高:模型试图在每个细节中寻找该类数据的特征,即便测试数据中有些不合理的地方,模型也会尝试拟合这部分。

训练次数过多:训练次数过多,把测试数据一遍遍给神经网络过,相应的特征被神经网络过分看重。

抑制过拟合的方法及原理解析:

正则化:

l1,l2范数,可以称之为一种惩罚机制。

在我们知道过拟合已经发生的情况下,我们可以通过抑制模型对预测数据的拟合程度来修正模型对某些可能无关紧要特征的拟合程度。即表明,如果模型过分拟合预测数据,我们通过抬高相应的损失函数,来告诉模型你其实拟合的并不好。

权重衰减:对大的权重进行惩罚

早停:

用于解决因训练次数太多导致的神经网络过拟合现象。

名词解释:鲁棒,指神经网络在面对各种挑战时保持性能的能力。

我们可以故意加入扰乱数据的方法增强模型鲁棒的能力,也有助于使模型更好的应对过拟合这一问题。

Dropout

在训练过程中,随机抛弃部分神经元,抛弃部分神经元等同于抛弃部分特征对结果的影响,可以增加模型的鲁棒性,并且有助于应对过拟合问题。

超参数的验证:

超参数是人在系统中设置的参数,超参数的设计,是影响学习效率,学习最终结果的重要因素,为了找到相对合适的超参数,往往伴随着很多的试错。但是我们依旧可以通过某些方法减少试错的成本,加快找到合适超参数的过程。

首先,我们要知道如何判断我们的超参数是合适的:在训练数据和测试数据之外,添加一个新的数据分类--验证数据来专门验证超参数的合适程度。(可以是添加的新数据,也可以从现有的数据中分割出来)

超参数的改善过程是一个渐变的过程

还记得高中时求 根号2 的近似值么?我们知道 根号2 小于2大于1,那么从1开始分别计算1.1的平方,1.2的平方……找到小于和大于根号2的界限,以这个界限前后的两个数字为边界构成根号2存在的范围,再在这个范围内提高小数点后的位数,在这个过程中获得每个结果都会更接近最终结果一点。这是一个提高精度的过程。

而超参数的优化过程与这个类似,先确定一个较大的范围,再在这个范围内不断提高精度,最终获得一个误差可接受的超参数。

卷积神经网络(CNN):

(卷积神经网络的可以追溯到Hubel和Wiesel对猫大脑中的视觉系统的研究。)

卷积神经网络是一种专门用来处理具有类似网格结构的数据的神经网络,例如时间序列数据和图像数据,使用了卷积这种数学运算。--《花书》

卷积神经的性质:

卷积的含义:

卷积是一种特殊的线性运算,卷积运算的过程是通过两个函数生成第三个函数的过程,本质是一种特殊的积分变换。

局部性

卷积的目的是放大图片事物的突出特征,部分特征,即从局部区域判定整体性质:譬如,鸟有喙,通过是否拥有鸟喙来确定是否是鸟类。鸟喙是局部特征,但是通过局部特征可以确定整体的性质大概为鸟。

相同性

具有相同性质的物体具备相同的特征,这些特征可能出现在图片的不同位置,但我们检测到他们的方法可以是相同的。

不变性

采样之后,图片性质基本保持不变。

卷积神经网络的组成:

卷积神经网络主要有三部分组成卷积层,池化层,全连接层

卷积神经网络处理原始图片,提取突出,明显的特征,转化为特征得分,根据得分判断该事物所属的类别。

滤波器

滤波器出现在卷积层和池化层,包含了这两层绝大部分的参数,包括滤波器的大小以及步长,其中,根据滤波器步长的设计,滤波器是可以跳过某些数据的。

卷积层:

卷积层是卷积神经网络的核心,其主要的参数由可学习滤波器集合构成,滤波器在卷积层上移动时,当滤波器学习到某些视觉上的特征变量时会被激活。将特征提取出来,一个滤波器一般只针对一个特征。

(需要图例更好理解)

# 以一个单层滤波器处理为例子讲解:

 1  -1  -1  -1   1 这是一个5*5的数据,如果将标注为25各数字的占地围城正方形,
-1   1  -1   1  -1 每个数字占一个等大的小格子,1代表格子为白色,-1代表黑色
-1  -1   1  -1  -1 那么在黑色区域中,白色区域表示的图形表示为一个叉号。
-1   1  -1   1  -1
 1  -1  -1  -1   1 
 
 
 
 
 1  -1  -1 
-1   1  -1    这是一个3*3的滤波器,滤波器与数据的左上角叠放,对应数字相乘做和
-1  -1   1	  和的结果放置在滤波器中心位置。接着,滤波器向右移动步长长度,并进行
			  下一次运算。(用来检验主对角线特征)
这样最终结果使得主对角线上的数字较大,即特征明显,其余地方特征不明显,将主对角线特征提取出来。
接着,可以用第二个滤波器对原始数据进行第二各特征的获取。
池化层:

池化层依旧是依靠滤波器进行处理的,随着滤

处理数据和训练模型的技巧:

1.中心化:

比较常见的方法是使每个特征维度都减去相应的均值,这样可以使得数据变成0均值,可以方便我们在处理数据时减去一个相同的值。

2.标准化:

为了解决不同指标因为其量纲和量纲单位不在一个水平,无法进行比较的问题,将各指标放在同一水平进行比较,是对数据 特征放缩 ,为了确保在放缩过程中数据保持其有效性,常用两种方法:一种时除以标准差,这样可以使得新数据的分布接近高斯分布;话有一种做法就是缩小特征维度,使特征维度的最大值最小值介于-1到1之间。

后续模型使用梯度学习法更新参数学习使,标准化能够加速神经网络的学习速度。

3.PCA

计算协方差矩阵,通过协方差军阵可以验证这个结果的准确性,由于协方差矩阵使对称半定的,可以通过这个协方差军阵来进行奇异值分解,然后对数据进行去相关性,将其投影到一些没有方法的维度/

4.白噪声:

首先,白噪声会跟PCA一样将数据的特征维度投影到一个特征空间,然后每个维度初一特征值来标准化这些数据,直观上就是一个多元高斯分布转化到了一个0均值,协方差矩阵为1的多元高斯分布。

代码向:

代码分析*2(凑字数)+正文介绍

# 主要的库
import torch
import torchvision
# 可以定义的
import torch.nn as nn
# 如果不定义则在后续的代码中,"nn."写为"torch.nn."

# 辅助库
import matplotlib.pyplot as plt
from tqdm import tqdm
# 第一个是将数据图像化,第二个为制作进度条的工具
import torch
import torch.nn as nn
import torchvision
import matplotlib.pyplot as plt
from tqdm import tqdm
import torchvision.models as models
import os
# 尝试调用gpu
device = 'cuda:0' if torch.cuda.is_available() else 'cpu'



# 设置数据路径
path = './dataset/'



# 设置转化形式,将图片转化为包含图片参数的tensor形式,并进行标准化,标准化可以将可以加速后期梯度下降法的速度。
transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor(),torchvision.transforms.Normalize(mean=[0.5], std=[0.5])])

# 设置参数,每批个数,学习率,多少批
BATCH_SIZE = 256
EPOCH = 10
LR = 0.01


# 获取数据
traindata = torchvision.datasets.MNIST(path,train=True,transform=transform,download=True)# 如果已经下载直接使用,如果没有下载数据,自动下载
testdata = torchvision.datasets.MNIST(path,train=False,transform=transform)# 参数train表明该数据为训练数据还是测试数据。

trainDATA = torch.utils.data.DataLoader(dataset=traindata,batch_size=BATCH_SIZE,shuffle=True)# shuffle 表明是否打乱顺序,有助于提高泛化能力
testDATA = torch.utils.data.DataLoader(dataset=testdata,batch_size=BATCH_SIZE)


# 神经网络,利用卷积神经。
class NET(nn.Module):
    def __init__(self):
        super(NET,self).__init__()
        # 添加神经网路层
        self.model = nn.Sequential(
            # RGB三色,灰度图,单色,MNIST为灰度图。
            nn.Conv2d(in_channels = 1,out_channels = 16,kernel_size=3, stride = 1,padding = 1),
            # kernel_size参数表明滤波器的大小,stride参数表明步幅,padding参数表明填充数。
            nn.ReLU(),
            nn.MaxPool2d(kernel_size = 2 ,stride = 2),
			# maxpool2d表明池化层,选出最大值。
            nn.Conv2d(in_channels = 16,out_channels = 32,kernel_size=3,stride = 1,padding = 1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size = 2,stride = 2),

            nn.Conv2d(in_channels = 32,out_channels = 64,kernel_size = 3,stride = 1,padding = 1),
            nn.ReLU(),

            nn.Flatten(),
            nn.Linear(in_features = 7*7*64,out_features= 128),
            nn.ReLU(),
            nn.Linear(in_features=128,out_features= 10)
        )
    # 正向移动
    def forward(self,input):
        output = self.model(input)
        return output
net = NET()


"""# 利用梯度下降法
class NET(nn.Module):
   def __init__(self):
       super(NET,self).__init__()
       self.model = nn.Sequential

"""
lossF = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters())

history = {'Test Loss':[],'Test Accuracy':[]}


for epoch in range(1,EPOCH+1):
    processBar = tqdm(trainDATA,unit ='step')
    net.train(True)
    for step,(trainImgs,labels) in enumerate(processBar):
        trainImgs = trainImgs.to(device)
        labels = labels.to(device)

        net.zero_grad()
        outputs = net(trainImgs)
        loss = lossF(outputs,labels)
        predictions = torch.argmax(outputs,dim = 1)
        accuracy = torch.sum(predictions == labels)/labels.shape[0]
        loss.backward()
        optimizer.step()

        processBar.set_description("[%d/%d Loss: %.4f,Acc:%.4f" %
                                   (epoch, EPOCH,loss.item(),accuracy.item()))
        if step == len(processBar) - 1:
            correct,totalLoss = 0,0
            net.train(False)
            for testImgs,labels in testDATA:
                testImgs = testImgs.to(device)
                labels = labels.to(device)
                outputs = net(testImgs)
                loss = lossF(outputs,labels)
                predictions = torch.argmax(outputs, dim=1)

                totalLoss += loss
                correct += torch.sum(predictions == labels)
            testAccuracy = correct/(BATCH_SIZE*len(testDATA))
            testLoss = totalLoss/len(testDATA)
            history['Test Loss'].append(testLoss.item())
            history['Test Accuracy'].append(testAccuracy.item())
            processBar.set_description("[%d/%d] Loss: %.4f, Acc: %.4f, Test Loss: %.4f, Test Acc: %.4f" %
                                   (epoch,EPOCH,loss.item(),accuracy.item(),testLoss.item(),testAccuracy.item()))
    processBar.close()

代码规范:

有些代码规范可能与python代码规范有些重合的部分:

譬如,不要在一行放入过长的语句,对于过长的语句可以采取换行处理的方法。

程序的部分功能可能写入不同的.py文件来进行管理,方便以后对于某些功能可以直接拿过来使用。

标签:函数,梯度,学习,神经网络,参数,深度,数据
From: https://www.cnblogs.com/zonghongqi/p/18321793

相关文章

  • 卡尔曼滤波器原理的学习理解
    一、什么是卡尔曼。跟其他著名的理论(例如傅立叶变换,泰勒级数等等)一样,卡尔曼也是一个人的名字,而跟他们不同的是,他是个现代人!1960年卡尔曼在他的博士论文和发表的论文《ANewApproachtoLinearFilteringandPredictionProblems》(线性滤波与预测问题的新方法中提出了这种算法......
  • C语言学习day03
    变量概念表面:程序运行过程中取值可以改变的数据实质:变量其实代表了一块内存区域/单元/空间。变量名可视为该区域的标识。整个变量分为三部分:  变量名:这个只是变量的一个标识,我们借助变量名来存取数据。  变量空间/内存单元:这个就是内存中分配的一块用来存储数据的......
  • Spring Boot学习|Stopwatch 在 Spring Boot 中的使用
    文章目录什么是Stopwatch?使用场景优点缺点注意事项使用步骤使用案例及结果可能面试题1.**理解与解释**2.**技术细节**3.**实际应用**4.**优缺点与替代方案**5.**面向框架的具体问题**6.**高级主题**什么是Stopwatch?Stopwatch是由ApacheCommonsLang......
  • 【数据结构初阶】一篇文章带你超深度理解【单链表】
     hi!目录前言:1、链表的概念和结构2、单链表(SingleList,简写SList)的实现2.1  定义链表(结点)的结构2.2 创建一个链表2.3 打印链表2.4 尾插2.5 头插2.6 尾删2.7 头删2.8 查找2.9 在指定位置之前插入数据2.10 在指定位置之后插入数据2.11......
  • 目标检测的即时演进:在线学习在行动
    目标检测的即时演进:在线学习在行动在线学习(OnlineLearning)是一种机器学习范式,它允许模型通过逐步接收数据并实时更新来学习。这种学习方式对于目标检测尤其重要,因为它允许检测系统在不断变化的环境中适应新的或罕见的目标,同时保留对旧目标的检测能力。本文将探讨在线学习......
  • hadoop学习
    Hadoop是一种用于存储和处理大数据的开源软件框架,它采用分布式文件系统和MapReduce编程模型,可以有效地处理海量数据。在学习Hadoop的过程中,我掌握了许多重要的知识和技能,以下是我的Hadoop学习总结:首先,我学会了Hadoop的核心概念和架构。Hadoop由HDFS(分布式文件系统)和MapReduce组成......
  • opencascade AIS_Line源码学习
    前言AIS_Line是OpenCASCADE库中的一个类,用于表示和操作三维直线。它可以通过几何线(Geom_Line)或者两个几何点(Geom_Point)来初始化。方法1//!初始化直线aLine。Standard_EXPORTAIS_Line(constHandle(Geom_Line)&aLine);2//!初始化直线的起点aStartPoint和终......
  • 基于AT89C51单片机的简易计算器(含仿真、源码、论文适用于小白学习、课程设计等)
    本篇文章论述的是基于AT89C51单片机的简易计算器设计的详情介绍,如果对您有帮助的话,还请关注一下哦,如果有资源方面的需要可以联系我。含有仿真、源码的下载链接(如果打开不显示就是资源在审核中,如果着急需要的话可以私信我获取)基于AT89C51单片机的简易计算器资源-CSDN文库......
  • 学习vue第一天
    文章目录1.什么是Vue?2.渐进式框架3.如何新建一个vue项目1.什么是Vue?Vue(发音为/vjuː/,类似 view)是一款用于构建用户界面的JavaScript框架。它基于标准HTML、CSS和JavaScript构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无......
  • Java基础常见面试题学习(上)
    1、JVMvsJDKvsJRE①Java虚拟机(JVM)是运行Java字节码的虚拟机。JVM有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的JVM实现是Java语言“一次编译,随处可以运行”的关键所在。JVM并不是只有一种!只要满足JVM规范,......