原创

机器学习手册07---线性回归


线性回归是机器学习中最简单的有监督学习算法之一,事实上,由于它非常简单,有时,甚至不会认为是机器学习的一部分。无论你是否相信,当目标向量是数值(如:房价)时,线性回归及其扩展一直是常见且有效的预测方法。

1.什么是线性回归

【解决的问题】:对大量的观测数据进行处理,从而得到比较符合事物内部规律的数学表达式。也就是说寻找到数据与数据之间的规律所在,从而就可以模拟出结果,也就是对结果进行预测。解决的就是通过已知的数据得到未知的结果。例如:对房价的预测、判断信用评价、电影票房预估等。

【线性】:两个变量之间的关系是一次函数关系,指广义线性,也就是数据与数据之间的关系。

【非线性】:两个变量之间的关系不是一次函数关系的。

【回归】:人们在测量事物的时候因为客观条件所限,求得的都是测量值,而不是事物真实的值,为了能够得到真实值,无限次的进行测量,最后通过这些测量数据计算回归到真实值。

avatar 【说明】:仅仅通过这些点我们很难预测当x=x0时,y的值是多少,所以,我们通过找到一条直线来描述这些点的趋势或者分布。通俗说就是用一个函数去逼近这个真实值。

2.损失函数

线性回归中,损失函数用均方误差表示,即最小二乘法。我们需要找出一条线去拟合它,那么我先假设这个线的方程,然后把数据点代入假设的方程得到观测值,求使得实际值与观测值相减的平方和最小的参数。 avatar

avatar

【说明】:红线为理想回归,绿线误差比较大,需要通过计算误差来进行微调。

3.优化算法

3.1正规方程

avatar

【说明】:X为特征值矩阵,y为目标值矩阵,直到求到最好的结果。但是,对于特征较多复杂时,求解速度太慢且得不到结果。

avatar

3.2梯度下降

在一元函数中叫做求导,在多元函数中就叫做求梯度。梯度下降是一个最优化算法,通俗的来讲也就是沿着梯度下降的方向来求出一个函数的极小值。比如一元函数中,加速度减少的方向,总会找到一个点使速度达到最小。通常情况下,数据不可能完全符合我们的要求,所以很难用矩阵去求解,所以机器学习就应该用学习的方法,因此我们采用梯度下降,不断迭代,沿着梯度下降的方向来移动,求出极小值。梯度下降法包括批量梯度下降法和随机梯度下降法(SGD)以及二者的结合mini批量下降法(通常与SGD认为是同一种,常用于深度学习中)。

avatar avatar

【说明】:梯度对于单变量---切线,对于多变量---向量。参数步长太小---下山太慢,步长太长---容易跳过极小值点。

3.3正规方程与梯度下降对比
梯度下降正规方程
需要选择学习率不需要
需要迭代求解一次性算出
特征数量较大时使用需要计算方程,时间复杂度高
3.4算法选择

【小规模数据】:正规方程LinearRegression(不能解决拟合问题)、岭回归

【大规模数据】:梯度下降法SGDRegressor

4.欠拟合和过拟合

【过拟合】:模型过于复杂(原始特征过多,存在一些嘈杂特征,导致模型尝试去兼顾各个测试数据点),在训练集上能获得更好的拟合,但是在测试集上却不能很好地拟合数据。解决方法:(1)重新清洗数据(2)正则化(3)减少特征维度,防止维度灾难。

【欠拟合】:模型过于简单(数据的特征过少),在训练集上不能获得更好的拟合,但是在测试集上却能很好地拟合数据。解决方法:(1)添加其他特征(2)添加多项式特征 avatar

5.正则化

5.1为什么要用正则化

在解决回归过拟合中,我们选择正则化。但是对于其他机器学习算法入分类算法来说,也会出现这样的问题,除了一些算法本身作用外(决策树、神经网络),我们更多的也是取自己做特征选择,包括之前说的删除、合并一些特征等等。 avatar 在学习过程中,数据提供的特征有些影响模型复杂度或这个特征的异常点较多,所以算法在学习的时候尽量减少这个特征的影响(甚至删除这个特征),这就是正则化。

【说明】:调整的时候,算法并不知道某个特征的影响,而是去微调参数得出最优的结果。

5.2正则化的类别

【L1正则化】:可以使得其中一些w的值直接为0(如:x3与x4前面的系数直接为0),删除这个特征的影响。例如:岭回归Ridge

【L2正则化】:可以使得其中一些w的值很小,接近于0(如:x3与x4前面的系数变小),消弱这个特征的影响。例如:套索回归LASSO

6.线性回归API初步使用

6.1拟合一条直线

【手动创建数据】:

from sklearn.linear_model import LinearRegression

# 1.获取数据
x = [[80, 86],
     [82, 80],
     [85, 78],
     [90, 90],
     [86, 82],
     [82, 90],
     [78, 80],
     [92, 94]]
y = [84.2, 80.6, 80.1, 90, 83.2, 87.6, 79.4, 93.4]

# 2.模型训练
# 2.1实例化一个估计器
estimator = LinearRegression()

# 2.2使用fit方法进行训练
estimator.fit(x, y)
线性回归的系数是:
 [0.3 0.7]
输出预测结果:
 [86.]

【利用波士顿房价数据集】:

from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_boston

# 加载只有两个特征的数据集
boston = load_boston()          # 波士顿房价数据集:共有506个样本
features = boston.data[ :, 0:2] # 特征(2个特征)
target = boston.target          # 目标值:单位是千美元

# 查看数据集大小
print('特征大小:', features.shape)
print('目标值大小:', target.size)

# 创建线性回归对象
regression = LinearRegression()
# 拟合线性回归模型
model = regression.fit(features, target)
特征大小: (506, 2)
目标值大小: 506
# 查看截距
print('截距:', model.intercept_)
# 查看特征权重
print('特征的权重:', model.coef_)
截距: 22.485628113468223
特征的权重: [-0.35207832  0.11610909]
# 查看目标值
print('第一个样本的目标值(单位:美元)', target[0] * 1000)
print('第一个样本的预测值(单位:美元)', model.predict(features)[0] * 1000)
print('当每个居民的犯罪次数增加一次后,对房价的影响:', model.coef_[0]*1000)
第一个样本的目标值(单位:美元) 24000.0
第一个样本的预测值(单位:美元) 24573.366631705547
当每个居民的犯罪次数增加一次后,对房价的影响: -352.0783156402677

【说明】:线性回归常见属性:参数intercept_截距、参数coef_权重。

6.2处理特征之间的影响

一个特征对目标值的影响取决于另一个特征,现在要处理两个特征间的影响。利用PolynomialFeatures创建多项式特征,交互特征指相互作用的一组特征的乘积作为新特征加入模型。

from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_boston
from sklearn.preprocessing import PolynomialFeatures
import numpy as np

# 加载只有两个特征的数据集
boston = load_boston()          # 波士顿房价数据集:共有506个样本
features = boston.data[ :, 0:2] # 特征(2个特征)
target = boston.target          # 目标值:单位是千美元

# 创建交互特征
interaction = PolynomialFeatures(degree=3, include_bias=False, interaction_only=True)
features_interaction = interaction.fit_transform(features)

# 创建线性回归对象
regression0 = LinearRegression()
regression1 = LinearRegression()

# 拟合线性回归模型
model0 = regression0.fit(features, target)
model1 = regression1.fit(features_interaction, target)

# 查看两个模型的区别
print('未经过交互特征的第一个样本特征值:', features[0])
print('未经过交互特征的特征的权重:', model0.coef_)
print('-----------------------------------------------------------')
print('经过交互特征后的第一个样本特征值:', features_interaction[0])
print('经过交互特征后的特征的权重:', model1.coef_)

print('-----------------------------------------------------------')
# 利用numpy检查:交互特征是否正确(用样本0来进行检验)
interaction_term = np.multiply(features[:, 0], features[:, 1])
print('利用numpy计算的交互特征值(样本0):', interaction_term[0])
未经过交互特征的第一个样本特征值: [6.32e-03 1.80e+01]   //x1,x2
未经过交互特征的特征的权重: [-0.35207832  0.11610909]
-----------------------------------------------------------
经过交互特征后的第一个样本特征值: [6.3200e-03 1.8000e+01 1.1376e-01] //x1,x2,x1x2
经过交互特征后的特征的权重: [-0.33715159  0.08155747  0.80662   ]
-----------------------------------------------------------
利用numpy计算的交互特征值(样本0): 0.11376  //x1x2

【说明】:PolynomialFeatures创建交互特征的参数:参数interaction_only=True只返回交互特征;参数include_bias=False阻止加入偏差;参数degree=3确定最多用几个特征来创建交互特征。

6.3拟合非线性关系
from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_boston
from sklearn.preprocessing import PolynomialFeatures

# 加载只有1个特征的数据集
boston = load_boston()          # 波士顿房价数据集:共有506个样本
features = boston.data[ :, 0:1] # 特征(1个特征)
target = boston.target          # 目标值:单位是千美元

# 创建交互特征
polynomial = PolynomialFeatures(degree=3, include_bias=False)
features_polynomial = polynomial.fit_transform(features)

# 创建线性回归对象
regression1 = LinearRegression()

# 拟合线性回归模型
model1 = regression1.fit(features_polynomial, target)

# 查看模型
print('本次非线性拟合,只引用了1个特征')
print('非线性拟合第一个样本的特征值(x、x^2、x^3):', features_polynomial[0])
print('非线性拟合的特征的权重(x、x^2、x^3):', model1.coef_)
本次非线性拟合,只引用了1个特征
非线性拟合第一个样本的特征值(x、x^2、x^3): [6.32000000e-03 3.99424000e-05 2.52435968e-07]
非线性拟合的特征的权重(x、x^2、x^3): [-1.13640072e+00  2.37848254e-02 -1.48872090e-04]

【说明】:PolynomialFeatures进行非线性模型两个重要参数:参数degree确定多项式特征的最高阶数;参数include_bias=False阻止加入偏差。

6.4通过正则化减少方差
from sklearn.linear_model import Ridge
from sklearn.datasets import load_boston
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import RidgeCV

# 加载数据集
boston = load_boston()          # 波士顿房价数据集:共有506个样本
features = boston.data          # 特征(全部)13个特征
target = boston.target          # 目标值:单位是千美元

# 特征标准化
scaler = StandardScaler()
features_standardized = scaler.fit_transform(features)

# 创建一个包含指定alpha值的“岭回归”
regression1 = Ridge(alpha=0.5)

# 拟合“岭回归”、线性回归模型
model = regression1.fit(features_standardized, target)

# 查看模型
print('当alpha=0.5时,岭回归后的13个特征权重:', model.coef_)
print('-------------------------------------------------------------------')

# 创建一组alpha值的RidgeCV对象
# 自动选择最佳alpha的值
regr_cv = RidgeCV(alphas=[0.1, 1.0, 10.0])
model_cv = regr_cv.fit(features_standardized, target)
# 最佳alpha值
best_alpha = model_cv.alpha_
print('当alpha=' + str(best_alpha) + '时,岭回归后的13个特征权重:', model_cv.coef_)
当alpha=0.5时,岭回归后的13个特征权重: [-0.92396151  1.07393055  0.12895159  0.68346136 -2.0427575   2.67854971
  0.01627328 -3.09063352  2.62636926 -2.04312573 -2.05646414  0.8490591
 -3.73711409]
-------------------------------------------------------------------
当alpha=1.0时,岭回归后的13个特征权重: [-0.91987132  1.06646104  0.11738487  0.68512693 -2.02901013  2.68275376
  0.01315848 -3.07733968  2.59153764 -2.0105579  -2.05238455  0.84884839
 -3.73066646]
6.5使用套索回归减少特征

减少特征数量来简化线性回归模型。

from sklearn.linear_model import Lasso
from sklearn.datasets import load_boston
from sklearn.preprocessing import StandardScaler

# 加载只有1个特征的数据集
boston = load_boston()          # 波士顿房价数据集:共有506个样本
features = boston.data          # 特征(全部)13个特征
target = boston.target          # 目标值:单位是千美元

# 特征标准化
scaler = StandardScaler()
features_standardized = scaler.fit_transform(features)

# 创建一个包含指定alpha值的“套索回归”
regression = Lasso(alpha=0.5)

# 拟合“岭回归”、线性回归模型
model = regression.fit(features_standardized, target)

# 查看模型
print('当alpha=0.5时,套索回归后的13个特征权重:')
print(model.coef_)

regression = Lasso(alpha=10)
model = regression.fit(features_standardized, target)
print('当alpha=10时,套索回归后的13个特征权重:')
print(model.coef_)
当alpha=0.5时,套索回归后的13个特征权重:
[-0.11526463  0.         -0.          0.39707879 -0.          2.97425861
 -0.         -0.17056942 -0.         -0.         -1.59844856  0.54313871
 -3.66614361]
 
当alpha=10时,套索回归后的13个特征权重:
[-0.  0. -0.  0. -0.  0. -0.  0. -0. -0. -0.  0. -0.]

7.案例分析波士顿房价预测01---线性回归:正规方程

from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

def liner_model1():
    """
    线性回归:正规方程
    """
    # 1.获取数据
    boston = load_boston()
    print("特征名称:\n", boston.feature_names)

    # 2.数据基本处理
    # 2.1分割数据
    x_train, x_test, y_train, y_test = train_test_split(boston.data, boston.target, test_size=0.2, random_state=20)

    # 3.特征工程---标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.fit_transform(x_test)

    # 4.机器学习---线性回归
    estimator = LinearRegression()
    estimator.fit(x_train, y_train)

    # print("这个模型的偏置是:\n", estimator.intercept_)
    print("这个模型的系数是:\n", estimator.coef_)

    # 5.模型评估
    # 5.1预测值
    y_pre = estimator.predict(x_test)
    # print("预测值是:\n", y_pre)
    # 5.2均方误差
    ret = mean_squared_error(y_test, y_pre)
    print("均方误差是:\n", ret)

if __name__ == '__main__':
    liner_model1()
特征名称:
 ['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
 'B' 'LSTAT']

这个模型的系数是:
 [-0.56858806  0.95897501  0.32876157  0.77313673 -2.44775239  2.6786234
  0.54009014 -2.88042407  2.36720216 -1.89865586 -1.95557073  0.85129913
 -4.14413021]

均方误差是:
 18.327750834649247

8.案例分析波士顿房价预测02---线性回归:梯度下降法

def liner_model2():
    """
    线性回归:梯度下降法
    """
    # 1.获取数据
    boston = load_boston()

    # 2.数据基本处理
    # 2.1分割数据
    x_train, x_test, y_train, y_test = train_test_split(boston.data, boston.target, test_size=0.2)

    # 3.特征工程---标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.fit_transform(x_test)

    # 4.机器学习---线性回归
    # estimator = SGDRegressor(max_iter=1000, learning_rate='constant', eta0=0.001)  eta0学习率
    estimator = SGDRegressor(max_iter=1000)
    estimator.fit(x_train, y_train)

    # print("这个模型的偏置是:\n", estimator.intercept_)
    print("这个模型的系数是:\n", estimator.coef_)

    # 5.模型评估
    # 5.1预测值
    y_pre = estimator.predict(x_test)
    # print("预测值是:\n", y_pre)
    # 5.2均方误差
    ret = mean_squared_error(y_test, y_pre)
    print("均方误差是:\n", ret)
这个模型的系数是:
 [-1.1248626   0.9858017  -0.08024169  0.58921981 -2.0850025   2.7970438
 -0.2308236  -3.09911418  2.54794524 -1.83096886 -1.93958323  0.72334658
 -3.24277061]

均方误差是:
 23.183941176837116

9.案例分析波士顿房价预测03---线性回归:岭回归

def liner_model3():
    """
    线性回归:岭回归
    """
    # 1.获取数据
    boston = load_boston()

    # 2.数据基本处理
    # 2.1分割数据
    x_train, x_test, y_train, y_test = train_test_split(boston.data, boston.target, test_size=0.2)

    # 3.特征工程---标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.fit_transform(x_test)

    # 4.机器学习---线性回归
    estimator = Ridge(alpha=1.0)
    # estimator = RidgeCV(alphas=(0.001, 0.01, 0.1, 1, 10, 100))  # alphas:正则化   正则化力度越大,权重系数越小;正则化力度越小,权重系数越大
    estimator.fit(x_train, y_train)

    # print("这个模型的偏置是:\n", estimator.intercept_)
    print("这个模型的系数是:\n", estimator.coef_)

    # 5.模型评估
    # 5.1预测值
    y_pre = estimator.predict(x_test)
    # print("预测值是:\n", y_pre)
    # 5.2均方误差
    ret = mean_squared_error(y_test, y_pre)
    print("均方误差是:\n", ret)
这个模型的系数是:
 [-0.85299192  0.93361371 -0.12957985  0.56174811 -2.28283349  2.31927112
  0.44093982 -3.0613485   3.14332775 -2.32972398 -2.39777892  0.87174584
 -4.08128534]

均方误差是:
 22.287083565494996
Python
机器学习
  • 作者:李延松(联系作者)
  • 发表时间:2020-07-24 20:56
  • 版本声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
  • 公众号转载:请在文末添加作者公众号二维码

评论

留言