zoukankan      html  css  js  c++  java
  • 线性回归(最小二乘法和梯度下降)

    一、定义与公式

    线性回归(Linear regression)是一种线性模型,利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式。

    • 具体来说,利用线性回归模型,可以从一组输入变量x的线性组合中,计算输出变量y。
    • 只有一个自变量的情况称为单变量回归,大于一个自变量情况的叫做多元回归

    那么怎么理解呢?我们来看几个例子

    • 期末成绩:0.7×考试成绩+0.3×平时成绩
    • 房子价格 = 0.02×中心区域的距离 + 0.04×城市一氧化氮浓度 + (-0.12×自住房平均房价) + 0.254×城镇犯罪率

    上面两个例子,我们看到特征值与目标值之间建立的一个关系,这个可以理解为回归方程

    多元线性回归

    如果有两个或两个以上的自变量,这样的线性回归分析就成为多元线性回归。

    实际问题中,一个现象往往是受到多个因素影响的,所以多元线性回归比一元线性回归的实际应用更广。

    二、最小二乘法

    线性回归模型的关键就是确定w和b。w和b学得之后,模型也就确定了。

    那么该如何确定w和b?

    假设输入特征只有一个。

    使f(x)与y之间的均方误差最小

     试图找到一条直线,使得所有样本到直线上的欧式距离之和最小,这就是最小二乘法。

    基于均方误差最小化来进行模型求解的方法称为“最小二乘法”(least square method)。

    它的主要思想就是选择未知参数,使得理论值与观测值只差的平方和达到最小。

    2.1 公式推导

    使得

    最小化的过程,称为线性回归模型的“最小二乘参数估计”,分别对w和b求偏导。

    推导过程参见南瓜书:https://datawhalechina.github.io/pumpkin-book/#/chapter3/chapter3

     令偏导数都等于0

     

     

     

    2.2 代码实现

    数据集:https://files.cnblogs.com/files/wkfvawl/data.rar

    import numpy as np
    import matplotlib.pyplot as plt
    #导入数据
    # delimiter 分隔符
    points = np.genfromtxt('data.csv', delimiter=',')
    # 提取points中的两列数据,分别作为x,y
    # 每行的第一个和每行的第二个
    x = points[:, 0]
    y = points[:, 1]
    # 先定义一个求均值的函数
    def average(data):
        sum = 0
        num = len(data)
        for i in range(num):
            sum += data[i]
        return sum/num
    
    # 定义核心拟合函数
    def fit(points):   
        M = len(points)
        #x均值    
        x_bar = average(points[:, 0])
        #求w     
        sum_yx = 0
        sum_x2 = 0
        sum_delta = 0
        for i in range(M):
            x = points[i, 0]
            y = points[i, 1]
            sum_yx += y * ( x - x_bar )
            sum_x2 += x ** 2
        # 根据公式计算w
        w = sum_yx / ( sum_x2 - M * (x_bar**2) )
        #求b
        for i in range(M):
            x = points[i, 0]
            y = points[i, 1]
            sum_delta += ( y - w * x )
        b = sum_delta / M
        return w, b
    
    # scatter散点图
    plt.scatter(x, y)
    # 针对每一个x,计算出预测的y值
    pred_y = w * x + b
    # plot线型图
    plt.plot(x, pred_y, c='r')
    plt.show()

    三、梯度下降

    最小二乘法在面对大量数据时,太慢了,可以使用凸优化中最常见的梯度下降法进行优化。

    梯度下降是一个用来求函数最小值的算法,我们将使用梯度下降算法来求出损失函数(0, 1) 的最小值。
    梯度下降背后的思想是:开始时我们随机选择一个参数的组合(0, 1, . . . . . . , ),计算代价函数,然后我们寻找下一个能让代价函数值下降最多的参数组合。我们持续这么做直到到到一个局部最小值(local minimum),因为我们并没有尝试完所有的参数组合,所以不能确定我们得到的局部最小值是否便是全局最小值(global minimum),选择不同的初始参数组合,可能会找到不同的局部最小值。

    3.1 公式推导

    一元线性回归

    在多元线性回归中

    α为学习速率,需要手动指定(超参数),α旁边的整体表示方向
    
    沿着这个函数下降的方向找,最后就能找到山谷的最低点,然后更新值

    我们可以通过α来控制步长,大不能太大也不能太小。

    在多元线性回归中,选择损失函数

    这里

     

    梯度下降算法

     

     

    3.2 代码实现

    import numpy as np
    import matplotlib.pyplot as plt
    # 模型超参数
    alpha = 0.0001
    # 初始值
    initial_w = 0
    initial_b = 0
    # 迭代次数
    num_iter = 10
    # 导入数据
    points = np.genfromtxt('data.csv', delimiter=',')
    
    # 损失函数是系数的函数,另外还要传入数据的x,y
    def compute_cost(w, b, points):
        total_cost = 0
        M = len(points)
        # 逐点计算平方损失误差,然后求平均数
        for i in range(M):
            x = points[i, 0]
            y = points[i, 1]
            total_cost += ( y - w * x - b ) ** 2
        return total_cost/M
    # 核心算法
    def grad_desc(points, initial_w, initial_b, alpha, num_iter):
        w = initial_w
        b = initial_b
        # 定义一个list保存所有的损失函数值,用来显示下降的过程
        cost_list = []
        # 迭代     
        for i in range(num_iter):
            cost_list.append( compute_cost(w, b, points) )
            w, b = step_grad_desc( w, b, alpha, points )
        # 迭代结束 获得最优w b        
        return [w, b, cost_list]
    
    def step_grad_desc( current_w, current_b, alpha, points ):
        sum_grad_w = 0
        sum_grad_b = 0
        M = len(points)
        # 对每个点,代入公式求和
        for i in range(M):
            x = points[i, 0]
            y = points[i, 1]
            h = current_w * x + current_b - y
            sum_grad_w += h * x
            sum_grad_b += h - y
        # 用公式求当前梯度
        grad_w = 2/M * sum_grad_w
        grad_b = 2/M * sum_grad_b
        # 梯度下降,更新当前的w和b
        updated_w = current_w - alpha * grad_w
        updated_b = current_b - alpha * grad_b
        return updated_w, updated_b

    测试:运行梯度下降算法计算最优的w和b

    w, b, cost_list = grad_desc( points, initial_w, initial_b, alpha, num_iter )
    
    print("w is: ", w)
    print("b is: ", b)
    
    cost = compute_cost(w, b, points)
    
    print("cost is: ", cost)
    
    plt.plot(cost_list)
    plt.show()
    w is:  1.47513229374931
    b is:  0.17505959562572973
    cost is:  112.56579741946545
    

    画出拟合曲线

    plt.scatter(x, y)
    # 针对每一个x,计算出预测的y值
    pred_y = w * x + b
    
    plt.plot(x, pred_y, c='r')
    plt.show()

    作者:王陸

    -------------------------------------------

    个性签名:罔谈彼短,靡持己长。做一个谦逊爱学的人!

    本站使用「署名 4.0 国际」创作共享协议,转载请在文章明显位置注明作者及出处。鉴于博主处于考研复习期间,有什么问题请在评论区中提出,博主尽可能当天回复,加微信好友请注明原因

  • 相关阅读:
    程序员之道——编程也是一门艺术
    Spring动态获取IoC容器中管理的Bean
    SVN使用教程之——分支、合并
    WebSphere从Windows迁移至Linux出现org.dom4j.DocumentException异常:Nested exception: prolog 中不允许有内容
    Spring动态获取IoC容器中管理的Bean
    com.microsoft.sqlserver.jdbc.SQLServerException: 将截断字符串或二进制数据
    IMP导入数据 出现ORA01691问题 解决办法
    jquery对象与Dom对象的相互转化
    json<>js
    photoshop快捷键
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/15561263.html
Copyright © 2011-2022 走看看