线性回归
线性回归
线性回归(Linear regression)是利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式。
特点:只有一个自变量的情况称为单变量回归,多于一个自变量情况的叫做多元回归。
from sklearn.linear_model import LinearRegression
#获取数据
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]
#实例化模型对象
lr=LinearRegression()
#训练模型
lr.fit(x,y)
#输出模型的参数和截距
lr.coef_,lr.intercept_
#预测
lr.predict([[100,80]])
小结:
- 线性回归
- 做回归 房价预测 销量预测 分数预测
- 模型:y=ax+b 是线性的
- 训练:已知大量的x和y, 用优化算法求解最优的a和b 确定了一个模型函数:y=ax+b
- 预测:已经知道了a和b 给我x,我利用y=ax+b计算出y的值
- 分类:
- 一元线性回归 y=ax+b
- 多元线性回归 y=ax1+bx2+….+d
- 回归的分类【知道】
- 线性关系:直接上线性回归
- 非线性关系:用非线性模型
-
knn、svm、决策树
-
多项式扩展+线性回归 :多项式回归
- 多项式扩展 x—> x,x^2 ,x^3 将数据从低维映射到高维, 低维中是非线性的,高维空间中就是线性的
- 再用线性回归解决
-
- 线性回归api初步使用
sklearn.linear_model.LinearRegression() - lr.coef_:回归系数 w
- lr.intercept_:回归截距 b
求导
矩阵(向量)求导(了解)
线性回归的损失和优化
损失函数
极大似然(补充)
极大似然(联合概率最大化) 已经发生的就是最应该发生
优化算法
正规方程/最小二乘法
推导方式
- 梯度的概念:
- 单变量的时候,梯度就是该变量的导数值,只有正负之分
- 多变量的时候,每个变量都有一个偏导数,多个导数值一起就是一个向量
- 单调性角度
- 导数为正,表示函数在该点是单调递增函数, 参数减小,函数值减小 导数正,参数减
- 导数为负,表示函数在该点是单调递减函数,参数增大,函数减小 导数负 参数增
梯度下降(Gradient Descent)
在单变量的函数中,梯度其实就是函数的微分,代表着函数在某个给定点的切线的斜率;
在多变量函数中,梯度是一个向量,向量有方向,梯度的方向就指出了函数在给定点的上升最快的方向;
公式:
- α在梯度下降算法中被称作为学习率或者步长
- 注意:学习率只有一个,所有参数共用一个学习率
- 学习率过大:梯度爆炸 如果出现损失函数值不降反增,说明学习率过大,要调小
- 学习率过小: 导致下降速度太慢
-梯度要乘以一个负号:负梯度方向
梯度下降和正规方程的对比
梯度下降法介绍
全梯度下降算法(Full gradient descent),
随机梯度下降算法(Stochastic gradient descent),
小批量梯度下降算法(Mini-batch gradient descent),
随机平均梯度下降算法(Stochastic average gradient descent)
全梯度下降算法(FG)
计算训练集所有样本误差,对其求和再取平均值作为目标函数。
批梯度下降法同样也不能在线更新模型,即在运行的过程中,不能增加新的样本。
在整个训练数据集上计算损失函数关于参数θ的梯度:
- 每次拿所有样本进行损失计算
- 慢,稳
- 需要所有样本进内存
随机梯度下降算法(SG)
每次只代入计算一个样本目标函数的梯度来更新权重,再取下一个样本重复此过程,直到损失函数值停止下降或损失函数值小于某个可以容忍的阈值。
迭代形式:
x(i)表示一条训练样本的特征值,y(i)表示一条训练样本的标签值
- 每次随机拿一个样本进行损失计算并迭代
- 快,不稳
- 不需要所有样本进内存
小批量梯度下降算法(mini-batch)
每次从训练样本集上随机抽取一个小样本集,在抽出来的小样本集上采用FG迭代更新权重。
迭代形式:
- 每次拿batch_size个样本计算损失
- 一般稳,一般快
随机平均梯度下降算法(SAG)
- 原理:
- 在内存中为每个样本保存一个历史梯度值(dx1,dx2,dx3…dxm) 刚开始是0
- 每次随机选一个样本,计算梯度,更新自己的梯度值 ——快
- 然后求出所有样本的梯度的平均值,用这个平均值来更新参数—— 稳
线性回归api
- sklearn.linear_model.LinearRegression(fit_intercept=True)
通过正规方程优化
参数:fit_intercept:是否计算偏置
属性:LinearRegression.coef_:回归系数、LinearRegression.intercept_:偏置 - sklearn.linear_model.SGDRegressor(loss=“squared_loss”, fit_intercept=True, learning_rate =‘invscaling’, eta0=0.01)
SGDRegressor类实现了随机梯度下降学习,它支持不同的loss函数和正则化惩罚项来拟合线性回归模型。
参数:loss:损失类型 loss=”squared_loss”: 普通最小二乘法
fit_intercept:是否计算偏置
learning_rate : string, optional
学习率填充
‘constant’: eta = eta0
‘optimal’: eta = 1.0 / (alpha * (t + t0)) [default]
‘invscaling’: eta = eta0 / pow(t, power_t)、power_t=0.25:存在父类当中
对于一个常数值的学习率来说,可以使用learning_rate=’constant’ ,并使用eta0来指定学习率。
属性:SGDRegressor.coef_:回归系数、SGDRegressor.intercept_:偏置
回归模型评估
- rmse 均方根误差
-
np.sqrt(np.mean(np.square(y_true-y_pred)))
-
- mse 均方误差
-
np.mean(np.square(y_true-y_pred))
-
- mae 平均绝对误差
-
np.mean(np.fabs(y_true-y_pred))
-
- R^2:决定系数,0-1之间 越接近1越好
-
model.score(x_train,y_train)
-
案例:波士顿房价预测
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
from sklearn.metrics import mean_squared_error
#最小二乘法
#加载数据
boston=load_boston()
#划分数据
x_train,x_test,y_train,y_test=train_test_split(boston.data,boston.target,test_size=0.3,random_state=12)
#标准化
sc=StandardScaler()
new_x_train=sc.fit_transform(x_train)
new_x_test=sc.transform(x_test)
#模型训练
lr1=LinearRegression()
lr1.fit(new_x_train,y_train)
#预测
y_pred=lr1.predict(new_x_test)
print("预测值:",y_pred)
lr1.coef_
lr1.intercept_
#模型评估
err=mean_squared_error(y_test,y_pred)
err
#随机梯度下降的实现
#加载数据
boston=load_boston()
#划分数据
x_train,x_test,y_train,y_test=train_test_split(boston.data,boston.target,test_size=0.3,random_state=12)
#标准化
sc=StandardScaler()
new_x_train=sc.fit_transform(x_train)
new_x_test=sc.transform(x_test)
lr2=SGDRegressor(max_iter=5000,learning_rate='constant',eta0=0.001)
lr2.fit(new_x_train,y_train)
#预测
y_pred=lr2.predict(new_x_test)
print("预测值:",y_pred)
print("系数:",lr2.coef_)
print("截距:",lr2.intercept_)
#模型评估
err=mean_squared_error(y_test,y_pred)
err
欠拟合和过拟合
过拟合:在训练数据上能够获得比其他假设更好的拟合, 但是在测试数据集上却不能很好地拟合数据(模型过于复杂)
欠拟合:在训练数据上不能获得更好的拟合,并且在测试数据集上也不能很好地拟合数据(模型过于简单)
- 过拟合:
- 表现:训练集表现很好,测试集表现很差
- 产生的原因:模型过于复杂
- 数据: 特征太多
- 算法:模型参数太多、模型太强、模型迭代次数太多、正则化力度太小
- 解决办法
- 数据
- 减少特征:特征选择、特征降维
- 增加数据量(特征多不多是相对于数据量来说)
- 算法:减少参数、换一个简单的算法、早停(早点停止训练)、加大正则
- 数据
- 欠拟合
- 表现:训练集和测试机表现都不好
- 产生的原因:模型过于简单
- 数据:特征太少,特征无用
- 算法: 算法参数少、 算法太弱、 迭代次数过少、正则化力度太大
- 解决办法
- 数据:增加特征
- 算法:增加参数、 换一个算法、多训练几轮、 减少正则化力度、对特征做非线性变换(提高特征的表达能力)(平方、指数、对数、sin/cos/相除/相乘)、换算法:决策树、knn/svm/神经网络/深度学习
正则化
数据提供的特征有些影响模型复杂度或者这个特征的数据点异常较多,所以算法在学习的时候尽量减少这个特征的影响(甚至删除某个特征的影响),这就是正则化。
- 定义:通过一定的手段使得模型的部分参数等于0或者接近0 ,减小模型复杂度,从而防止过拟合
- L2正则化
- 作用:可以使得其中一些W的都很小,都接近于0,削弱某个特征的影响
- 优点:越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象
- Ridge回归
- L1正则化
- 作用:可以使得其中一些W的值直接为0,删除这个特征的影响
- LASSO回归
正则化线性模型
正则化的目的: 损失函数+正则项
- 能够防止损失函数去寻找最优解(训练集的最优解一定不是测试集的最优解)
- 模型的目的不是为了训练集表现好,而是为了测试集表现好
Ridge Regression (岭回归)
- 损失函数+所有参数平方和 L2
- 导数=2\theta 接近0的时候导数为0 永远走不到0
- alpha越大,正则越厉害,参数值越小,走向欠拟合 极端: 参数=0 y=b
- alpha越小,正则越弱,参数值就越大,走向过拟合
样本数 特征数
Lasso Regression(Lasso 回归)
- 损失函数+所有参数绝对值的和 L1
- 导数 -1 0 1 很快可以走到0
- 得到的是一个稀疏模型(部分参数=0)可以做特征选择
Elastic Net (弹性网络)
弹性网络在岭回归和Lasso回归中进行了折中,通过 混合比(mix ratio) r 进行控制:
r=0:弹性网络变为岭回归
r=1:弹性网络便为Lasso回归
小结
Early Stopping [了解]:在验证错误率达到最小值的时候停止训练
常用:岭回归
假设只有少部分特征是有用的:弹性网络、Lasso
一般来说,弹性网络的使用更为广泛。因为在特征维度高于训练样本数,或者特征是强相关的情况下,Lasso回归的表现不太稳定。
api:from sklearn.linear_model import Ridge, ElasticNet, Lasso
线性回归改进-岭回归
sklearn.linear_model.Ridge(alpha=1.0, fit_intercept=True,solver=“auto”, normalize=False)
- 具有l2正则化的线性回归
- alpha:正则化力度,也叫 λ
- λ取值:0~1 1~10
- alpha越大,就会走向欠拟合
- alpha越小 就会走向过拟合
- λ取值:0~1 1~10
- solver:会根据数据自动选择优化方法
- sag:如果数据集、特征都比较大,选择该随机梯度下降优化
- normalize:数据是否进行标准化
- normalize=False:可以在fit之前调用preprocessing.StandardScaler标准化数据
- Ridge.coef_:回归权重
- Ridge.intercept_:回归偏置
正则对模型参数的影响
- 岭迹图
- alpha越小,正则化力度越小,模型的系数(绝对值)就会变大,模型走向过拟合
- alpha越大,正则化力度越大,模型的系数就会越来越小,模型走向欠拟合
- alpha应该选择岭迹图喇叭口的位置
from sklearn.linear_model import Ridge,RidgeCV
#加载数据
boston=load_boston()
#划分数据
x_train,x_test,y_train,y_test=train_test_split(boston.data,boston.target,test_size=0.3,random_state=12)
#标准化
sc=StandardScaler()
new_x_train=sc.fit_transform(x_train)
new_x_test=sc.transform(x_test)
# ridge=Ridge(alpha=0.1)
ridge=RidgeCV(alphas=(0.001,0.005,0.1,0.5,1,10,20,50,100))
ridge.fit(new_x_train,y_train)
#预测
y_pred=ridge.predict(new_x_test)
print("预测值:",y_pred)
print("系数:",ridge.coef_)
print("截距:",ridge.intercept_)
#模型评估
err=mean_squared_error(y_test,y_pred)
err
模型的保存和加载
from sklearn.externals import joblib
保存:joblib.dump(estimator, ‘test.pkl’)
加载:estimator = joblib.load(‘test.pkl’)
注意:
1.保存文件,后缀名是**.pkl
2.加载模型是需要通过一个变量进行承接
from sklearn.externals import joblib
#保存岭回归模型
joblib.dump(ridge,'data/test.pkl')
#保存标准化模型
joblib.dump(sc,'data/sc.pkl')
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.externals import joblib
#加载数据
boston=load_boston()
#划分数据
x_train,x_test,y_train,y_test=train_test_split(boston.data,boston.target,test_size=0.3,random_state=12)
#加载标准化模型
sc=joblib.load('data/sc.pkl')
sc
#使用加载的标准化模型对数据进行标准化
x=sc.transform(x_test)
#加载ridge模型
ridge=joblib.load('data/test.pkl')
ridge
#利用加载的模型进行预测
y_pred=ridge.predict(x)
y_pred
常用
RMSE/MSE/MAE/SD
RMSE(均方根误差)、MSE(均方误差)、MAE(平均绝对误差)、SD(标准差)