写在前面:
这个月有点懈怠,从博客就看得出。月底开学,马上就要开始忙碌起来了。
1.定义与公式
线性回归(linear regression )是利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系建模的一种分析方式。
只有一个自变量的情况称之为单变量回归,多于一个自变情况的叫做多元回归。
y=kx+b
要探求的解就是k,b。
分类:线性关系,非线性关系
线性关系:单特征与目标值的关系成直线关系,两个特征值与目标值呈现平面的关系。
2.线性回归api初步使用
sklearn.linear_model.LinearRegression()
3.数学:求导
4.线性回归的损失和优化
4.1 损失函数
损失=所有预测值-真实值的差的平方之和,又称最小二乘法。
为此,要进行优化,减少损失,使我们预测的更加准确。
4.2 优化算法
通过一些优化方法去优化(其实是数学当中的求导功能)回归的总损失。
4.2.1 正规方程
4.2.2 梯度下降法
可理解为:首先,我们有一个可微分的函数。这个函数代表一座山。
我们的目标就是找到这个函数的最小值,也就是山底。
因此,下山最陡峭的地方就是函数变化最快的方向。
在单变量函数中,梯度其实就是函数的微分,代表函数在某个给定点的切线的斜率。
在多变量函数中,梯度是一个向量,梯度的方向就指出了函数在给定点的上升最快的方向,那么梯度的反方向就是函数在给定点下降最快的方向。
梯度下降法中要关注的两个参数:
α 就是步长,步长太小,下山太慢,步长太大,容易跳过极小值。
梯度要加一个负号:梯度的反方向就是函数在给定点下降最快的方向。
5.梯度下降法方法介绍
5.1 全梯度下降算法FG
计算训练集所有样本误差,对其求和再取平均值
5.2 随机梯度下降算法SG
每次只代入计算一个样本目标函数的梯度来更新权重,再取下一个样本重复此过程,直到损失函数值停止下降或损失函数值小于某个可以容忍的阈值。
但是每次SG只是用一个样本迭代,若遇上噪声容易陷入局部最优解。
5.3 小批量梯度下降算法 mini-batch
是前面两种的折中方案。
每次从训练样本集上随机抽取部分样本集,在抽出来的小样本集上采用FG迭代更新权重。
被抽出的小样本集所含样本点的个数称为batch_size,通常设置为2的幂次方,更有利于GPU加速处理。若batch_size=1,则变成了SG,若batch_size=n,则变成了FG。
5.4 随机平均梯度下降算法SAG
会给每个样本都维持一个平均值,后期计算的时候,参考这个平均值。
随机平均梯度算法,在内存中为每一个样本都维护了一个旧的梯度,随机选择第i个样本来更新梯度,最后求得所有梯度的平均值,进而更新参数。由于每次更新仅计算一个样本点的梯度,计算成本等同SG,但收敛速度快很多。
6. 线性回归api再介绍
正规方程的使用
sklearn.linear_model.LinearRegression(fit_intercept =True)
预测波士顿房价为例:
# coding:utf-8
"""
# 1.获取数据
# 2.数据基本处理
# 2.1 数据集划分
# 3.特征工程
# 4.机器学习(线性回归)
# 5.模型评估
"""
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 linear_model1():
"""
正规方程
:return:None
"""
# 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 =LinearRegression()
estimator.fit(x_train,y_train)
print("这个模型的偏置是:\n",estimator.intercept_)
# 5.模型评估
# 预测值和准确率
y_pre =estimator.predict(x_test)
print("预测值是:\n",y_pre)
score = estimator.score(x_test,y_test)
print("准确率是:\n",score)
# 均方误差
ret =mean_squared_error(y_test,y_pre)
print("误差为:\n",ret)
if __name__=='__main__':
linear_model1()
结果输出:
梯度下降法使用
-
sklearn.linear_model.LinearRegression(fit_intercept =True) 通过正规方程优化
fit_intercept:是否计算偏置 LinearRegression.coef_:回归系数
LinearRegression.intercept_:偏置 -
sklearn.linear_model.SGDReggressor(loss=“squared_loss”,fit_intercept=True,learing_rate=‘invscaling’,eta0=0.01)
SGDRegressor类实现了随机梯度下降学习,它支持不同的loss函数和正则化惩罚项来拟合线性回归模型。 loss:损失类型
·loss=“squared_loss”:普通最小二乘法
·fit_intercept:是否计算偏置
·learning_rate:string.optional ·学习率填充 ·‘constant’:eta=eta0
·‘optional’ :eta=1.0/(alpha*(t+t0))[default]
· power_t =0.25
存在父类当中 对于一个常数值的学习率来说,可以使用learni_rate=‘constant’,并使用eta0来指定学习率在上面的代码中修改,使用SGDRegressor()
# 4.机器学习(线性回归)
estimator = SGDRegressor() # 未在括号内加参数时,可能会报如下错误
estimator.fit(x_train, y_train)
print("这个模型的偏置是:\n", estimator.intercept_)
warning如下:
D:\python\lib\site-packages\sklearn\linear_model\stochastic_gradient.py:128:
FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDRegressor'> in 0.19.
If both are left unset, they default to max_iter=5 and tol=None.
If tol is not None, max_iter defaults to max_iter=1000. From 0.21,
default max_iter will be 1000, and default tol will be 1e-3.
"and default tol will be 1e-3." % type(self), FutureWarning)
指定一下max_inter即可。
estimator = SGDRegressor(max_inter=1000)
上下比较,图1 是正规方程得到的结果:
图2 是梯度下降法,
7. 过拟合与欠拟合
7.1 过拟合
一个假设在训练数据上能够获得比其他假设更好的拟合,但是在测试数据集上却不能很好地拟合数据,此时认为这个假设出现了过拟合的现象。
解决办法:
由于原始特征过多,模型过于复杂是因为模型尝试去兼顾各个测试数据点。
重新清洗数据,
增大数据的训练量
正则化
减少特征维度,防止维灾难
7.2 欠拟合
一个假设在训练数据上不能获得更好的拟合,并且在测试数据集上也不能很好的拟合数据,此时认为假设出现了欠拟合的现象。(模型过于简单)
解决办法:
添加其他特征:组合,泛化,相关性三类特征
添加多项式特征:这个在机器学习算法里面用的很普遍,例如将线性模型通过添加二次项或三次项使模型泛化能力更强。
7.3 正则化
在机器学习中,数据提供的特征有些影响模型复杂度或者这个特征的数据点异常较多,所以算法在学习的时候尽量减少这个特征的影响(甚至删除某个特征的影响)。
7.3.1 正则化类别
L2正则化:
作用:使得其中一些W的都很小,都接近于0,削弱某个特征的影响
优点:越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象。
Ridge回归(岭回归)
L1正则化
作用:可以使其中一些W的值直接为0,删除这个特征的影响。
LASSO回归
8. 正则化线性模型
8.1 *Ridge Regression(岭回归)
把系数前面添加平方项,然后限制系数值的大小。α值越小,系数值越大,α越大,系数值越小
8.2 Lasso 回归
对系数值进行绝对值处理。
由于绝对值在顶点处不可导,所以进行计算的过程中产生很多0,最后得到结果为:稀疏矩阵。
8.2 Elastic Net 弹性网络
是前两个的综合。设置了一个r,如果r=0,岭回归;r=1,Lasso回归
8.3 Early stopping
通过限制错误率的阈值,进行停止。
9.线性回归的改进–岭回归
eg.房价预测
def linear_model3():
"""
岭回归
:return:None
"""
# 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()
estimator = RidgeCV(alphas=(0.001,0.1,1,10,100))
estimator.fit(x_train, y_train)
print("这个模型的偏置是:\n", estimator.intercept_)
# 5.模型评估
# 预测值和准确率
y_pre = estimator.predict(x_test)
print("预测值是:\n", y_pre)
score = estimator.score(x_test, y_test)
print("准确率是:\n", score)
# 均方误差
ret = mean_squared_error(y_test, y_pre)
print("均方误差为:\n", ret)
10.模型的保存和加载
sklearn模型的保存和加载API
from sklearn.externals import joblib
保存:joblib.dump(estimator,‘test.pkl’)
加载:estimator = joblib.load(‘test.pkl’)
10.1 保存模型
# coding:utf-8
"""
# 1.获取数据
# 2.数据基本处理
# 2.1 数据集划分
# 3.特征工程
# 4.机器学习(线性回归)
# 5.模型评估
"""
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,SGDRegressor ,Ridge,RidgeCV# 线性回归
from sklearn.metrics import mean_squared_error # 模型评估
from sklearn.externals import joblib
# 获取数据
def dump_load_demo():
"""
模型保存和加载
:return:None
"""
# 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.机器学习(线性回归)
# 4.1 模型训练
estimator = Ridge()
# estimator = RidgeCV(alphas=(0.001,0.1,1,10,100))
estimator.fit(x_train, y_train)
print("这个模型的偏置是:\n", estimator.intercept_)
# 4.2 模型保存
joblib.dump(estimator,"C://Users//PycharmProjects//learn//data//test.pkl")
# 5.模型评估
# 预测值和准确率
y_pre = estimator.predict(x_test)
print("预测值是:\n", y_pre)
score = estimator.score(x_test, y_test)
print("准确率是:\n", score)
# 均方误差
ret = mean_squared_error(y_test, y_pre)
print("均方误差为:\n", ret)
if __name__=='__main__':
dump_load_demo()
保存模型后,在指定路径下看到模型:
记下此时的结果:
修改代码加载模型:
# coding:utf-8
"""
# 1.获取数据
# 2.数据基本处理
# 2.1 数据集划分
# 3.特征工程
# 4.机器学习(线性回归)
# 5.模型评估
"""
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,SGDRegressor ,Ridge,RidgeCV# 线性回归
from sklearn.metrics import mean_squared_error # 模型评估
from sklearn.externals import joblib
# 获取数据
def dump_load_demo():
"""
模型保存和加载
:return:None
"""
# 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.机器学习(线性回归)
# # 4.1 模型训练
# estimator = Ridge()
# # estimator = RidgeCV(alphas=(0.001,0.1,1,10,100))
#
# estimator.fit(x_train, y_train)
# print("这个模型的偏置是:\n", estimator.intercept_)
#
# # 4.2 模型保存
# joblib.dump(estimator,"C://Users//PycharmProjects//learn//data//test.pkl")
# 4.3 模型加载
estimator =joblib.load("C://Users//PycharmProjects//learn//data//test.pkl")
# 5.模型评估
# 预测值和准确率
y_pre = estimator.predict(x_test)
print("预测值是:\n", y_pre)
score = estimator.score(x_test, y_test)
print("准确率是:\n", score)
# 均方误差
ret = mean_squared_error(y_test, y_pre)
print("均方误差为:\n", ret)
if __name__=='__main__':
dump_load_demo()
此时结果,比较两者的均方误差:
可以看到两者的均方误差不一样。
由于数据分割方式不一样,数据集合测试集划分不一样。
解决办法:在数据集划分时进行设置,加入random_state
x_train, x_test, y_train, y_test = train_test_split(boston.data, boston.target,random_state=22,test_size=0.2)