线性回归是机器学习中最简单的有监督学习算法之一,事实上,由于它非常简单,有时,甚至不会认为是机器学习的一部分。无论你是否相信,当目标向量是数值(如:房价)时,线性回归及其扩展一直是常见且有效的预测方法。
【解决的问题】:对大量的观测数据进行处理,从而得到比较符合事物内部规律的数学表达式。也就是说寻找到数据与数据之间的规律所在,从而就可以模拟出结果,也就是对结果进行预测。解决的就是通过已知的数据得到未知的结果。例如:对房价的预测、判断信用评价、电影票房预估等。
【线性】:两个变量之间的关系是一次函数关系,指广义线性,也就是数据与数据之间的关系。
【非线性】:两个变量之间的关系不是一次函数关系的。
【回归】:人们在测量事物的时候因为客观条件所限,求得的都是测量值,而不是事物真实的值,为了能够得到真实值,无限次的进行测量,最后通过这些测量数据计算回归到真实值。
【说明】:仅仅通过这些点我们很难预测当x=x0时,y的值是多少,所以,我们通过找到一条直线来描述这些点的趋势或者分布。通俗说就是用一个函数去逼近这个真实值。
线性回归中,损失函数用均方误差表示,即最小二乘法。我们需要找出一条线去拟合它,那么我先假设这个线的方程,然后把数据点代入假设的方程得到观测值,求使得实际值与观测值相减的平方和最小的参数。
【说明】:红线为理想回归,绿线误差比较大,需要通过计算误差来进行微调。
【说明】:X为特征值矩阵,y为目标值矩阵,直到求到最好的结果。但是,对于特征较多复杂时,求解速度太慢且得不到结果。
在一元函数中叫做求导,在多元函数中就叫做求梯度。梯度下降是一个最优化算法,通俗的来讲也就是沿着梯度下降的方向来求出一个函数的极小值。比如一元函数中,加速度减少的方向,总会找到一个点使速度达到最小。通常情况下,数据不可能完全符合我们的要求,所以很难用矩阵去求解,所以机器学习就应该用学习的方法,因此我们采用梯度下降,不断迭代,沿着梯度下降的方向来移动,求出极小值。梯度下降法包括批量梯度下降法和随机梯度下降法(SGD)以及二者的结合mini批量下降法(通常与SGD认为是同一种,常用于深度学习中)。
【说明】:梯度对于单变量---切线,对于多变量---向量。参数步长太小---下山太慢,步长太长---容易跳过极小值点。
梯度下降 | 正规方程 |
---|---|
需要选择学习率 | 不需要 |
需要迭代求解 | 一次性算出 |
特征数量较大时使用 | 需要计算方程,时间复杂度高 |
【小规模数据】:正规方程LinearRegression(不能解决拟合问题)、岭回归
【大规模数据】:梯度下降法SGDRegressor
【过拟合】:模型过于复杂(原始特征过多,存在一些嘈杂特征,导致模型尝试去兼顾各个测试数据点),在训练集上能获得更好的拟合,但是在测试集上却不能很好地拟合数据。解决方法:(1)重新清洗数据(2)正则化(3)减少特征维度,防止维度灾难。
【欠拟合】:模型过于简单(数据的特征过少),在训练集上不能获得更好的拟合,但是在测试集上却能很好地拟合数据。解决方法:(1)添加其他特征(2)添加多项式特征
在解决回归过拟合中,我们选择正则化。但是对于其他机器学习算法入分类算法来说,也会出现这样的问题,除了一些算法本身作用外(决策树、神经网络),我们更多的也是取自己做特征选择,包括之前说的删除、合并一些特征等等。
在学习过程中,数据提供的特征有些影响模型复杂度或这个特征的异常点较多,所以算法在学习的时候尽量减少这个特征的影响(甚至删除这个特征),这就是正则化。
【说明】:调整的时候,算法并不知道某个特征的影响,而是去微调参数得出最优的结果。
【L1正则化】:可以使得其中一些w的值直接为0(如:x3与x4前面的系数直接为0),删除这个特征的影响。例如:岭回归Ridge
【L2正则化】:可以使得其中一些w的值很小,接近于0(如:x3与x4前面的系数变小),消弱这个特征的影响。例如:套索回归LASSO
【手动创建数据】:
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_权重。
一个特征对目标值的影响取决于另一个特征,现在要处理两个特征间的影响。利用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确定最多用几个特征来创建交互特征。
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阻止加入偏差。
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]
减少特征数量来简化线性回归模型。
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.]
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
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
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
评论