机器学习笔记 第二篇 (梯度下降法原理、过拟合、误差函数为什么用平方而非绝对值)

首先需理解第一篇内容点击前往


梯度下降法原理

如何随机上篇中的W0,W1 (W)

对于上篇中的下图:
在这里插入图片描述

w0调整

假设现在随机到的W(即w0,w1)在图中位置,很明显,如果我们想要使J()尽可能的小(也就是我们的误差函数的值尽可能小),需要将w1往小调整,w0往大调整,那么具体调整多少?先看下图
在这里插入图片描述
该图为第一章图从某方向看的二维图,最下方是我们想要取到的w0的值,那么,很明显,在虚线的左边,J()对w0的偏导数小于0,在虚线右边,J()对w0的偏导数大于0
所以,在对w0偏导数小于0时,我们应该往大调整w0,那么W0应该加上一个正数,因为此时J()对w0的偏导数小于0,那么可以让w0减去此时的偏导数作为下一次的w0

同理,在虚线右边,我们需要减小w0,就是让w0减去某个正数,此时恰好导数大于0,那么便可以归纳出以下公式

在这里插入图片描述
代入原式(误差函数公式),得:
在这里插入图片描述

同理,w1调整

在这里插入图片描述
代入原式,对w1求偏导,得:
在这里插入图片描述

为什么要乘以一个常数阿尔法(也叫做学习率)

阿尔法是学习率,偏导数正负决定的是w调整的方向,而学习率,决定了他调整的大小(速度、步长、幅度)

重新总结一遍训练步骤:

  1. 随机w0,w1的参数值

  2. 训练集数据和随机出来的w参数代入误差函数求解误差

  3. 如果误差小于用户设置的阈值,此时的w参数便是最佳参数

  4. 否则调整w参数,循环2,3

  5. 调整依据:在这里插入图片描述

  6. 如果已经达到迭代次数,退出

###梯度下降法这个名字由来
梯度,始终是沿着函数上升的方向,对于下图中左右两个点的梯度,分别是箭头所指的方向

在这里插入图片描述
可以发现,不管左边还是右边,我们都需要让w按照梯度的方向相反的方向调整,于是乎该方法就叫做梯度下降法

梯度下降法代码(python)

PS:代码中用到了numpy,如果没有请自行安装Anaconda

import numpy as np

def h(x):
    return w0 + w1 * x

rate = 0.001
x_train = np.array([1,2,3,4,5,6,7,8,9,10])
y_train = np.array([2,3,4,5,6,7,8,9,10,11])

w0 = np.random.normal()
w1 = np.random.normal()

err = 1
while(err > 0.0001):
# for i in range(10000):
    for x, y in zip(x_train, y_train):
        w0 = w0 - rate * (h(x) - y) * 1
        w1 = w1 - rate * (h(x) - y) * x

        err = 0.0
        # 累加
        for x, y in zip(x_train, y_train):
            err += (y - h(x))** 2
        # 根据表达式,还要除以2m
    m = len (x_train)
    err = err / (2.0 * m)
    print(w0, w1)

代码中,rate是公式中的阿尔法(学习率),查看运行结果:

.....................................
0.9683975748539286 1.0043385645044027
0.9684644356780738 1.0043293854620656
0.9685311550456763 1.0043202258397042
0.9685977332560135 1.0043110855962323
0.96866417060773 1.0043019646906501
0.9687304673988387 1.004292863082045
0.9687966239267217 1.0042837807295901
0.9688626404881322 1.0042747175925457
0.968928517379195 1.004265673630258
0.9689942548954087 1.0042566488021591
0.9690598533316471 1.004247643067767
0.96912531298216 1.0042386563866854
0.9691906341405743 1.0042296887186037
0.9692558170998955 1.0042207400232963
0.9693208621525099 1.0042118102606228
0.969385769590185 1.0042028993905279
0.9694505397040706 1.0041940073730402
0.9695151727847007 1.0041851341682737
0.969579669121995 1.0041762797364273

前面省略了一部分,可以发现,w0和w1越来越接近1,为什么,因为代码中给的10个点,其实是在一条斜率为1的直线上

为什么调整W时是减去学习率*偏导数而不是直接加减阿尔法(学习率):

在这里插入图片描述
因为会出现下面情况:
在这里插入图片描述
在左边,因为导数1小于0,所以增加阿尔法到导数2
在右边,又因为导数大于0,所以减少阿尔法到导数1,无限震荡

但如果引入偏导后,首先,我们知道,导数1的绝对值大雨导数2的绝对值,这意味着如果从左边跨越到右边的距离是阿尔法*导数1的绝对值,则下次从导数儿往左跨越时,一定会比刚刚跨越的距离小,也就是说,会逐渐逼近最小值(震荡下旋)
如图:
在这里插入图片描述

再考虑一个问题,如果 学习率 设置的很大,会出现什么情况:

如下图,盘旋上升,因为你每一次移动,w跨越距离太大,反而使得 偏导数 的绝对值越来越大了(螺旋上升)
在这里插入图片描述
可以通过刚刚的代码验证这一点:
修改学习率rate为0.1,重新执行代码,得到以下结果,直至程序溢出报错

12.038784052571156 103.34250994220841
-909.8467771316002 -7945.557607449751
70558.7079571713 615929.9262668388
-5468976.384224963 -47740807.72627898
423901740.59638625 3700401665.338483
-32856726730.726837 -286819031057.0279
2546732862960.7207 22231412705407.254
-197397882274541.4 -1723162194136934.2
1.5300357761585996e+16 1.3356271986173587e+17
-1.1859344433439048e+18 -1.0352478830815695e+19
9.192206651798107e+19 8.024231466193059e+20
-7.124901684372331e+21 -6.2196012834512244e+22
5.522528586978794e+23 4.8208280491515676e+24
-4.280525310390261e+25 -3.73663552056355e+26
3.317845556489099e+27 2.896275260428445e+28
-2.5716701429131005e+29 -2.2449099833276616e+30
1.9933077689574564e+31 1.7400351762486475e+32
-1.5450176892769626e+33 -1.3487054880011839e+34
1.19754696056155e+35 1.0453848969226704e+36
-9.282215554576229e+36 -8.1028037064906e+37
7.194667803358234e+38 6.280502817592795e+39
-5.576604475120133e+40 -4.8680329760666085e+41
4.3224396625253677e+42 3.773224173977019e+43
-3.3503334725509577e+44 -2.9246352144862244e+45
2.5968516054975653e+46 2.266891852544614e+47

还有最后一种情况,学习率(阿尔法)的设置刚好使w修改后位置的导数与之前相同,则不断平行来回不变

所以我们应该知道,阿尔法的调整具有一定的艺术性

上篇遗留问题:损失函数为什么用平方不用绝对值?

在这里插入图片描述
在这里插入图片描述
如下图:
在这里插入图片描述

y=x是移动前,y=x+1是移动后,共有3个点
首先应该知道y=x与y=x+1哪个更合适,答案是y=x,因为y=x考虑到了第三个点(4,2)
那么,我们用平方的方法去计算误差,
对于y=x,点(4,2)(1,2). (2,3),它的误差函数结果是(4-2)^2+(1-2) ^2+(2-3) ^2 = 6
对于y=x+1,误差函数的结果是9

如果使用绝对值呢?
对于y=x,他的误差函数结果将会是:|4-2|+|1-2|+|2-3|=4
对于y=x+1, 他的误差函数结果将会是:|2-2|+|3-3|+|5-2|=3
也就是说,他会认为y=x+1比y=x更合适,这并不是我们想要的答案

所以我们的误差函数用平方而非绝对值

过拟合与欠拟合

在这里插入图片描述
看上图,误差为0,好吗?显然不好,因为根本代表不了空间中点的规律,类似学痴(学痴:学了很多题,但是是在背题,一到考试啥都不会;学霸:通过做题找到规律,碰到类似题能做对)

这就是过拟合

如何控制模型不会过拟合?

答案,需要一个测试集

将数据分为三份:验证集、训练集、测试集
训练集用来训练
验证集用来计算通过模型得到的值与真实值的误差,辅助我们选择合适模型
测试集:当你得到好的模型后,肯定是拿来用的,测试集就是你想要预测的数据

在不断的训练中,对于训练集,误差一定是在不断减小,但当通过模型对验证集进行训练时,得到的误差却未必会减少,当模型训练次数过大时,模型由于过拟合,反而可能会使验证集的误差更大。
在这里插入图片描述
简言之,随着在模型训练的过程中,验证集的误差大多数时候应该略微大雨训练集的误差,但是如果某次训练后,验证集的误差远远大于训练集的误差,则有可能发生了过拟合。

那么欠拟合呢:其实就是训练次数太少,连训练集的误差都很大(学渣)

下图包含了两篇文章所讲的全部内容,来自网络,用来辅助理解
在这里插入图片描述

迄今为止,一直都是只用了1个x,两个w,如果再加一个呢?

请见下篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值