机器学习-8.线性回归

Posted wyply115

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器学习-8.线性回归相关的知识,希望对你有一定的参考价值。

1. 概述

  • 定义:线性回归通过一个或多个自变量(理解为特征)与因变量(理解为目标值)之间进行建模的回归分析。其中可以为一个或多个自变量之间的线性组合(线性回归的一种)。
  • 一元线性回归:涉及到的变量只有一个。
  • 多元线性回归:涉及到的变量两个或两个以上。
  • 通用公式: h ( w ) = w 0 + w 1 x 1 + w 2 x 2 + . . . = w T x h(w)=w_0+w_1x_1+w_2x_2+... = w^Tx h(w)=w0+w1x1+w2x2+...=wTx
    其中w,x为矩阵:
    w = ( w 0 w 1 w 2 ) , x = ( 1 x 1 x 2 ) w=\\left(\\beginmatrixw_0\\\\w_1\\\\w_2\\endmatrix\\right),x=\\left(\\beginmatrix1\\\\x_1\\\\x_2\\endmatrix\\right) w=w0w1w2,x=1x1x2
  • 假设只有单特征(面积)计算目标值(房价)

    我们需要做的是找出一条线(是个迭代计算的过程),这条线和图中的点的误差最小,即损失函数最小。
  • 损失函数(就是误差的平方和):
  • 那么线性回归的目的就是:如何去求模型中的W,使得损失最小?
  • 如何寻找这个W值,有两种求解方式:
    1. 正规方程(非重点):可以直接求到损失最低的点(但特征复杂时很难求出来)
    2. 梯度下降

2. 正规方程与梯度下降

  • 正规方程API:sklearn.linear_model.LinearRegression
  • 梯度下降API:sklearn.linear_model.SGDRegressor
  • 案例:预测波士顿房价,数据集在sklearn.datasets.load_boston中获取,下面是影响房价的特征:
  • 正规方程方式:
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler

def linear():
    '''
    线性回归预测房价
    :return: None
    '''
    # 获取数据
    lb = load_boston()

    # 分割数据
    x_train, x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)

    # 标准化,这里特征值和目标值都必须进行标准化处理
    std_1 = StandardScaler()
    x_train = std_1.fit_transform(x_train)
    x_test = std_1.transform(x_test)

    std_2 = StandardScaler()
    y_train = std_2.fit_transform(y_train.reshape(-1, 1))# 转换为2维数据
    y_test = std_2.transform(y_test.reshape(-1, 1))

    # estimator预测
    # 正规方程求解方式预测结果
    lr = LinearRegression()
    lr.fit(x_train, y_train)
    print(lr.coef_) # 回归系数,即W值
    y_predict = lr.predict(x_test)
    # 由于进行标准化了,所以y_predict需要转回来
    y_predict = std_2.inverse_transform(y_predict)

    print("测试集里每个房子的预测价格:", y_predict)

    return None

if __name__ == '__main__':
    linear()

输出结果部分截图:

  • 梯度下降方式:
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.linear_model import  SGDRegressor
from sklearn.preprocessing import StandardScaler

def linear():
    '''
    线性回归预测房价
    :return: None
    '''
    # 获取数据
    lb = load_boston()

    # 分割数据
    x_train, x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)

    # 标准化,这里特征值和目标值都必须进行标准化处理
    std_1 = StandardScaler()
    x_train = std_1.fit_transform(x_train)
    x_test = std_1.transform(x_test)

    std_2 = StandardScaler()
    y_train = std_2.fit_transform(y_train.reshape(-1, 1))# 转换为2维数据
    y_test = std_2.transform(y_test.reshape(-1, 1))

    # estimator预测
    # 梯度下降求解方式预测结果
    sgd = SGDRegressor()
    sgd.fit(x_train, y_train)
    print(sgd.coef_) # 回归系数,即W值
    y_predict = sgd.predict(x_test)
    # 由于进行标准化了,所以y_predict需要转回来
    y_predict = std_2.inverse_transform(y_predict)

    print("测试集里每个房子的预测价格:", y_predict)

    return None

if __name__ == '__main__':
    linear()

输出结果部分截图:

3. 回归性能评估

  • 均方误差API:sklearn.metrics.mean_squared_error
  • 以上面的案例中的梯度下降解法为基础,进行评估
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, SGDRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error

def linear():
    '''
    线性回归预测房价
    :return: None
    '''
    # 获取数据
    lb = load_boston()

    # 分割数据
    x_train, x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)

    # 标准化,这里特征值和目标值都必须进行标准化处理
    std_1 = StandardScaler()
    x_train = std_1.fit_transform(x_train)
    x_test = std_1.transform(x_test)

    std_2 = StandardScaler()
    y_train = std_2.fit_transform(y_train.reshape(-1, 1))# 转换为2维数据
    y_test = std_2.transform(y_test.reshape(-1, 1))

    # estimator预测
    # 梯度下降求解方式预测结果
    sgd = SGDRegressor()
    sgd.fit(x_train, y_train)
    #print(sgd.coef_) # 回归系数,即W值
    y_predict = sgd.predict(x_test)
    # 由于进行标准化了,所以y_predict需要转回来
    y_predict = std_2.inverse_transform(y_predict)
    #print("测试集里每个房子的预测价格:", y_predict)

    # 均方误差进行性能评估
    mse = mean_squared_error(std_2.inverse_transform(y_test),y_predict)
    print("均方误差为:", mse)

    return None

if __name__ == '__main__':
    linear()

输出结果:均方误差为: 29.37517305937515

4. 正规方程与梯度下降对比

5. 过拟合与欠拟合

  • 问题:训练数据训练的很好啊,误差也不大,为什么在测试集上面有问题呢?
  • 欠拟合:一个假设在训练数据上不能获得很好的拟合,但是在训练数据以外的数据集上也不能很好的拟合数据,此时认为这个假设出现了欠拟合现象。(模型过于简单
    下图所示,机器学习到的天鹅特征太少,导致区分标准太粗糙,不能准确识别出天鹅。
  • 过拟合:一个假设在训练数据上能够获得比其他假设更好的拟合,但是在训练数据外的数据集上却不能很好的拟合数据,此时认为这个假设出现了过拟合现象。(模型过于复杂
  • 再比如下图所示,更直观的看出欠拟合和过拟合的情况。
  • 欠拟合的原因:学到的数据的特征过少。
  • 欠拟合解决办法:增加数据的特征数量。
  • 过拟合原因:原始特征过多,存在一些嘈杂特征,模型过于复杂是因为模型尝试去兼顾各个测试数据点。
  • 过拟合解决办法
  1. 进行特征选择,消除关联性大的特征(很难做)
  2. 交叉验证(让所有数据都有过训练)
  3. L2正则化
  • 正则化解决过拟合的思想:不断尝试减少高次项特征的权重,趋近于0。
  • L2正则化作用:可以使得W的每个元素都很小,都接近于0。
  • 优点:越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象。

6. Ridge岭回归(带有正则化的线性回归)解决过拟合

  • API:sklearn.linear_model.Ridge

    alpha取值,根据经验通常情况下会取:0到1之间的小数,或者1-10之间的整数。
    官网给出的正则化力度和权重之间的关系图:正则化力度越大,权重越来越趋近于0(不会等于0)
  • 案例:同上面的波士顿房价一样。
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error

def linear():
    '''
    线性回归预测房价
    :return: None
    '''
    # 获取数据
    lb = load_boston()

    # 分割数据
    x_train, x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)

    # 标准化,这里特征值和目标值都必须进行标准化处理
    std_1 = StandardScaler()
    x_train = std_1.fit_transform(x_train)
    x_test = std_1.transform(x_test)

    std_2 = StandardScaler()
    y_train = std_2.fit_transform(y_train.reshape(-1, 1))# 转换为2维数据
    y_test = std_2.transform(y_test.reshape(-1, 1))

    # 岭回归进行房价预测
    rd = Ridge(alpha=1.0) #alpha为超参数,可通过网格搜索找到更合适的值
    rd.fit(x_train, y_train)
    #print(rd.coef_)  # 回归系数,即W值
    y_predict = rd.predict(x_test)
    # 由于进行标准化了,所以y_predict需要转回来
    y_predict = std_2.inverse_transform(y_predict)
    #print("测试集里每个房子的预测价格:", y_predict)

    # 均方误差进行性能评估
    mse = mean_squared_error(std_2.inverse_transform(y_test), y_predict)
    print("均方误差为:", mse)

    return None

if __name__ == '__main__':
    linear()

输出:均方误差为: 33.48485484981214

  • 线性回归LinearRegression与Ridge对比:
  • 岭回归得到的回归系数更符合实际,更可靠。另外,能让估计参数的波动范围变小,变的更稳定。在存在病态数据偏多的研究中有较大的实用价值。

以上是关于机器学习-8.线性回归的主要内容,如果未能解决你的问题,请参考以下文章

机器学习-8.线性回归

机器学习基础概念笔记

机器学习概念

线性回归系数与决策树特征重要性之间的关系

机器学习

机器学习算法:线性回归API详细介绍