大白话5分钟带你走进人工智能-第十节梯度下降之归一化的各种方式和必要性(5)

本文主要是介绍大白话5分钟带你走进人工智能-第十节梯度下降之归一化的各种方式和必要性(5),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

                                            第十节梯度下降之归一化的各种方式和必要性(5)

上一节中我们讲解了梯度下降的函数最优化算法和梯度下降代码过程,了解了梯度下降的代码实现过程,本节的话我们讲解一个梯度下降之前必要的数据准备,归一化。

先看一个例子,假如你收集到一个数据集,一列是年龄,一列是身高(厘米)。比如体重的数据都是60,65。身高的数据是180,185,你发现它的量纲远远大于age,这样会导致什么?比如身高是W2,体重是W1,假如要根据这些数据预测寿命,比如结果是这样的:

 

体重身高预测年龄
6018070
6518580

因为最后它们相乘相加等于你预测的年龄,那么对数据本身来说量纲比较小的数字,它会乘的W比较大一些。因为体重乘上比较小的数字w1+身高乘以比较大的数字w2,才能等于最后的年龄。这么想好像没什么问题,相当于程序给我们把数据自动修正了,身高数据大,我就自动W小点,预测也不会出问题,虽然看起来没问题,但它在梯度下降的效率上会导致一定的问题。会导致一个什么问题呢? 比如W2小,它越小,是不是越灵敏相当,那么W2动一点就会怎么样?我们先看下上面数据训练模型时如果不做归一化的损失函数的等高线如图:

等高线里面,每一个圆的损失函数是一样的。在这个例子里面,你觉得θ1(即w1)和θ2(即w2),谁是age谁是height?实际上θ2是height,θ1是age,为什么?因为W2是不是小,你动一点点,损失函数会变化的很多,所以图中θ2一点点变化,损失函数就会从一个圆变到另一个圆,所以θ2对应着身高前面的参数。那么这会导致什么问题?我们看下图中的θ1(即w1)和θ2(即w2)的更新参数:

                                                                \theta=\theta-\alpha \cdot \frac{\partial J(\theta)}{\partial(\theta)}

                                                               \frac{\partial J(\theta)}{\theta_{j}}=(h_\theta(x)-y)x_{j}

无论对于W1来说还是W2来说,(h_\theta(x)-y)x_{j}前边部分有区别吗? 没区别吧?那么体现在更新W1和W2的更新的不同,是Xj不同。在θ2的方向上,因为X2比较大,所以θ2方向每次加的都很大,而θ1方向每次加的又比较小,假如最开始在初始点那块,θ2距离自己的终点也就是最后的最优解的点其实很近,而θ1距离自己的终点很远,按理说θ1应该赶紧紧跑两步对不对?而现在变成了θ2在反复的震荡,而θ1在不着急得一步一步走,这样的话会导致你的计算效率变得特别慢。梯度下降的过程中,你想让W2是不是每一步更新更加细致一点,更微小一点,更精准一点,让W1每一步更大刀阔斧一点?所以如果量纲不一致,会导致本来需要一步一步慢慢走的这个维度W2,反倒震荡的特别厉害。W1想让它变化快一点,但X1比较小,会导致它下降的速度反倒慢了,适得其反。讲到这里,有的人会说我调控每一步下降的\theta=\theta-\alpha \cdot \frac{\partial J(\theta)}{\partial(\theta)}中的α,也就是我们的λ,是不是可以控制下每次减的幅度?这里想让大家想一个问题,λ是只有一个数还是说每个维度各有一个λ?如果每个维度各有一个λ就没这问题了,你自己单独的给它们调一下就行了,但是调参又变得复杂了,你有一千个维度,难道你还要手工设一千个λ,还要细致地调吗?不现实。这数根源就是因为只有一个λ管着我所有的W,那么需要大的反倒小了,小的反倒大了。 所以我们怎么办?

我们就需要对数据进行一个归一化。比如我原来原始数据身高是180,170,160,150,我做一个最大最小值归一化,最大最小值归一化公式是:

                                                       x^{\prime}=\frac{x-\min (x)}{\max (x)-\min (x)}

我用X减去最小的X,除以(最大的X,减去最小的X),假设这四个数,180,170,160,150。那么此时180会变成什么?你们根据这算一下。180变成1了,150变成什么了?0了,中间是0到1的一些数相当于就把所有列,如果你都执行这么一遍的话,是不是就变成了所有数都在0到1之间了。这样他们的量纲就一样了。这样我们的损失函数就会从一个椭圆特别椭的圆变成一个比较圆的圆。如下面一样:

因为各个维度的数值通过最大最小值归一化之后会让它两边的步伐速度是一致的,不会存在谁等谁的情况,所以损失函数等高线的图就近似一个相对比较圆的圆。这样会带来更快的收敛步数和更快的收敛速度。除此之外,归一化还有什么好处?对one-hot编码来说,有的维度转变成one-hot编码,比如性别转成one-hot之后男的是0-1 女的是1-0两个维度标识性别,这样相对公平,不至于男的性别是1 ,女的性别是0,这样会给机器学习一种错误的输入,男的比女的大的错误信息,因此需要转成one-hot编码。但假如有的没转成one-hot编码,比如身高,没转one_hot编码的这些维度如果经过最大最小值归一化都给它缩放到零和一之间后,这样跟经过one-hot编码的那些维度的量纲也都一致了,在训练模型的时候,经过处理过的训练集就是一堆你看不懂的数了,比如身高它就不再代表实际物理意义上的高度有多高了,但它是一个高度的评分,越近越1越代表你在这里边越高。例如170和160,经过最大值最小值归一化之后,肯定170更接近数值1。

那么当预测一条新数据的时候,怎么预测? 你还能把原始数据直接丢进去算吗?你是不是需要对新的数据要做最大最小值归一化,用谁的最大值?谁的最小值?用你的训练集中的最大值和训练集中的最小值做归一化,我们称它为经验最大值和经验最小值。好在这些事情不需要你来手工处理,只要你把normalize=true,就可以了。

                      lin_reg = LinearRegression(normalize=True)

这一切的一切底层就帮你做好了。它做的不光是最大最小值归一化,它还要做零均值化,它要把每一个X都减去这一列的平均值。为什么要这么做?比如看下面的例子:

假如你随机到图中这个点了,再接着往下,θ1需要增大减小?增大,对吧?θ2需要增大还是减小?减小。所以θ1需要增大,θ2需要减小,但θ1和θ2怎么算的?咱们看随机梯度下降,对于θ1也好,θ2也好,(h_\theta(x)-y)x_{j}(h_\theta(x)-y)这一项都一样,能影响它到底增大还是减小,是不是取决于它Xj? 所以对于θ1就把X1带进去,对于θ2就把X2代进去。通常训练集里的数据是不是都是正数?如果你不做零均值化的话,所有X都是正数,是不是所有的θ要增都增要减都减。对于这个例子,要想走到最优解,应该这样走,如图:

如果不去处理归一化的话,这会只能θ1也增θ2也增,第一步θ2先少增一点,尽量等一下θ1,θ1多走点, 甚至走过θ1的最优值,然后,θ1减,θ2也减才能走到最后最优解的那个点,它不具备同时一个参数增另一个参数减的这么一个功能。但假如你对它做一个零均值化,比如第二列X2,1.8米,1.7米,1.6米,1.5米,都减去均值后,这就变成了+1.5,+0.5,-0.5,-1.5,这会X是不是就有正有负了?有正有负了之后,是不是它就有可能进行这种有的增有的减的这种下降?所以说normalize里面至少会同时做最大最小值归一化来保证量纲一样和零均值化让所有的维度数值有大有小,这样才能获得更好的梯度下降效率。 如果你不做这些也能得到最优解,就是人家走10步你可能走15步这么一个概念,它效率更低,做了这个能够帮助你下降的更快,更好的找到这个结果。那么来一条新数据,是不是也得减去平均值,减谁的平均值?减你训练集里边的算出来平均值,能理解吗?这个也叫经验平均值。 经验平均值这个东西在深度学习里面一样要这么处理。只要用到梯度下降,就都需要这么处理。只要有梯度下降,均值归一化是必须的,没有均值归一化的话,它下降速率一定会慢好多,因为它老要走曲折的弯路。

对于有些算法,还会使用方差均值标准化来调整数据使模型训练拥有更好的性能。即:

                                                                               x^{\prime}=\frac{x-\overline{x}}{\sigma}

所以归一化方式是进行模型训练前的必要步骤,也是数据处理的关键步骤。下面一节我们将手动实现批量梯度下降和随机梯下降的方式,不调sklearn里面的api

这篇关于大白话5分钟带你走进人工智能-第十节梯度下降之归一化的各种方式和必要性(5)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/309479

相关文章

gradle第三方Jar包依赖统一管理方式

《gradle第三方Jar包依赖统一管理方式》:本文主要介绍gradle第三方Jar包依赖统一管理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景实现1.顶层模块build.gradle添加依赖管理插件2.顶层模块build.gradle添加所有管理依赖包

Linux之systemV共享内存方式

《Linux之systemV共享内存方式》:本文主要介绍Linux之systemV共享内存方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、工作原理二、系统调用接口1、申请共享内存(一)key的获取(二)共享内存的申请2、将共享内存段连接到进程地址空间3、将

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

C#使用StackExchange.Redis实现分布式锁的两种方式介绍

《C#使用StackExchange.Redis实现分布式锁的两种方式介绍》分布式锁在集群的架构中发挥着重要的作用,:本文主要介绍C#使用StackExchange.Redis实现分布式锁的... 目录自定义分布式锁获取锁释放锁自动续期StackExchange.Redis分布式锁获取锁释放锁自动续期分布式

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

Spring Boot读取配置文件的五种方式小结

《SpringBoot读取配置文件的五种方式小结》SpringBoot提供了灵活多样的方式来读取配置文件,这篇文章为大家介绍了5种常见的读取方式,文中的示例代码简洁易懂,大家可以根据自己的需要进... 目录1. 配置文件位置与加载顺序2. 读取配置文件的方式汇总方式一:使用 @Value 注解读取配置方式二

JAVA保证HashMap线程安全的几种方式

《JAVA保证HashMap线程安全的几种方式》HashMap是线程不安全的,这意味着如果多个线程并发地访问和修改同一个HashMap实例,可能会导致数据不一致和其他线程安全问题,本文主要介绍了JAV... 目录1. 使用 Collections.synchronizedMap2. 使用 Concurren

C# foreach 循环中获取索引的实现方式

《C#foreach循环中获取索引的实现方式》:本文主要介绍C#foreach循环中获取索引的实现方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、手动维护索引变量二、LINQ Select + 元组解构三、扩展方法封装索引四、使用 for 循环替代

将Java程序打包成EXE文件的实现方式

《将Java程序打包成EXE文件的实现方式》:本文主要介绍将Java程序打包成EXE文件的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录如何将Java程序编程打包成EXE文件1.准备Java程序2.生成JAR包3.选择并安装打包工具4.配置Launch4

springboot上传zip包并解压至服务器nginx目录方式

《springboot上传zip包并解压至服务器nginx目录方式》:本文主要介绍springboot上传zip包并解压至服务器nginx目录方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录springboot上传zip包并解压至服务器nginx目录1.首先需要引入zip相关jar包2.然