• 机器学习3- 一元线性回归+Python实现


    1. 线性模型

    给定 (d) 个属性描述的示例 (oldsymbol{x} = (x_1; x_2; ...; x_d)),其中 (x_i)(oldsymbol{x}) 在第 (i) 个属性上的取值,线性模型linear model)试图学得一个通过属性的线性组合来进行预测的函数,即:

    [f(oldsymbol{x}) = w_1x_1 + w_2x_2 + ... + w_dx_d +b ag{1.1} ]

    使用向量形式为:

    [f(oldsymbol{x}) = oldsymbol{w}^Toldsymbol{x}+b ag{1.2} ]

    其中 (oldsymbol{w} = (w_1;w_2;...;w_d)),表达了各属性在预测中的重要性。

    2. 线性回归

    给定数据集 (D = lbrace(oldsymbol{x}_1,{y}_1), (oldsymbol{x}_2,{y}_2), ..., (oldsymbol{x}_m,{y}_m) brace),其中 (oldsymbol{x}_i = (x_{i1}; x_{i2}; ...; x_{id}))(y_i in mathbb{R})线性回归linear regression)试图学得一个能尽可能准确地预测真实输出标记的线性模型,即:

    [f(oldsymbol{x}_i) = oldsymbol{w}^Toldsymbol{x}_i+b ext{,使得} f(oldsymbol{x}_i) simeq y_i ag{2.1} ]

    2.1 一元线性回归

    先只考虑输入属性只有一个的情况,(D = lbrace({x}_1,{y}_1), ({x}_2,{y}_2), ..., ({x}_m,{y}_m) brace)(x_i in mathbb{R})。对离散属性,若属性值存在order)关系,可通过连续化将其转化为连续值。

    如”高度“属性的取值“高”、“中”、“低”,可转化为({1.0, 0.5, 0.0})

    若不存在序关系,则假定有 (k) 种可能的属性值,将其转化为 (k) 维向量。

    如“瓜类”属性的取值有“冬瓜”、“西瓜”、“南瓜”,可转化为 ((0,0,1),(0,1,0),(1,0,0))

    线性回归试图学得:

    [f(x_i) = wx_i+b ext{,使得}f(x_i)simeq y_i ag{2.2} ]

    为使 (f(x_i)simeq y_i),即:使 (f(x))(y) 之间的差别最小化。
    考虑回归问题的常用性能度量——均方误差(亦称平方损失(square loss)),即让均方误差最小化:

    [egin{aligned} (w^*,b^*) = underset{(w,b)}{arg min}sum_{i=1}^m(f(x_i)-y_i)^2 \ = underset{(w,b)}{arg min}sum_{i=1}^m(y_i-wx_i-b)^2 end{aligned} ag{2.3} ]

    (w^*,b^*) 表示 (w)(b) 的解。
    均方误差对应了欧几里得距离,简称欧氏距离(Euclidean distance)。
    基于均方误差最小化来进行模型求解的方法称为最小二乘法least square method)。在线性回归中,就是试图找到一条直线,使得所有样本到直线上的欧氏距离之和最小。

    下面需要求解 (w)(b) 使得 (E_{(w,b)} = sumlimits_{i=1}^m(y_i-wx_i-b)^2) 最小化,该求解过程称为线性回归模型的最小二乘参数估计parameter estimation)。

    (E_{(w,b)}) 为关于 (w)(b) 的凸函数,当它关于 (w)(b) 的导数均为 (0) 时,得到 (w)(b) 的最优解。将 (E_{(w,b)}) 分别对 (w)(b) 求导数得:

    [frac{partial{E_{(w,b)}}}{partial(w)} = 2Big(wsum_{i=1}^m x_i^2 - sum_{i=1}^m (y_i-b)x_iBig) ag{2.4} ]

    [frac{partial{E_{(w,b)}}}{partial(b)} = 2Big(mb - sum_{i=1}^m (y_i-wx_i)Big) ag{2.5} ]

    令式子 (2.4) 和 (2.5) 为 (0) 得到 (w)(b) 的最优解的闭式(closed-form)解:

    [w = frac{sum_limits{i=1}^m y_i(x_i-overline{x})}{sumlimits_{i=1}^m x_i^2 - frac{1}{m}Big(sumlimits_{i=1}^m x_iBig)^2} ag{2.6} ]

    [b = frac{1}{m}sum_{i=1}^m (y_i-wx_i) ag{2.7} ]

    其中 (overline{x} = frac{1}{m}sumlimits_{i=1}^m x_i)(x) 的均值。

    其他解法:

    [方差 var(x) = frac{sumlimits_{i=1}^m(x_i-ar{x})^2}{m-1} ]

    [协方差 cov(x,y) = frac{sum_limits{i=1}^m (x_i-overline{x})(y_i-overline{y})}{n-1} ]

    [w = frac{cov(x,y)}{var(x)} = frac{sum_limits{i=1}^m (x_i-overline{x})(y_i-overline{y})}{sumlimits_{i=1}^m (x_i-overline{x})^2} ]

    [b = ar{y} - war{x} ]

    3. 一元线性回归的Python实现

    现有如下训练数据,我们希望通过分析披萨的直径与价格的线性关系,来预测任一直径的披萨的价格。

    其中 Diameter 为披萨直径,单位为“英寸”;Price 为披萨价格,单位为“美元”。

    3.1 使用 stikit-learn

    3.1.1 导入必要模块

    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    from sklearn.linear_model import LinearRegression
    

    3.1.2 使用 Pandas 加载数据

    pizza = pd.read_csv("pizza.csv", index_col='Id')
    pizza.head()  # 查看数据集的前5行
    

    3.1.3 快速查看数据

    我们可以使用 matplotlib 画出数据的散点图,x 轴表示披萨直径,y 轴表示披萨价格。

    def runplt():
        plt.figure()
        plt.title("Pizza price plotted against diameter")
        plt.xlabel('Diameter')
        plt.ylabel('Price')
        plt.grid(True)
        plt.xlim(0, 25)
        plt.ylim(0, 25)
        return plt
    
    dia = pizza.loc[:,'Diameter'].values
    price = pizza.loc[:,'Price'].values
    print(dia)
    print(price)
    plt = runplt()
    plt.plot(dia, price, 'k.')
    plt.show()
    
    [ 6  8 10 14 18]
    [ 7.   9.  13.  17.5 18. ]
    

    3.1.4 使用 stlearn 创建模型

    model = LinearRegression()  # 创建模型
    X = dia.reshape((-1,1))
    y = price
    model.fit(X, y)  # 拟合
    
    X2 = [[0], [25]] # 取两个预测值
    y2 = model.predict(X2)  # 进行预测
    print(y2)  # 查看预测值
    
    plt = runplt()
    plt.plot(dia, price, 'k.')
    plt.plot(X2, y2, 'g-')  # 画出拟合曲线
    plt.show()
    
    [ 1.96551724 26.37284483]
    

    这里 fit()方法学得了一元线性回归模型 (f(x) = wx+b),这里 (x) 指披萨的直径,(f(x)) 为预测的披萨的价格。

    fit() 的第一个参数 X 为 shape(样本个数,属性个数) 的数组或矩阵类型的参数,代表输入空间;
    第二个参数 y 为 shape(样本个数,) 的数组类型的参数,代表输出空间。

    3.1.5 模型评估

    成本函数(cost function)也叫损失函数(lost function),用来定义模型与观测值的误差。

    模型预测的价格和训练集数据的差异称为训练误差training error)也称残差residuals)。

    plt = runplt()
    plt.plot(dia, price, 'k.')
    plt.plot(X2, y2, 'g-')
    
    # 画出残差
    yr = model.predict(X)
    for index, x in enumerate(X):
        plt.plot([x, x], [y[index], yr[index]], 'r-')
        
    plt.show()
    

    根据最小二乘法,要得到更高的性能,就是让均方误差最小化,而均方误差就是残差平方和的平均值。

    print("均方误差为: %.2f" % np.mean((model.predict(X)-y) ** 2))
    
    均方误差为: 1.75
    

    3.2 手动实现

    3.2.1 计算 w 和 b

    (w)(b) 的最优解的闭式(closed-form)解为:

    [w = frac{sum_limits{i=1}^m y_i(x_i-overline{x})}{sumlimits_{i=1}^m x_i^2 - frac{1}{m}Big(sumlimits_{i=1}^m x_iBig)^2} ag{2.6} ]

    [b = frac{1}{m}sum_{i=1}^m (y_i-wx_i) ag{2.7} ]

    其中 (overline{x} = frac{1}{m}sumlimits_{i=1}^m x_i)(x) 的均值。

    [方差 var(x) = frac{sumlimits_{i=1}^m(x_i-ar{x})^2}{m-1} ]

    [协方差 cov(x,y) = frac{sum_limits{i=1}^m (x_i-overline{x})(y_i-overline{y})}{n-1} ]

    [w = frac{cov(x,y)}{var(x)} = frac{sum_limits{i=1}^m (x_i-overline{x})(y_i-overline{y})}{sumlimits_{i=1}^m (x_i-overline{x})^2} ]

    [b = ar{y} - war{x} ]

    下面使用 Python 计算 (w)(b) 的值:

    # 法一:
    # w = np.sum(price * (dia - np.mean(dia))) / (np.sum(dia**2) - (1/dia.size) * (np.sum(dia))**2)
    # b = (1 / dia.size) * np.sum(price - w * dia)
    
    #法二:
    variance = np.var(dia, ddof=1)  # 计算方差,doff为贝塞尔(无偏估计)校正系数
    covariance = np.cov(dia, price)[0][1]  # 计算协方差
    w = covariance / variance
    b = np.mean(price) - w * np.mean(dia)
    
    print("w = %f
    b = %f" % (w, b))
    
    y_pred = w * dia + b
    
    plt = runplt()
    plt.plot(dia, price, 'k.')  # 样本点
    plt.plot(dia, y_pred, 'b-')  # 手动求出的线性回归模型
    plt.plot(X2, y2, 'g-.')  # 使用LinearRegression.fit()求出的模型
    plt.show()
    
    w = 0.976293
    b = 1.965517
    

    可以看到两条直线重合,我们求出的回归模型与使用库求出的回归模型相同。

    3.2.2 功能封装

    将上述代码封装成类:

    class LinearRegression:
        """
        拟合一元线性回归模型
    
        Parameters
        ----------
        x : shape 为(样本个数,)的 numpy.array
            只有一个属性的数据集
    
        y : shape 为(样本个数,)的 numpy.array
            标记空间
    
        Returns
        -------
        self : 返回 self 的实例.
        """
        def __init__(self):
            self.w = None
            self.b = None
    
        def fit(self, x, y):
            variance = np.var(x, ddof=1)  # 计算方差,doff为贝塞尔(无偏估计)校正系数
            covariance = np.cov(x, y)[0][1]  # 计算协方差
            self.w = covariance / variance
            self.b = np.mean(y) - w * np.mean(x)
    #         self.w = np.sum(y * (x - np.mean(x))) / (np.sum(x**2) - (1/x.size) * (np.sum(x))**2)
    #         self.b = (1 / x.size) * np.sum(y - self.w * x)
            return self
    
        def predict(self, x):
            """
            使用该线性模型进行预测
    
            Parameters
            ----------
            x : 数值 或 shape 为(样本个数,)的 numpy.array
                属性值
    
            Returns
            -------
            C : 返回预测值
            """
            return self.w * x + self.b
    

    使用:

    # 创建并拟合模型
    model = LinearRegression()
    model.fit(dia, price)
    
    x2 = np.array([0, 25])  # 取两个预测值
    y2 = model.predict(x2)  # 进行预测
    print(y2)  # 查看预测值
    
    runplt()
    plt.plot(dia, price, 'b.')
    plt.plot(x2, y2, 'y-')  # 画出拟合
    plt.show()
    
    [ 1.96551724 26.37284483]
    


    此文原创禁止转载,转载文章请联系博主并注明来源和出处,谢谢!
    作者: Raina_RLN https://www.cnblogs.com/raina/

  • 相关阅读:
    关于transition中嵌套keep-alive的问题解决
    vue-cli中使用全局less变量
    git 移除远程仓库关联
    当浏览器窗口大小发生变化时,重新绘制JsPlumb中的线条、端点
    事件循环详解
    React + Sass
    使用OpenSSL自签发SSL证书,支持chrome识别
    英汉翻译技巧之直译与意译、正说与反说、顺序法和逆序法
    英汉翻译技巧之拆句
    英语翻译时句子成分的转换
  • 原文地址:https://www.cnblogs.com/raina/p/12605768.html
Copyright © 2020-2023  润新知