核心逻辑
在给定n个属性描绘的客观事物 x = (x1,x2,…,xn) 中,每个 xi 都用于描绘某一次观测时事物在某个
维度表现出来的数值属性值.
我们希望能够综合这些维度的属性值来描绘事物最终运行结果,
最简单的综合这些属性的方法就是对其进行加权求和汇总,这即是线性回归.
y
=
X
w
+
b
y = Xw + b
y=Xw+b
从空间上说,线性回归就是让函数的直线,尽可能靠近空间中所有的数据点.线性回归输出一个连续值
损失函数/ MSE
对于线性回归模型,”损失函数“就是衡量当系数为 w 时的模型拟合训练集时产生的信息损失的大小,并以此衡量参数 w 的优劣。
对于线性回归, 简单理解就是 样本中各点 到 w代表的“超平面” 的距离之和。
距离有正有负,直接取绝对值或者平方都可合理解释
M
S
E
=
1
n
Σ
(
y
−
y
^
)
2
MSE = \frac{1}{n}\Sigma(y - \hat y)^2
MSE=n1Σ(y−y^)2
MSE最小 代表当前的直线是拟合最好的直线
为什么损失函数选用MSE
1、平方和比绝对值和更容易求导
2、感性理解:
例如在某一次优化过程:
对于某点到一条直线的距离 D 来说,从 D=5 到D =4 到 D = 3 到 D=2 到 D =1 。
如果用 绝对值 来计算损失的降低,则每次降低的值都相等都为
Δ
\Delta
ΔD= 1;
而使用 平方距离, 则每次降低的值分别为
Δ
\Delta
ΔD= {9,7,5,1 },降低的幅度是不一样的。
即使用MSE,随着数值的靠近,降低损失函数的收益会变小,也就是说,模型在把容易预测点的MSE降低到一定程度后,如果继续在易分点上优化,收益就会变小。这会使得模型的训练注意力转到到难分的点。感性上就是使用平方会使损失函数降低的更快一点。而使用绝对值距离的话,模型训练注意力无法转移。
线性回归解析解
1、对于
y
=
X
w
+
b
+
ϵ
y=Xw+b + \epsilon
y=Xw+b+ϵ,
2、 上述解法隐含的条件是
ϵ
\epsilon
ϵ 残差序列满足独立同分布,其现实意义在于观测误差服从正太分布,而实际上,由于样本来源不一样,那么
ϵ
\epsilon
ϵ 就会存在异方差问题,解决方法是在计算残差平方和的时候给方差不同样本赋予不同的权重。
此时
w
=
(
X
T
Λ
X
)
−
1
X
T
Λ
y
w=(X^T\Lambda X)^{-1}X^T\Lambda y
w=(XTΛX)−1XTΛy
其中,
Λ
=
d
i
a
g
(
w
1
,
w
2
,
.
.
.
,
w
n
)
\Lambda=diag(w_1,w_2,...,w_n)
Λ=diag(w1,w2,...,wn) ,
w
i
w_i
wi代表每个样本的观测方差之比,且w之和为1
解析解存在的条件——无多重共线性
1、解析解中存在
(
X
T
X
)
−
1
(X^T X)^{-1}
(XTX)−1
—>
X
T
X
X^T X
XTX 必须可逆(
A
−
1
=
A
∗
/
∣
A
∣
A^{-1}=A^*/|A|
A−1=A∗/∣A∣ ,A*是伴随矩阵必存在,所以|A|不能为0)
而
X
T
X
X^T X
XTX 必然是个方阵,
---->
X
T
X
X^T X
XTX 必须要满秩(否则其行列式为0)
这要求X是满(列)秩的,如果X是满(列)秩的,那么它的奇异值分解就会存在,而且奇异值都是非零的。然后
X
T
X
X^T X
XTX的特征值都是X的奇异值的平方,也才会都存在。
因为X是数据矩阵,X的满(列)秩说明,数据矩阵中不能有多余的列,也就是不能有重复的特征。例如我们不能看一个公司的过去一天的分红,过去两天的分红的时候,还考虑了公司过去两天之内的分红的均值。这些都会导致X不满(列)秩,间接的动摇了最小二乘法的基础,也就是
X
T
X
X^T X
XTX必须可逆
2、此外,数据量大的时候数据无法一次性读入内存,另一方面解析解需要对矩阵求逆,复杂度是O(n^3),所以一般不直接使用解析解
一般使用梯度下降
解析解存在使用限制,一般使用梯度下降法。
如果损失函数是凸函数,梯度下降法得到的解就是全局最优解。
W
−
>
W
+
η
∂
M
S
E
∂
W
W -> W + \eta \frac{\partial MSE}{\partial W}
W−>W+η∂W∂MSE
η
\eta
η是学习率, 学习率太大,容易跳过最低点,学习不到最优点;学习率太小,收敛太慢。
首先初始化一组W, 然后按上式更新W,直至梯度为0(与0相差很小)。
数据量很大时,更多选择随机梯度下降法。
关于随机梯度下降的采样
例如,当样本量 n = 1000w 时,计算耗时太大。随机抽样 m越小,会导致收敛方向波动越大。
有一个原理是,抽样的波动幅度与
1
m
\frac{1}{\sqrt m}
m1 成正比,而运算量与m 成正比。
所以,“m 取小一点,多次抽样”的计算效率, 比 “取一个大的m,少次计算 ” 的速度更快。
即每次取 m=10 抽100w次, 比 取m=1000 算1w次要合理。由于计算机硬件特点,实际中,一般取m为2的整数次方(32,64,128等)
特征缩放
在梯度下降中,如果样本的某些维度取值范围不合理,比如房价预测系统中将房价的单位采用亿元/平方米,这样每一个样本值的房价会非常小,以至于在图形表示时,几乎是一条水平线,不同的拟合直线所计算出的损失函数之间的差值非常小。所以,线性回归时有必要进行特征缩放,通常采用标准化的方式来进行特征缩放。特征缩放之后,还可以加快收敛速度。
训练集上的损失越小越好吗
并不是。
我们的训练数据只是在真实世界中很小的一部分。在训练集上训练得到的模型,只能在训练集(即是当前的场景)上得到比较好的模拟,而这种模拟还要受到诸如训练集取样的误差,真实模型本身存在的噪声等等因素影响。
把数据分为训练集、验证集、测试集。训练集训练得到的参数会使损失函数值(mse)逐步下降,把参数拿到验证集验证。一般来说,模型在验证集上的表现开始会越来越好,而随着mse越来越低,模型开始学习训练集中的噪声或者随机因素,这会导致模型在验证集上的表现转向变差。 通常选择模型在验证集上的表现转向时的参数,然后再在测试集上进行最后的测试。
线性回归的特点
1、抗噪声( 不含信息量)
现有
y
=
w
1
x
1
+
b
y=w_1x_1+b
y=w1x1+b , 假设加入一个随机噪声
x
2
x_2
x2 ,
则新形成的线性回归
y
=
w
1
x
1
+
w
2
x
2
+
b
y=w_1x_1+w_2x_2+b
y=w1x1+w2x2+b 中, w2=0
2、抗冗余信息
现在
y
=
w
1
x
1
+
w
2
x
2
+
b
y=w_1x_1+w_2x_2+b
y=w1x1+w2x2+b , 假设复制了一份 x1 加入x集,
则新生成的
y
=
(
w
1
a
+
w
1
b
)
x
1
+
w
2
x
2
+
b
y=(w_{1a}+w_{1b})x_1+w_2x_2+b
y=(w1a+w1b)x1+w2x2+b 中,w1a+w1b=w1
3、特征的权重并不完全代表该特征的重要性
由2可知,高相关的特征权重会被稀释。
训练效果不理想
1、扩大训练集
2、让训练集的数据更加接近真实环境(pdd的模型训练出来不能用在tb上)–> 特征选择、特征工程
3、增加训练集的多样性(多渠道采样)
4、升维
升维后的模型肯定比升维前的效果好,比如本来是
y
=
a
x
1
+
b
x
2
y = ax1 +bx2
y=ax1+bx2,现在加入新维度
x
1
x
2
x1x2
x1x2后,
y
=
a
x
1
+
b
x
2
+
c
x
1
x
2
y = ax1 +bx2 + cx1x2
y=ax1+bx2+cx1x2,只要令c=0,则升维后的函数就可表示升维前的所有可能性。
代码
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
iris = load_iris()
# 获取花瓣长度为x,花瓣宽度为 y。长度需要转换成二维,即列模式。对于y没有要求
X,y = iris.data[:,2].reshape(-1,1),iris.data[:,3]
# 加载线性回归类
lr = LinearRegression()
# 将数据集分为训练集与测试集
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.25,random_state=0)
# 使用训练集数据,训练模型
lr.fit(X_train,y_train)
print("权重",lr.coef_)
print("截距",lr.intercept_)
# # 从训练集中学习到了模型的参数(w 与 b),确定方程,就可以进行预测
y_hat = lr.predict(X_test)
print("实际值",y_test[:5])
print("预测值",y_hat[:5])
# 画出散点图和拟合直线
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.size'] = 15
plt.figure(figsize=(10,6))
plt.scatter(X_train,y_train,c='orange',label='训练集')
plt.scatter(X_test,y_test,c='g',marker='D',label='测试集')
plt.plot(X,lr.predict(X),'r-')
plt.legend()
plt.xlabel('花瓣长度')
plt.ylabel('花瓣宽度')
plt.show()
# 其他一些参数
from sklearn.metrics import mean_squared_error,mean_absolute_error,r2_score
#测试集与预测值 差值
print("均方误差MSE:",mean_squared_error(y_test,y_hat))
print("根均方误差(RMSE):",np.sqrt(mean_squared_error(y_test,y_hat)))
print("平均绝对值误差(MAE):",mean_absolute_error(y_test,y_hat))
print("训练集R^2",r2_score(y_train,lr.predict(X_train)))
print("测试集R^2:",r2_score(y_test,y_hat))
print("训练集R^2",lr.score(X_train,y_train))
print("测试集R^2:",lr.score(X_test,y_test))