模型
自变量x和因变量y为线性关系。
x:数据点集合,y:目标值,(x, y):一个训练样本。
e 为误差,这里假设服从均值0的正态分布。
机器学习中,一般描述为
假设函数:
x 是向量。矩阵表示
其中, xji表示第j个样本第i维特征,m个样本,n维特征。
已知训练集
x=(x0,x1,…,xn)
估计
θ
,MSE为点估计的一种评价标准。
注:已假定e服从正态分布,MSE也就自然了。比如SAE绝对差和,无法给出可解的优化问题。
代价函数(可以通过最大似然估计推导出):
目的,寻找最小化 J(θ) 的 θ∗ ,几何意义上,就是试图找一条直线,使所有样本与直线的欧式距离之和最小。
策略及算法
最小二乘
由
zTz=∑iz2i
,
正规方程组
XTX
为满秩矩阵或小样本少特征情况下:
这里
梯度下降法
迭代逼近,一般采用批量下降,为了减少收敛至局部最优解的概率,随机初始化多次,从中选择最优解。
迭代规则:
其中, α 为学习速率,值过小会导致迭代收敛慢,值过大会导致徘徊在最优解附近无法收敛。
迭代规则:
随机梯度下降法:更新参数时,不必遍历所有样本,随机选择一个就可以。
梯度下降中,由于样本分布不同,可能会遇到局部最小值点、鞍点、下降速度过慢、跳过最小值点等问题。
过拟合
模型泛化能力差,高方差。
来自网络的图片,很形象:
一般由于:
- 训练集和测试集特征分布不一致
- 样本和特征数量不匹配,模型复杂
解决办法:
- 合理化样本和特征数量(比如相应减少特征或增加样本)
- 交叉验证
- 正则化
正则化
L1_normal(lasso、L1正则化),使用L1_normal的建模称为lasso(least absolute shrinkage and selection operator)回归
L2_normal(ridge、L2正则化),使用L2_normal的建模称为ridge(岭)回归
一些解释:
L1、L2都是一种通过对权值向量引入额外约束以避免产生过拟合的方法。
L1产生稀疏权值矩阵,某些权值项为0,挑选样本特征,降低模型复杂度。
L2 减小某些权值的影响,降低模型复杂度。
矩阵解释:
Θ 为非奇异矩阵时,矩阵可逆,代价函数有唯一解。如果其为近似奇异矩阵时,微小的样本变化都可能导致模型巨大的变化,模型泛化能力差。
增强矩阵求逆数值稳定性,可在方阵 XTX 的主对角线上增加 λ 。
Θ^=(XTX+λI)−1XTy
L2的求解刚好能获取上面公式。
关于 λ 选择
λ 越大,对参数修正越明显,模型相对简单
一般通过交叉验证获取
这是一个bias-var-tradeoff 偏差、方差权衡的问题
code
# -*- coding:utf-8 -*-
import numpy as np
from sklearn.linear_model import LinearRegression, RidgeCV, LassoCV
from sklearn.preprocessing import PolynomialFeatures
import matplotlib.pyplot as plt
from sklearn.pipeline import Pipeline
import matplotlib as mpl
import warnings
if __name__ == "__main__":
warnings.filterwarnings("ignore")
np.random.seed(0)
ORDER = 8
N = 10
x = np.linspace(0, 6, N) + np.random.randn(N)
x = np.sort(x)
y = 1.2 * x**2 - 3.1*x - 3 + np.random.randn(N)
x = x.reshape(-1, 1)
y = y.reshape(-1, 1)
models = [
Pipeline([('poly', PolynomialFeatures()), ('linear', LinearRegression(fit_intercept=False))]),
Pipeline([('poly', PolynomialFeatures()), ('linear', RidgeCV(alphas=np.logspace(-3, 2, 50), fit_intercept=False))]),
Pipeline([('poly', PolynomialFeatures()), ('linear', LassoCV(alphas=np.logspace(-3, 2, 50), fit_intercept=False))]),
]
mpl.rcParams['font.sans-serif'] = [u'simHei']
mpl.rcParams['axes.unicode_minus'] = False
np.set_printoptions(suppress=True)
plt.figure(figsize=(18, 12), facecolor='w')
d_pool = np.arange(1, ORDER, 2)
m = d_pool.size
clrs = []
for c in np.linspace(255, 16711680, m):
clrs.append('#%06x' % np.int32(c))
print(clrs)
line_width = np.linspace(5, 2, m)
titles = [u'线性回归', u'Ridge回归', u'LASSO']
for t in range(3):
model = models[t]
plt.subplot(2, 2, t+1)
plt.plot(x, y, 'ro', ms=10, zorder=ORDER)
for i, d in enumerate(d_pool):
model.set_params(poly__degree=d)
model.fit(x, y.flatten())
lin = model.get_params('linear')['linear']
x_hat = np.linspace(x.min(), x.max(), num=100)
x_hat.shape = -1, 1
y_hat = model.predict(x_hat)
s = model.score(x, y)
z = ORDER - 1 if (d == 2) else 0
label = u'%d阶,$R^2$=%.3f' % (d, s)
if hasattr(lin, 'l1_ratio_'):
label += u',L1 ratio=%.2f' % lin.l1_ratio_
plt.plot(x_hat, y_hat, color=clrs[i], lw=line_width[i], alpha=0.75, label=label, zorder=z)
plt.legend(loc='upper left')
plt.grid(True)
plt.title(titles[t], fontsize=18)
plt.xlabel('X', fontsize=16)
plt.ylabel('Y', fontsize=16)
plt.tight_layout(1, rect=(0, 0, 1, 0.95))
plt.suptitle(u'多项式曲线拟合比较', fontsize=22)
plt.show()