机器学习-线性回归

本文参考python机器学习手写算法系列——线性回归进行适当自己的修改

回归分析是一种因变量为连续值的监督学习

线性回归是一种x和y之间的关系为线性关系的回归分析,也就是最简单那种类似 y=ax+b 即为一元线性回归。


假设问题

    从最简单的一元线性回归来谈,我们会得到具体的x列表及对应的y值,例如下:

XY
1385421332
1221320162
1100919138
1065518621
950318016

    我们看一下散点图

    从散点图上其实我们也能看到大致的线的趋势,所以问题其实就是如何选择合适的斜率a、截距b点

    我们先想一下我们能怎么休闲手动做这件事情:

        调整斜率a,调到觉得适合了,我们就调调截距b,总会有个相对拟合情况较好的。

    再想:

        第一个问题:我们怎么判断哪个好哪个不好?

        答:损失函数 Cost Function

        第二个问题:怎么调整斜率a和截距b?

        答:暴力求解当然是不可能的,所以我们使用到了 优化方法 Optimization Function

    所以整个思想就变成了如下

        不断通过损失函数计算目前a、b的模型的优劣,再通过优化算法更新a、b,重复一定次数

 

损失函数

    在线性回归中,我们经常用方差作为损失函数,使得方差尽可能最小

    损失函数作为一个评判目前模型的优劣性,还有很多不同的评判标准,对于不同的实际问题也会有不同的计算损失的方法。

    我们下面用到损失函数为:

     yˆ 为当前a、b值下的x对应的值,y为原本给出的值

 

优化方法

    其实机器学习的优化方法可以看成是去算损失的方向,即我们现在在分析的这个问题,斜率变大了,但我们计算的损失反而增大了,这就说明斜率目前变化的这个方向不对,也就是应该改成斜率减小。需要说明的一点是,我们在进行优化时,变化量是较小的,呈现小幅度改变,通常需要引入一个超参数α来控制,正常取值为0.01。

    优化方法的计算一般依据的是偏微分,得到损失函数的变化量,如下所示

    慢慢修改我们的a、b值,即能使我们的损失函数的值趋于最小值

    我们下面用的算法为偏微分的方法,得到损失函数的变化量


算法步骤

    详见程序注释

import matplotlib.pyplot as plt
import numpy as np

def model(a, b, x): #一元线性模型
    #a为斜率 b为截距
    return [a*i + b for i in x] #返回出当前a、b值所对应的y

def model_single(a,b): #求出模型上的两点用于划线
    return (0.9,a*0.9+b),(1.5,a*1.5+b)

def cost_function(a, b, x, y):  #损失函数
    n = 5
    #损失函数公式
    return 0.5/n * sum([np.square(y[i]-a*x[i]-b) for i in range(len(y))])

def optimize(a,b,x,y):  #优化函数
    n = 5
    alpha = 1e-1
    y_hat = model(a,b,x)
    #计算a、b变化量的优化公式
    da = (1.0/n) * sum([(y_hat[i]-y[i])*x[i] for i in range(len(y))])
    db = (1.0 / n) * sum([(y_hat[i]-y[i]) for i in range(len(y))])
    #对a、b进行变化并更新a、b值
    a = a - alpha*da
    b = b - alpha*db
    return a, b


if __name__ == '__main__':
    #原始数据
    x=[1.3854,1.2213,1.1009,1.0655,0.9503]
    y=[2.1332,2.0162,1.9138,1.8621,1.8016]
    #使a、b的初始值如下,可随意设置
    a,b=(0.1,0)
    
    #选择图表的显示某次更新时的模型情况(可修改,最大值不能大于下面循环的最大值)
    sign=[1,5,50,100,1000,10000]
    ab=[]   #存储上诉点的a、b情况
    
    #循环更新了10100次
    for i in range(10100):
        a,b=optimize(a,b,x,y)
        if i+1 in sign:
            ab.append([a,b,cost_function(a,b,x,y)])
        # print('第%d次 损失:' % i, model_single(a,b))

    #画图
    fig = plt.figure()
    for i in range(len(sign)):
        print('第%d次 损失:' % sign[i], cost_function(a, b, x, y))
        ax = fig.add_subplot(231+i)
        ax.scatter(x, y, c='r', marker='o')
        print(ab[i][0],ab[i][1])
        X,Y=model_single(ab[i][0],ab[i][1])
        print(X,Y)
        ax.plot([X[0],Y[0]],[X[1],Y[1]])
        ax.set_title('%d -> %.10f'%(sign[i],ab[i][2]))
    plt.show()

结果

     我们可以很容易看到,随着训练次数的增加,回归线越趋近于样本,损耗也越来越小。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值