一: 拟合
(一): 过拟合与欠拟合
机器学习中一个重要的话题便是模型的泛化能力,泛化能力强的模型才是好模型,对于训练好的模型,若在训练集表现差,不必说在测试集表现同样会很差,这可能是欠拟合导致;若模型在训练集表现非常好,却在测试集上差强人意,则这便是过拟合导致的; 过拟合与欠拟合也可以用 Bias 与 Variance 的角度来解释,欠拟合会导致高 Bias; 过拟合会导致高 Variance ,所以模型需要在 Bias 与 Variance 之间做出一个权衡
Bias 即为模型的期望输出与其真实输出之间的差异;
Variance 刻画了不同训练集得到的模型的输出与这些模型期望输出的差异。
一般在模型效果差的第一个想法是增多数据,其实增多数据并不一定会有更好的结果,因为欠拟合时增多数据往往导致效果更差,而过拟合时增多数据会导致 Gap 的减小,效果不会好太多,所以当模型效果很差时,应该检查模型是否处于欠拟合或者过拟合的状态,而不要一味的增多数据量,关于过拟合与欠拟合,这里给出几个解决方法。
(二): 常用解决办法
(1)解决欠拟合的方法:
1、增加新特征,可以考虑加入进特征组合、高次特征,来增大假设空间;
2、尝试非线性模型,比如核SVM 、决策树、DNN等模型;
3、如果有正则项可以较小正则项参数
λ
\lambda
λ;
4、Boosting ,Boosting 往往会有较小的 Bias,比如 Gradient Boosting 等.
(2)解决过拟合的方法:
1、交叉检验,通过交叉检验得到较优的模型参数;
2、特征选择,减少特征数或使用较少的特征组合,对于按区间离散化的特征,增大划分的区间;
3、正则化,常用的有 L1、L2 正则。而且 L1正则还可以自动进行特征选择;
4、如果有正则项则可以考虑增大正则项参数 lambda;
5、增加训练数据可以有限的避免过拟合;
6、Bagging ,将多个弱学习器Bagging 一下效果会好很多,比如随机森林等.
二: Ridge回归 - 岭回归
1: Ridge回归 - 梯度下降(在线性回归后加上L2正则项-解决过拟合问题)
损失函数:
J
(
w
)
=
min
w
∣
∣
X
w
−
y
∣
∣
2
2
+
α
∣
∣
w
∣
∣
2
2
J(w) = \min\limits_w||Xw-y||_2^2 + \alpha||w||_2^2
J(w)=wmin∣∣Xw−y∣∣22+α∣∣w∣∣22
1
m
\frac{1}{m}
m1表示m个样本求平均:
J
(
w
)
=
1
m
∑
i
=
1
m
(
∣
∣
X
i
w
−
y
i
∣
∣
2
2
+
α
∣
∣
w
∣
∣
2
2
)
J(w) = \frac{1}{m}\sum_{i=1}^m(||X_iw-y_i||_2^2 + \alpha||w||_2^2)
J(w)=m1i=1∑m(∣∣Xiw−yi∣∣22+α∣∣w∣∣22)
J
(
w
)
=
1
m
[
(
X
w
−
y
)
T
(
X
w
−
y
)
+
α
w
T
w
]
J(w) = \frac{1}{m}[(Xw-y)^T(Xw-y)+\alpha w^Tw]
J(w)=m1[(Xw−y)T(Xw−y)+αwTw]
求解梯度(导数):
J
′
(
w
)
=
2
m
[
X
T
(
X
w
−
y
)
+
α
w
]
J'(w) = \frac{2}{m}[X^T(Xw-y)+\alpha w]
J′(w)=m2[XT(Xw−y)+αw]
∇
w
J
(
w
)
=
2
m
[
X
T
(
X
w
−
y
)
+
α
w
]
\nabla_wJ(w) = \frac{2}{m} [X^T(Xw - y) +\alpha w]
∇wJ(w)=m2[XT(Xw−y)+αw]
更新w:
w
=
w
−
ϵ
∇
w
J
(
w
)
w = w-\epsilon \nabla_wJ(w)
w=w−ϵ∇wJ(w)
w
=
w
−
2
m
ϵ
[
X
T
(
X
w
−
y
)
+
α
w
]
w = w -\frac{2}{m}\epsilon[X^T(Xw-y)+\alpha w]
w=w−m2ϵ[XT(Xw−y)+αw]
w
=
w
−
2
ϵ
m
X
T
(
X
w
−
y
)
−
2
α
ϵ
m
w
w = w -\frac{2\epsilon}{m} X^T(Xw-y)-\frac{2\alpha\epsilon}{m} w
w=w−m2ϵXT(Xw−y)−m2αϵw
w
=
[
w
−
2
ϵ
m
X
T
(
X
w
−
y
)
]
−
2
α
ϵ
m
w
w = [w -\frac{2\epsilon}{m} X^T(Xw-y)]-\frac{2\alpha\epsilon}{m} w
w=[w−m2ϵXT(Xw−y)]−m2αϵw
如上公式, 中括号内的公式是线性回归的更新规则, 也就是说岭回归就是在 线性回归的基础上多减了一项,
2
α
ϵ
m
w
\frac{2\alpha\epsilon}{m} w
m2αϵw, 其
中:
α
>
=
0
\alpha >= 0
α>=0缩放强度
ϵ
>
=
0
\epsilon>=0
ϵ>=0步幅
m
>
0
m>0
m>0样本数量
当w是正数时:
2
ϵ
α
m
w
\frac{2\epsilon\alpha}{m}w
m2ϵαw 为正数,此时岭回归就相当于在线性回归的基础上减去一个正数, 所以系数w变小
当w是负数时:
2
ϵ
α
m
w
\frac{2\epsilon\alpha}{m}w
m2ϵαw 为负数,此时岭回归就相当于在线性回归的基础上减去一个负数, 所以系数w的绝对值变小
正则项:w变小的好处:防止过拟合
岭回归适用范围:
方程完全共线性(方程内有方程是其他方程的倍数,相当于重复方程):
- x+ 2y + 22 = 9
- 2x +4y + 42 = 18
岭回归适用于数据中存在共线性的情况(非满秩矩阵)
2: Ridge回归正规方程推导:
损失函数:
J
(
w
)
=
min
w
∣
∣
X
w
−
y
∣
∣
2
2
+
α
∣
∣
w
∣
∣
2
2
J(w) = \min\limits_w||Xw-y||_2^2 + \alpha||w||_2^2
J(w)=wmin∣∣Xw−y∣∣22+α∣∣w∣∣22
J
(
w
)
=
(
X
w
−
y
)
T
(
X
w
−
y
)
+
α
w
T
w
J(w)=(Xw-y)^T(Xw-y)+\alpha w^Tw
J(w)=(Xw−y)T(Xw−y)+αwTw
求导:
∇
w
J
(
w
)
=
2
X
T
X
w
−
2
X
T
y
+
2
α
w
\nabla_wJ(w)=2X^TXw-2X^Ty+2\alpha w
∇wJ(w)=2XTXw−2XTy+2αw
令导数为0:
2
X
T
X
w
−
2
X
T
y
+
2
α
w
=
0
2X^TXw-2X^Ty+2\alpha w=0
2XTXw−2XTy+2αw=0
X
T
X
w
−
X
T
y
+
α
I
w
=
0
X^TXw-X^Ty+\alpha Iw=0
XTXw−XTy+αIw=0
(
X
T
X
+
α
I
)
w
−
X
T
y
=
0
(X^TX+\alpha I)w-X^Ty=0
(XTX+αI)w−XTy=0
(
X
T
X
+
α
I
)
w
=
X
T
y
(X^TX+\alpha I)w=X^Ty
(XTX+αI)w=XTy
(
X
T
X
+
α
I
)
−
1
(
X
T
X
+
α
I
)
w
=
(
X
T
X
+
α
I
)
−
1
X
T
y
(X^TX+\alpha I)^{-1}(X^TX+\alpha I)w=(X^TX+\alpha I)^{-1}X^Ty
(XTX+αI)−1(XTX+αI)w=(XTX+αI)−1XTy
推导得出w:
w
=
(
X
T
X
+
α
I
)
−
1
X
T
y
w=(X^TX+\alpha I)^{-1}X^Ty
w=(XTX+αI)−1XTy
3: Ridge回归和线性回归对比
import numpy as np
from sklearn.linear_model import LinearRegression, Ridge, Lasso
# 将数据一分为二
from sklearn.model_selection import train_test_split
# 均方误差
from sklearn.metrics import mean_squared_error
import pandas as pd
# 加载数据
# 加载训练数据
# train = pd.read_table('./zhengqi_train.txt') 和下面一行的效果相同
train = pd.read_csv('./zhengqi_train.txt', sep = '\t')
train
# 加载测试数据
test = pd.read_table('./zhengqi_test.txt')
test
# 将训练数据分乘特征值和目标值
# 特征, 影响目标值的因素
X = train.iloc[:, :-1]
# 目标值
y = train['target']
# 算法评估, 将上面的数据分成两份,一部分用来训练, 一部分用来测试
X_train, X_validation, y_train, y_validation = train_test_split(X, y, test_size = 0.2)
# 使用普通线性回归模型
linear = LinearRegression()
linear.fit(X_train, y_train)
y_ = linear.predict(X_validation)
mean_squared_error(y_validation,y_) # 均方误差
'''0.11713370444738197'''
# 使用线性模型预测测试数据
y_commit = linear.predict(test)
# 保存数据到本地
s = pd.Series(y_commit)
s.to_csv('./linear_result.txt', index=False, header = False)
# 使用岭回归模型
ridge = Ridge(alpha=256) # alpha值
ridge.fit(X_train, y_train)
y_ = ridge.predict(X_validation)
mean_squared_error(y_validation,y_)
'''0.13427749653218798'''
y_commit = ridge.predict(test)
pd.Series(y_commit).to_csv('./ridge_result.txt', index=False, header = False)
将生成的数据上传到阿里天池,与实际数据对比,计算均方误差时, 使用岭回归模型得到的数据比使用线性回归模型得到的数据的均方误差要小,说明对该组数据,岭回归效果更好
三: lasso回归 - 套索回归
1: lasso回归 - 梯度下降(在线性回归后加上L1正则项-解决过拟合问题)
罗斯回归方程:
min
w
1
2
n
s
a
m
p
l
e
s
∣
∣
X
w
−
y
∣
∣
2
2
+
α
∣
∣
w
∣
∣
1
\min\limits_w \frac{1}{2n_{samples}}||Xw-y||_2^2+\alpha ||w||_1
wmin2nsamples1∣∣Xw−y∣∣22+α∣∣w∣∣1
方程转换:
J
(
w
)
=
∣
∣
X
w
−
y
∣
∣
2
2
+
α
∣
∣
w
∣
∣
1
J(w)=||Xw-y||_2^2+\alpha ||w||_1
J(w)=∣∣Xw−y∣∣22+α∣∣w∣∣1
向量的1范数: 取绝对值的最大值
由于求导时方程中不能有绝对值符号, 所以分情况讨论: w是正数或者为负数
求导:
∇
w
J
(
w
)
=
2
X
T
X
w
−
2
X
T
y
+
α
s
g
n
(
w
)
\nabla_wJ(w)=2X^TXw-2X^Ty+\alpha sgn(w)
∇wJ(w)=2XTXw−2XTy+αsgn(w)
sgn(w)是符号表示函数: sgn(w)代表着w>0那么sgn(w)=+1;如果w<0那么sgn(W)=-1
梯度下降中系数w的更新规则:
w
=
w
−
ϵ
∇
w
J
(
w
)
w = w - \epsilon \nabla_wJ(w)
w=w−ϵ∇wJ(w)
w
=
w
−
ϵ
(
X
T
X
w
−
X
T
y
)
−
ϵ
α
s
g
n
(
w
)
w = w - \epsilon(X^TXw-X^Ty)-\epsilon \alpha sgn(w)
w=w−ϵ(XTXw−XTy)−ϵαsgn(w)
w
=
[
w
−
ϵ
(
X
T
X
w
−
X
T
y
)
]
−
ϵ
α
s
g
n
(
w
)
w = [w - \epsilon(X^TXw-X^Ty)]-\epsilon \alpha sgn(w)
w=[w−ϵ(XTXw−XTy)]−ϵαsgn(w)
当w为正时候sgn(w) =+1,直接去掉减去入所以正的w变小了
当w为负时候sgn(w)=-1,负号变成了正号加上了入,负数w取向零
Lasso回归系数可以缩减到0,岭回归不可以
系数(权重)变成0了,说明:可有可无,属性不重要
2: lasso回归与岭回归和线性回归对比
import numpy as np
from sklearn.linear_model import LinearRegression, Ridge, Lasso
# 将数据一分为二
from sklearn.model_selection import train_test_split
# 均方误差
from sklearn.metrics import mean_squared_error
import pandas as pd
# 加载数据
# 加载训练数据
# train = pd.read_table('./zhengqi_train.txt') 和下面一行的效果相同
train = pd.read_csv('./zhengqi_train.txt', sep = '\t')
train
# 加载测试数据
test = pd.read_table('./zhengqi_test.txt')
test
# 将训练数据分乘特征值和目标值
# 特征, 影响目标值的因素
X = train.iloc[:, :-1]
# 目标值
y = train['target']
# 算法评估, 将上面的数据分成两份,一部分用来训练, 一部分用来测试
X_train, X_validation, y_train, y_validation = train_test_split(X, y, test_size = 0.2)
# 使用普通线性回归模型
linear = LinearRegression()
linear.fit(X_train, y_train)
y_ = linear.predict(X_validation)
mean_squared_error(y_validation,y_) # 均方误差
'''0.11713370444738197'''
# 使用线性模型预测测试数据
y_commit = linear.predict(test)
# 保存数据到本地
s = pd.Series(y_commit)
s.to_csv('./linear_result.txt', index=False, header = False)
# 使用岭回归模型
ridge = Ridge(alpha=256) # alpha值
ridge.fit(X_train, y_train)
y_ = ridge.predict(X_validation)
mean_squared_error(y_validation,y_)
'''0.13427749653218798'''
y_commit = ridge.predict(test)
pd.Series(y_commit).to_csv('./ridge_result.txt', index=False, header = False)
# 使用lasso回归模型
lasso = Lasso(alpha=256)
lasso.fit(X_train, y_train)
y_ = lasso.predict(X_validation)
mean_squared_error(y_validation,y_)
'''0.9351911263395224'''
y_commit = lasso.predict(test)
pd.Series(y_commit).to_csv('./lasso_result.txt', index=False, header = False)
将生成的数据上传到阿里天池,与实际数据对比,计算均方误差时, 使用lasso回归模型得到的数据比使用岭回归模型和线性回归模型得到的数据的均方误差要小,说明对该组数据,lasso回归效果最好
套索回归适用于稀松矩阵(大部分系数是0)