机器学习-梯度下降参数调优小结

在机器学习领域,通过对特征的参数调优可以让模型的预测值更接近真实值的常见的两种方法包括最小二乘法和梯度下降方法。目前梯度下降更成为了一种解决问题的方法和思路,在集成学习和深度学习领域都有较多的应用。

定义

直观理解“梯度下降”:我们在山上想要下山的时候,不知道方向,手头上只有一个仪器可以提醒当前的海拔,这时候随意的走一步可以知道海拔变大还是变小,往海拔变小的方向一步一步走,通过顺着梯度下降的方向一步步缩小海拔,直到海拔也基本没有变化为止,这样我们就从山顶走道山下。这就是梯度下降的一个运算思维。在实际的机器学习中,山顶的海拔高度代表了模型的预测值和真实值之间的差距,而梯度下降的方法是通过不断迭代的方式来缩小这个差距,直到该差距收敛到极小值,从而确定参数。
以电子商务推荐算法为例,从建模的角度描述如何通过梯度下降来做参数调优:
用户对于商品的兴趣可以通过简单的线性回归建模,并设计函数h(x)来代表模型预测用户对于某个商品的购买兴趣,如果购买兴趣高,则可以作为商品推荐。模型的公式如下:


其中X(x1,x2...)是购买行为的特征,例如用户的年龄和喜好,商品类别和价格,参数组θ(θ0,θ1...)表示特征对于预测值的影响大小。
机器学习中除了包括数据分析、特征选择、模型选择之外,还有一个步骤是参数调优。假设 模型的X已经确定,目前需要确定参数组θ,来评估对于特定用户对于特定商品的购买兴趣而言,究竟是商品的价格重要还是用户的爱好影响更重要。
我们需要构建一个损失函数去评估所选择参数的优劣,简单的认为在当前参数组θ,直接比较预测值和真实值差距即可,公式表达为:

梯度学习方法就是通过调整参数组θ从而让J(θ)取得最小值,调整的方法与从山上顺着梯度朝下一样:

  1. 首先对θ初始赋值,这个值可以是随机的,也可以让θ是一个全零的向量。
  2. 改变θ的值,使得J(θ)按梯度下降的方向进行减少,直到损失函数差减小收敛到极小值或者0为止。

第二个步骤是关键步骤,就是如何让θi会向着梯度下降的方向进行减少,对于(θ)求偏导J,我们可以进一步得到θ的变化函数:



其中α表示步长,h(x)-y表示上次误差,通过上次误差、步长和变量来反馈更新θi。更新的图示如下,其中的两个黑线都是梯度下降的可能运行方向。



当参数组θ的每一个参数都按照这样的计算公式进行变化更新的时候,模型的预测值将会以梯度的方向接近真实值,最终得到一个最优值,这个最优值可能是局部最优也可能是全局最优,我们将在后面的章节讨论这个问题。

关联概念

在上一章节,我们举的建模样例中提到了一些概念,系统介绍一下:

  • 特征x:建模的输入变量,例如商品推荐中商品的价格、类别等参数。
  • 预测值:建模h(x)的输出指标,例如商品推荐中预测用户对于某商品的兴趣程度。
  • 损失函数 J(θ):为了评估模型拟合的好坏,通常用损失函数来度量拟合的程度。损失函数极小化,意味着拟合程度最好,对应的模型参数即为最优参数。在线性回归中,损失函数通常为样本输出和假设函数的差取平方。
  • 步长:梯度下降过程中,每一步参数变化的长度大小。步长的设置应该仔细斟酌,如果太小,得到最优参数组合的速度很慢(需要迭代的轮数次数会很多),如果太大,收敛过早得到的并非是最优参数,模型的可靠性不高。
  • 初始赋值:初始值不同,获得的最小值也有可能不同,因此梯度下降求得的只是局部最小值;当然如果损失函数是凸函数则一定是最优解。由于有局部最优解的风险,需要多次用不同初始值运行算法,关键损失函数的最小值,选择损失函数最小化的初值。
  • 退出阈值:当梯度下降的下降幅度达到该阈值时,退出梯度下降。该退出阈值应该尽量接近0(如果有充足的资源进行迭代训练的话),我个人认为最低不大于步长的百分之一,即在最大百分之一步长内的变化即认为收敛到无法变化了。

对于步长和退出阈值应该基于训练数据多次遍历后判断得出

在训练的时候一个技巧:对特征值x进行归一化处理提高迭代的速度。可以参考博文 的方法。

算法版本

批量梯度下降

批量梯度下降法的做法是,当前一步的梯度下降迭代遍历中参数空间θ的保持不变,当前步结束后,使用更新后的参数θ获得步长大小,然后进行下一步的梯度下降,这就是批量的梯度下降思路。
批量梯度下降的方法需要计算整个数据集才会更新一次参数θ,对于数据集较大的情况下,会非常耗时,另外也不适用于在线更新模型的应用情况,因此应用不太广泛。
代码示例如下:

x = [(1,0.,3) , (1,1.,3) ,(1,2.,3), (1,3.,2) , (1,4.,4)]
y = [95.364,97.217205,75.195834,60.105519,49.342380]
my_break=0.00001
alpha=0.01
diff=0
error1,error0=0,0
theta0,theta1,theta2=0,0,0
sum0,sum1,sum2=0,0,0
while True:
    for i in range(len(x)):
        #批量更新参数
        diff=y[i]-(theta0*x[i][0]+theta1*x[i][1]+theta2*x[i][2])
        sum0=sum0+alpha*diff*x[i][0]
        sum1=sum1+alpha*diff*x[i][1]
        sum2=sum2+alpha*diff*x[i][2]
        count+=1
    theta0,theta1,theta2=sum0,sum1,sum2
    error1=0
    for i in range(len(x)):
        error1+=(y[i]-(theta0*x[i][0]+theta1*x[i][1]+theta2*x[i][2]))**2/2
        count+=1
    if abs(error1-error0)<my_break:
        break
    else:
        error0=error1
print("Done: theta0:{0}, theta1:{1}, theta2:{2}.".format(theta0,theta1,theta2))

随机梯度下降

随机梯度下降与批量梯度下降类似,唯一的区别在于在每一步梯度下降的迭代遍历中,参数空间θ都在变化。也即是说批量梯度下降用所有数据来做梯度下降,随机梯度下降用的是单条数据来做梯度下降。
随机梯度下降的优点是训练速度快,随之而来的是所得到的解并不是最优解,准确度没有批量梯度下降好,尤其是当训练数据噪音比较大的情况。
代码演示如下:

x = [(1,0.,3) , (1,1.,3) ,(1,2.,3), (1,3.,2) , (1,4.,4)]
y = [95.364,97.217205,75.195834,60.105519,49.342380]
my_break=0.00001
alpha=0.01
diff=0
error1,error0=0,0
theta0,theta1,theta2=0,0,0
sum0,sum1,sum2=0,0,0
min_x=2
while True:
    for i in range(len(x)):
        #迭代内参数被单次样本迭代进行更新
        diff=y[i]-(theta0*x[i][0]+theta1*x[i][1]+theta2*x[i][2])
        theta0=theta0+alpha*diff*x[i][0]
        theta1=theta1+alpha*diff*x[i][1]
        theta2=theta2+alpha*diff*x[i][2]
        count+=1
    error1=0
    for i in range(len(x)):
        error1+=(y[i]-(theta0*x[i][0]+theta1*x[i][1]+theta2*x[i][2]))**2/2
        count+=1
    if abs(error1-error0)<my_break:
        break
    else:
        error0=error1
print("Done: theta0:{0}, theta1:{1}, theta2:{2}.".format(theta0,theta1,theta2))

小批量梯度下降

小批量梯度下降结合了批量梯度下降准确度高和随机梯度下降训练速度快的特点,对于训练集m的迭代中,选择x(1<x<m)次迭代后,参数空间θ进行更新。

x = [(1,0.,3) , (1,1.,3) ,(1,2.,3), (1,3.,2) , (1,4.,4)]
y = [95.364,97.217205,75.195834,60.105519,49.342380]
my_break=0.00001
alpha=0.01
diff=0
error1,error0=0,0
theta0,theta1,theta2=0,0,0
sum0,sum1,sum2=0,0,0
count=0
min_x=2
while True:
    count_x=0
    for i in range(len(x)):
        diff=y[i]-(theta0*x[i][0]+theta1*x[i][1]+theta2*x[i][2])
        sum0=sum0+alpha*diff*x[i][0]
        sum1=sum1+alpha*diff*x[i][1]
        sum2=sum2+alpha*diff*x[i][2]
        count_x+=1
        #在迭代内部小批量迭代更新参数
        if count_x%min_x==0:
            theta0,theta1,theta2=sum0,sum1,sum2
        count+=1

    error1=0
    for i in range(len(x)):
        error1+=(y[i]-(theta0*x[i][0]+theta1*x[i][1]+theta2*x[i][2]))**2/2
        count+=1
    if abs(error1-error0)<my_break:
        break
    else:
        error0=error1
print("Done: theta0:{0}, theta1:{1}, theta2:{2}.".format(theta0,theta1,theta2))

过度拟合

梯度下降的目标是在降低预测值和真实值之间的差距从而获得最优的参数空间,基于已有的数据进行迭代训练,需要特别注意”过度拟合“的现象。
防止过度拟合的方法可以参考这篇博文机器学习:防止过拟合的方法
这里参考wiki使用Early Stopping的方法来做防止过拟合:

  1. 将训练数据分隔成训练集和测试集,80%:20%或者2:1的比例都行;
  2. 只基于训练集进行训练,每轮训练集迭代后记录并记为一次EPOCH,每隔N(N=5,8...)个epoch在测试集上运行validation metric进行计算得到validation accuracy并,validation metric可以是模型表现的评估函数;
  3. 当连续M(M=10)次EPOCH没有达到最佳的validation accuracy,停止在训练集上的迭代;
  4. 记录最佳validation accuracy所对应的参数。

上述的方法是与梯度下降结合使用的,也可以认为在梯度下降的退出条件中增加了一个过渡拟合。除此之外,还可以选择交叉验证、拓展数据集数据等方法来进行过拟合。

局部最优VS全局最优

在不考虑模型过拟合的情况下,梯度下降得到的最优解不一定是全局最优解,也有可能是局部最优解,注意本文第三章节的代码示例中,梯度下降的退出条件:

if abs(error1-error0)<my_break:
    break

在下降过程中,我们找到了一个数据无变化的点(不动点),这个不动点可能有三个含义:极大值、极小值和鞍点。在梯度下降中,极大值基本上可能性没有,只有可能是极小值和鞍点。当前仅当梯度下降是凸函数时,梯度下降会收敛到最小值。
也就是在使用梯度下降中,我们最大可能得到是局部最优解。
为了确保不动点是局部最优解,可以设置更小的退出阈值,进行多次比较看看参数是否变化,如果变化了,说明可以再次调试。
总的来说,梯度下降时一种获得最优解的参数组合的思路,实际应用过程中会结合多种优化方法一起使用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容