公司微网站建设价格,设计网站需求,陕西省建设网三类人员公示,龙宜推广公司是正规吗在训练不同机器学习算法模型时#xff0c;遇到的各类训练算法大多对用户都是一个黑匣子#xff0c;而理解它们实际怎么工作#xff0c;对用户是很有帮助的#xff1b;
快速定位到合适的模型与正确的训练算法#xff0c;找到一套适当的超参数等#xff1b;更高效的执行错…在训练不同机器学习算法模型时遇到的各类训练算法大多对用户都是一个黑匣子而理解它们实际怎么工作对用户是很有帮助的
快速定位到合适的模型与正确的训练算法找到一套适当的超参数等更高效的执行错误调试、错误分析等有助于理解、构建和训练神经网络等
训练方法
线性回归模型 闭式方程直接计算出最拟合训练集的模型参数使训练集上的成本函数最小化的模型参数迭代优化GD、梯度下降、梯度下降变体、小批量梯度下降、随机梯度下降逐渐调整模型参数直至训练集上的成本函数调至最低 多项式回归模型 学习曲线评估过拟合情况正则化技巧降低过拟合风险 分类模型 Logistic 回归Softmax 回归 文章目录1. 线性回归1. 标准方程2. 奇异值分解3. 计算复杂度2. 梯度下降1. 批量梯度下降2. 随机梯度下降3. 小批量梯度下降3. 多项式回归4. 学习曲线5. 正则化线性模型1. 岭回归2. Lasso 回归3. 弹性网络4. 提前停止6. 逻辑回归1. 估计概率2. 训练和成本函数3. 决策边界4. Softmax 回归1. 线性回归
线性模型可以当做是对输入特征做加权求和再加上一个偏置项截距项常数
线性回归模型预测
y^θ0θ1x1θ2x2...θnxn\hat{y} \theta_0 \theta_1x_1 \theta_2x_2 ... \theta_nx_n y^θ0θ1x1θ2x2...θnxn
y^\hat{y}y^预测值n特征数量xix_ixi第 i 个特征值θj\theta_jθj第 j 个模型参数包括偏差项 θ0\theta_0θ0 和特征权重 θ1\theta_1θ1、θ2\theta_2θ2、…、θn\theta_nθn
线性回归模型预测向量化形式
y^hθ(x)θ⋅x\hat{y} h_\theta(x) \theta · x y^hθ(x)θ⋅x
θ\thetaθ模型的参数向量其中包含偏差项 θ0\theta_0θ0 和特征权重 θ1\theta_1θ1 至 θn\theta_nθnx实例的特征向量包含从 x0x_0x0 到 xnx_nxn x0x_0x0 始终等于 1θ⋅x\theta · xθ⋅x向量 θ\thetaθ 和 X 的点积它相当于 θ0x0θ1x1θ2x2...θnxn\theta_0x_0 \theta_1x_1 \theta_2x_2 ... \theta_nx_nθ0x0θ1x1θ2x2...θnxnhθh_\thetahθ假设函数使用模型参数 θ\thetaθ
特征向量feature vector一个样本对应在样本空间中坐标轴上的坐标向量 向量在机器学习中通常表示列向量表示单一列的二维数组
线性回归模型的 MSE 成本函数
MSE(X,hθ)1m∑i1m(θTx(i)−y(i))2MSE (X, h_\theta) \frac{1}{m}\sum_{i1}^m(\theta^Tx^{(i)} - y^{(i)})^2 MSE(X,hθ)m1i1∑m(θTx(i)−y(i))2
hθh_\thetahθ其中的 θ\thetaθ 表示模型 h 是被向量 θ\thetaθ 参数化的
1. 标准方程
闭式解方法直接得出使成本函数最小的 θ\thetaθ 值的数据方程也称标准方程
θ^(XTX)−1XTy\hat{\theta} (X^TX)^{-1}X^Ty θ^(XTX)−1XTy
θ^\hat{\theta}θ^使成本函数最小的 θ\thetaθ 值y包含 y(1)y^{(1)}y(1) 到 y(m)y^{(m)}y(m) 的目标值向量
使用线性数据测试标准方程
import numpy as npX 2 * np.random.rand(100, 1)
y 4 3 * X np.random.randn(100, 1)plt.plot(X, y, b.)
plt.xlabel($x_1$, fontsize18)
plt.ylabel($y$, rotation0, fontsize18)
plt.axis([0, 2, 0, 15])
plt.show()使用标准方程计算 θ^\hat{\theta}θ^
inv()对矩阵求逆dot()计算矩阵的内积 X_b np.c_[np.ones((100, 1)), X] # add x0 1 to each instancetheta_best np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)array([[4.21509616],[2.77011339]])原本的 θ0\theta_0θ04θ1\theta_1θ13这里算出的 θ0\theta_0θ04.215θ1\theta_1θ12.770已经比较接近
使用 θ^\hat{\theta}θ^ 做预测 X_new np.array([[0], [2]])X_new_b np.c_[np.ones((2, 1)), X_new] # add x0 1 to each instancey_predict X_new_b.dot(theta_best)y_predict
array([[4.21509616],[9.75532293]])绘制模型的预测结果
plt.plot(X_new, y_predict, r-, linewidth2, labelPredictions)
plt.plot(X, y, b.)
plt.xlabel($x_1$, fontsize18)
plt.ylabel($y$, rotation0, fontsize18)
plt.legend(locupper left, fontsize14)
plt.axis([0, 2, 0, 15])
plt.show()2. 奇异值分解
回顾使用 Scikit-Learn 的 LinearRegression from sklearn.linear_model import LinearRegressionlin_reg LinearRegression()lin_reg.fit(X, y)lin_reg.intercept_, lin_reg.coef_
(array([4.21509616]), array([[2.77011339]]))lin_reg.predict(X_new)
array([[4.21509616],[9.75532293]])intercept_偏差项coef_特征权重
LinearRegression 的 θ\thetaθ 是基于 scipy.linalg.lstsq() 函数最小二乘计算的
θ^Xy\hat{\theta} X^{}y θ^Xy
XX^{}XX 的伪逆 theta_best_svd, residuals, rank, s np.linalg.lstsq(X_b, y, rcond1e-6)theta_best_svd
array([[4.21509616],[2.77011339]])使用 np.linalg.pinv() 计算伪逆 np.linalg.pinv(X_b).dot(y)
array([[4.21509616],[2.77011339]])奇异值分解Singular Value DecompositionSVD计算伪逆的标准矩阵分解技术可将训练集矩阵 X 分解成三个矩阵 U∑VTU\sum{}V^{T}U∑VT 的乘积numpy.linalg.svd() 实现
XV∑UTX^{} V\sum{}^{}U^{T} XV∑UT
∑\sum^{}∑ 的计算方式取 ∑\sum∑ 并将所有小于一个阈值的值设置成 0再将非 0 值替换成它们的倒数最后把结果矩阵转置
** SVD vs. 标准方程**
伪逆比标准方程更有效可以很好的处理边缘问题若 XTXX^TXXTX 是不可逆的标准方程可能无解而伪逆总是有定义的
3. 计算复杂度
标准方程相对特征数量 n 的计算复杂度
O(n2.4)至O(n3)O(n^{2.4}) 至 O(n^{3}) O(n2.4)至O(n3)
标准方程计算的是 XTXX^{T}XXTX 的逆XTXX^{T}XXTX 是一个 (n1)×(n1)(n1) \times (n1)(n1)×(n1) 的矩阵n 是特征数求逆的计算复杂度通常为 O(n2.4)O(n^{2.4})O(n2.4) 至 O(n3)O(n^{3})O(n3)具体取决于实现方式当 n 翻倍计算复杂度将变大 22.42^{2.4}22.45.3 至 232^3238 倍
SVD 相对特征数量 n 的计算复杂度
O(n2)O(n^2)O(n2)
相对于训练集的实例数量 O(m)O(m)O(m)标准方程和 SVD 的计算复杂度都是线性的
线性回归模型一经训练不论标准方程还是其他算法预测就非常快计算复杂度相对于要预测实例数量和特征数量都是线性的
2. 梯度下降
假设你迷失在山上的浓雾之中你能感觉到的只有你脚下路面的坡度快速到达山脚的一个策略就是沿着最陡的方向下坡
梯度下降算法通过测量参数向量 θ\thetaθ 相关的误差函数的局部梯度并不断沿着降低梯度的方向调整直到梯度降为 0达到最小值 首先随机选择一个 θ\thetaθ 值随机初始化然后逐步改进每次踏出一步每步参试降低一点成本函数如 MSE直到算法收敛为一个最小值
学习率超参数梯度下降每一步的步长 太低算法需要大量迭代才能收敛耗时变得很长太高导致算法发散值越来越大可能直接越过山谷到达另一边甚至比之前的起点还高无法找到最优解
梯度下降陷阱 并非所有的成本函数都是一个碗型的可能如图一般不规则导致很难收敛到全局最小值若随机初始化起点在左侧会收敛到一个局部最小值而非全局最小值若随机初始化起点在右侧则可能需要很长一段时间才能迭代到最低点若停下得太早可能永远无法到底全局最小值
线性回归模型的 MSE 成本函数是一个连续的凸函数因此不存在局部最小值只有一个全局最小值且斜率不会产生陡峭变化即使乱走梯度下降也可以趋近全局最小值
细长碗状成本函数
因不同特征的尺寸差异巨大导致的细长碗状成本函数特征值越小如 θ1\theta_1θ1就需要更大的变化来影响成本函数 左图的梯度下降算法直接走向最小值可以快速到达右图则先沿着与全局最小值方向近乎垂直的方向前进然后验证近乎平坦的山谷走到最小值需要花费大量时间
应用梯度下降时需保证所有特征值大小比例相差不多比如使用 Scikit-Learn 的 StandardScaler否则收敛时间会长很多
训练模型也就是搜寻使成本函数在训练集上最小化的参数组合这是模型参数空间层面上的搜索模型的参数越多这个空间的维度就越多搜索就越难同样是在干草堆里寻找一根针在一个三百维的空间里就比在一个三维空间里要棘手得多幸运的是线性回归模型的成本函数是凸函数针就躺在碗底
1. 批量梯度下降
实现梯度下降需要计算每个模型关于参数 θj\theta_jθj 的成本函数的梯度即计算关于参数 θj\theta_jθj 的成本函数的偏导数计作 ∂∂θjMSE(θ)\frac{\partial}{\partial\theta_j}MSE(\theta)∂θj∂MSE(θ)
成本函数的偏导数
∂∂θjMSE(θ)2m∑i1m(θTx(i)−y(i))xj(i)\frac{\partial}{\partial\theta_j}MSE(\theta) \frac{2}{m}\sum_{i1}^{m}(\theta^{T}x^{(i)} - y^{(i)})x_j^{(i)} ∂θj∂MSE(θ)m2i1∑m(θTx(i)−y(i))xj(i)
一次性计算偏导数
▽θMSE(θ)(∂∂θ0MSE(θ)∂∂θ1MSE(θ)...∂∂θnMSE(θ))2mXT(Xθ−y)\triangledown_\theta MSE(\theta) \begin{pmatrix} \frac{\partial}{\partial\theta_0}MSE(\theta) \\ \frac{\partial}{\partial\theta_1}MSE(\theta) \\ ... \\ \frac{\partial}{\partial\theta_n}MSE(\theta) \\ \end{pmatrix} \ \frac{2}{m} X^{T}(X\theta - y) ▽θMSE(θ)∂θ0∂MSE(θ)∂θ1∂MSE(θ)...∂θn∂MSE(θ) m2XT(Xθ−y)
在计算梯度下降的每一步时都是基于完整的训练集 X 的因此面对非常庞大的训练集时算法会变得极慢梯度下降算法随特征数量扩展的表现比较好比如几十万个特征梯度下降比标准方程或者 SVD 要快很多
梯度下降步骤
θ(下一步)θ−η▽θMSE(θ)\theta^{(下一步)} \theta - \eta \triangledown_\theta MSE(\theta) θ(下一步)θ−η▽θMSE(θ)
η\etaη学习率用梯度向量乘以 η\etaη 确定下坡步长的大小
梯度下降的快速实现
eta 0.1 # learning rate
n_iterations 1000
m 100theta np.random.randn(2, 1) # random initializationfor iteration in range(n_iterations):gradients 2/m * X_b.T.dot(X_b.dot(theta) - y)theta theta - eta * gradientsprint(theta)
[[4.21509616][2.77011339]]theta 计算结果与标准方程的计算结果相同
计算三种学习率的梯度下降前十步
虚线表示起点
theta_path_bgd []def plot_gradient_descent(theta, eta, theta_pathNone):m len(X_b)plt.plot(X, y, b.)n_iterations 1000for iteration in range(n_iterations):if iteration 10:y_predict X_new_b.dot(theta)style b- if iteration 0 else r--plt.plot(X_new, y_predict, style)gradients 2/m * X_b.T.dot(X_b.dot(theta) - y)theta theta - eta * gradientsif theta_path is not None:theta_path.append(theta)plt.xlabel($x_1$, fontsize18)plt.axis([0, 2, 0, 15])plt.title(r$\eta {}$.format(eta), fontsize16)np.random.seed(42)
theta np.random.randn(2,1) # random initializationplt.figure(figsize(10,4))
plt.subplot(131); plot_gradient_descent(theta, eta0.02)
plt.ylabel($y$, rotation0, fontsize18)
plt.subplot(132); plot_gradient_descent(theta, eta0.1, theta_paththeta_path_bgd)
plt.subplot(133); plot_gradient_descent(theta, eta0.5)
plt.show()左图学习率太低需要太长时间找到解决方法中图学习率恰好经过几次迭代收敛出了最终解右图学习率太高算法发散直接跳过了数据区域且每次都离实际解决方案越来越远
可以通过网格搜索找到合适的学习率但需要限制迭代次数从而淘汰掉那些收敛耗时太长的模型 限制迭代次数的简单办法是在开始时设置一个非常大的迭代次数当梯度向量的值变得非常微小时中断即当梯度向量的范数变得低于容差时梯度下降到了几乎最小值 收敛速度若成本函数为凸函数且斜率没有陡峭变化如 MSE 的成本函数则具有固定学习率的批量梯度下降最终会收敛到最佳解若将容差缩小到原来的 1/10 以得到更精确的解算法将不得不运行 10 倍的时间
2. 随机梯度下降
随机梯度下降与使用整个训练集计算每一步的梯度算法特别慢的批量梯度下降相对随机梯度下降在每一步梯度计算时在训练集随机选择一个实例计算梯度算法很快可用于海量数据集的训练每次迭代只需要在内存中运行一个实例SGD 可以作为核外算法实现 随机梯度下降的随机性质让它比批量梯度下降要不规则得多成本函数不再是持续下降至最下值而是存在上下波动但整体上会慢慢下降最终接近最小值即时达到最小值依旧会反弹该算法的参数值只能是足够好不会是最优 逃离局部最优成本函数非常不规则时随机梯度下降可以跳出局部最小值相比批量梯度下降它更能找到全局最小值 模拟退火逐步降低学习率开始的步长较大快速进展和逃离局部最小值然后越来越小让算法尽量靠近全局最小值 学习率调度确认每个迭代学习率的函数
学习率降得太快可能陷入局部最小值学习率降得太慢可能需要太长时间走到最小值的附近提前结束训练可能导致得到一个次优的解决方案
学习率调度实现随机梯度下降
theta_path_sgd []
m len(X_b)
np.random.seed(42)n_epochs 50
t0, t1 5, 50 # learning schedule hyperparametersdef learning_schedule(t):return t0 / (t t1)theta np.random.randn(2, 1) # random initializationfor epoch in range(n_epochs):for i in range(m):if epoch 0 and i 20:y_predict X_new_b.dot(theta)style b- if i 0 else r--plt.plot(X_new, y_predict, style)random_index np.random.randint(m)xi X_b[random_index:random_index1]yi y[random_index:random_index1]gradients 2 * xi.T.dot(xi.dot(theta) - yi)eta learning_schedule(epoch * m i)theta theta - eta * gradientstheta_path_sgd.append(theta)plt.plot(X, y, b.)
plt.xlabel($x_1$, fontsize18)
plt.ylabel($y$, rotation0, fontsize18)
plt.axis([0, 2, 0, 15])
plt.show()随机选取事例某些实例可能每个轮次被选中多次有的实例则可能不会被选中
IID独立且均匀分布在训练过程中对实例进行随机混洗使用随机梯度下降时训练实例必须独立且均匀分布确保平均而言将参数拉向全局最优值 print(theta)
[[4.21076011][2.74856079]]使用 SGDRegressor 执行线性回归
from sklearn.linear_model import SGDRegressor
sgd_reg SGDRegressor(max_iter1000, tol1e-3, penaltyNone, eta00.1)
sgd_reg.fit(X, y.ravel())print(sgd_reg.intercept_, sgd_reg.coef_)[4.22520079] [2.79873691]max_iter最多可运行的轮次数tol轮次期间损失下降小于该值将停止训练eta0起始学习率
3. 小批量梯度下降
小批量梯度下降相比于基于完整训练集如批量梯度下降和基于一个实例如随机梯度下降来计算梯度小批量梯度下降在小型批量的随机实例集上计算梯度可以通过矩阵操作的硬件优化如 GPU来提高性能
小批量梯度下降比随机梯度下降在参数空间上的进展更稳定且最终更接近最小值但可能很难摆脱局部最小值局部最小值影响情况下不像线性回归而批量梯度下降最终会实际停留在最小值只是批量梯度下降每一步需要花费很多时间好的处理方式是使用良好的学习率调度让随机梯度下降和小批量梯度下降尽可能达到最小值
线性回归算法的比较
算法m 很大核外支持n 很大超参数要求缩放Scikit-Learn标准方程快否慢0否N/ASVD快否慢0否LinearRegression批量 GD慢否快2是SGDRegressor随机 GD快是快 2是SGDRegressor小批量 GD快是快 2是SGDRegressor
所有这些算法最终都具有非常相似的模型且以完全相同的方式进行预测
3. 多项式回归
多项式回归使用线性模型来拟合非线性模型比如将每个特征的幂次方添加为一个新特征然后在此扩展特征集上训练一个线性模型
多项式回归示例yax2bxcyax^2bxcyax2bxc
在二次方程 yax2bxcyax^2bxcyax2bxc 的基础上添加一些噪声
np.random.seed(42)m 100
X 6 * np.random.rand(m, 1) - 3
y 0.5 * X**2 X 2 np.random.randn(m, 1)plt.plot(X, y, b.)
plt.xlabel($x_1$, fontsize18)
plt.ylabel($y$, rotation0, fontsize18)
plt.axis([-3, 3, 0, 10])
plt.show()使用 PolynomialFeatures 类转换训练数据
将训练集中每个特征的评分二次多项式添加为新特征 from sklearn.preprocessing import PolynomialFeaturespoly_features PolynomialFeatures(degree2, include_biasFalse)X_poly poly_features.fit_transform(X)X[0]
array([-0.75275929]) X_poly[0] # 包含 X 的原始特征以及该特征的平方
array([-0.75275929, 0.56664654])将 LinearRegression 模型拟合到该扩展训练数据中 lin_reg LinearRegression()lin_reg.fit(X_poly, y)lin_reg.intercept_, lin_reg.coef_
(array([1.78134581]), array([[0.93366893, 0.56456263]]))即模型估算y^0.56x120.93x11.78\hat{y} 0.56x_1^2 0.93x_1 1.78y^0.56x120.93x11.78与原始函数相符y0.5x121.0x12.0高斯噪声y0.5x_1^2 1.0x_1 2.0 高斯噪声y0.5x121.0x12.0高斯噪声
多项式回归曲线
X_new np.linspace(-3, 3, 100).reshape(100, 1)
X_new_poly poly_features.transform(X_new)
y_new lin_reg.predict(X_new_poly)
plt.plot(X, y, b.)
plt.plot(X_new, y_new, r-, linewidth2, labelPredictions)
plt.xlabel($x_1$, fontsize18)
plt.ylabel($y$, rotation0, fontsize18)
plt.legend(locupper left, fontsize14)
plt.axis([-3, 3, 0, 10])
plt.show()存在多个特征时多项式回归能够找到特征之间的关系PolynomialFeatures 可以将特征的所有组合添加到给定的多项式阶数如存在两个特征 a 和 bdegress3 的 PolynomialFeatures 不仅会添加特征 a2、a3、b2、b3a^2、a^3、b^2、b^3a2、a3、b2、b3还会添加组合 ab、a2b、ab2ab、a^2b、ab^2ab、a2b、ab2
PolynomialFeaturesdegreed可以将一个包含 n 个特征的数组转换为包含 (nd)!d!n!\frac{(nd)!}{d!n!}d!n!(nd)! 个特征的数组因此要小心特征组合的数量爆炸
4. 学习曲线
高阶多项式回归的拟合曲线
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipelinefor style, width, degree in ((g-, 1, 300), (b--, 2, 2), (r-, 2, 1)):polybig_features PolynomialFeatures(degreedegree, include_biasFalse)std_scaler StandardScaler()lin_reg LinearRegression()polynomial_regression Pipeline([(poly_features, polybig_features),(std_scaler, std_scaler),(lin_reg, lin_reg),])polynomial_regression.fit(X, y)y_newbig polynomial_regression.predict(X_new)plt.plot(X_new, y_newbig, style, labelstr(degree), linewidthwidth)plt.plot(X, y, b., linewidth3)
plt.legend(locupper left)
plt.xlabel($x_1$, fontsize18)
plt.ylabel($y$, rotation0, fontsize18)
plt.axis([-3, 3, 0, 10])
plt.show()高阶多项式回归模型严重过拟合训练数据而线性模型欠拟合二次模型最能泛化数据集数据就是使用二次模型生成的
评估模型泛化性能的方法
交叉验证 若模型在训练数据上表现良好但交叉验证的指标泛化性能较差则模型过拟合若模型在训练数据和交叉验证表现都较差则说明欠拟合 学习曲线绘制模型在训练集和验证集上关于训练集大小或训练迭代的性能函数在不同大小的训练子集上多次训练模型观察期分别在训练集和验证集上的性能表现
学习曲线函数
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_splitdef plot_learning_curves(model, X, y):X_train, X_val, y_train, y_val train_test_split(X, y, test_size0.2, random_state10)train_errors, val_errors [], []for m in range(1, len(X_train) 1):model.fit(X_train[:m], y_train[:m])y_train_predict model.predict(X_train[:m])y_val_predict model.predict(X_val)train_errors.append(mean_squared_error(y_train[:m], y_train_predict))val_errors.append(mean_squared_error(y_val, y_val_predict))plt.plot(np.sqrt(train_errors), r-, linewidth2, labeltrain)plt.plot(np.sqrt(val_errors), b-, linewidth3, labelval)plt.legend(locupper right, fontsize14)plt.xlabel(Training set size, fontsize14)plt.ylabel(RMSE, fontsize14)分别截取前 1、2、… m 个实例作为训练集进行训练绘制其训练集和测试集上的性能效果
普通线性回归模型的学习曲线
lin_reg LinearRegression()
plot_learning_curves(lin_reg, X, y)
plt.axis([0, 80, 0, 3])
plt.show()当训练集只有一个或两个实例时模型可以很好的拟合训练集 train 曲线的 RMSE 从零开始但无法正确泛化验证集val 曲线误差很大随着新实例的加入模型不能完美拟合训练数据数据有噪声且并非线性但随着不断学习验证集误差逐渐降低训练集误差会一直上升直到达到平稳状态两条曲线最终接近但误差停留在较高的位置这说明模型是欠拟合训练集且添加更多训练实例也无济于事可能需要更复杂的模型或提供更好的特征
10 阶多项式模型的学习曲线
from sklearn.pipeline import Pipelinepolynomial_regression Pipeline([(poly_features, PolynomialFeatures(degree10, include_biasFalse)),(lin_reg, LinearRegression()),
])plot_learning_curves(polynomial_regression, X, y)
plt.axis([0, 80, 0, 3])
plt.show()与普通线性回归模型相比训练数据上的误差低了很多2 - 1train 与 val 曲线之间的间隙更大说明该模型在训练集上的性能要比在验证集上的性能要好很多这说明模型过拟合不过若使用更大的训练集两条曲线会继续接近
偏差与方差的权衡
统计学和机器学习的事实模型的泛化误差可以表示为偏差、方差、不可避免的误差这三个非常不同的误差之和
偏差错误的假设如假设数据是线性的而实际是二次的高偏差模型可能欠拟合训练数据方差模型对训练数据的细微变化过于敏感自由度越高可能方差越大如高阶多项式模型因此可能过拟合训练数据不可避免的误差数据本身的噪声减少该误差的办法唯有清理数据如修复数据源、检查并移除异常值等
增加模型复杂度通查会显著提升模型的方差并减少偏差反之降低模型复杂度则会提升模型的偏差并降低方差这其中需要试具体应用场景来权衡
5. 正则化线性模型
正则化即约束模型线性模型通常通过约束模型的权重来实现一种简单的方法是减少多项式的次数模型拥有的自由度越小则过拟合数据的难度就越大
1. 岭回归
岭回归也称 Tikhonov 正则化线性回归的正则化版本将等于 α∑i1nθi2\alpha \sum_{i1}^{n}\theta_i^2α∑i1nθi2 的正则化项添加到成本函数迫使学习算法拟合数据使模型权重尽可能小
仅在训练期间将正则化项添加到成本函数中训练完模型后使用非正则化的性能度量来评估模型的性能好的训练成本函数应该具有对优化友好的导数而用于测试的性能指标应该尽可能的接近最终目标如使用成本函数如对数损失来训练分类器但使用精度/召回率对其进行评估
岭回归的成本函数
J(θ)MSE(θ)α12∑i1nθi2J(\theta) MSE(\theta) \alpha \frac{1}{2} \sum_{i1}^{n} \theta_i^2 J(θ)MSE(θ)α21i1∑nθi2
α\alphaα控制要对模型进行正则化的程度的超参数若 α\alphaα 0则岭回归仅是一个线性回归若 α\alphaα 非常大则所有权重最终都非常接近于零结果是一条经过数据均值的平线θi\theta_iθi 从 θ1\theta_1θ1 开始偏置项 θ0\theta_0θ0 没有进行正则化
若定义 w 为特征权重的向量θ1\theta_1θ1 至 θn\theta_nθn则正则项等于 12(∥w∥2)2\frac{1}{2}(\lVert w\lVert_2)^221(∥w∥2)2其中 ∥w∥2\lVert w\lVert_2∥w∥2 表示权重向量的 ℓ2\ell_2ℓ2 范数
岭回归对输入特征的缩放敏感因此知悉岭回归之前需要缩放数据如使用 StandardScaler
不同 α\alphaα 值对线性数据训练的几种岭回归模型 np.random.seed(42)m 20X 3 * np.random.rand(m, 1)y 1 0.5 * X np.random.randn(m, 1) / 1.5X_new np.linspace(0, 3, 100).reshape(100, 1)使用 AndreLouis Cholesky 矩阵分解技术执行岭回归闭式解 from sklearn.linear_model import Ridgeridge_reg Ridge(alpha1, solvercholesky, random_state42)ridge_reg.fit(X, y)ridge_reg.predict([[1.5]])
array([[1.55071465]])ridge_reg Ridge(alpha1, solversag, random_state42)ridge_reg.fit(X, y)ridge_reg.predict([[1.5]])
array([[1.55072189]])from sklearn.linear_model import Ridgedef plot_model(model_class, polynomial, alphas, **model_kargs):for alpha, style in zip(alphas, (b-, g--, r:)):model model_class(alpha, **model_kargs) if alpha 0 else LinearRegression()if polynomial:model Pipeline([(poly_features, PolynomialFeatures(degree10, include_biasFalse)),(std_scaler, StandardScaler()),(regul_reg, model),])model.fit(X, y)y_new_regul model.predict(X_new)lw 2 if alpha 0 else 1plt.plot(X_new, y_new_regul, style, linewidthlw,labelr$\alpha {}$.format(alpha))plt.plot(X, y, b., linewidth3)plt.legend(locupper left, fontsize15)plt.xlabel($x_1$, fontsize18)plt.axis([0, 3, 0, 4])plt.figure(figsize(8, 4))
plt.subplot(121)
plot_model(Ridge, polynomialFalse, alphas(0, 10, 100), random_state42)
plt.ylabel($y$, rotation0, fontsize18)
plt.subplot(122)
plot_model(Ridge, polynomialTrue, alphas(0, 10**-5, 1), random_state42)
plt.show()左普通岭模型线性预测右带有岭正则化的多项式回归使用 PolynomialFeatures(degree10) 扩展数据使用 StandardScaler 进行缩放最后将岭模型应用于结果特征
随着 α\alphaα 的增加预测更平坦不极端、更合理模型的方差减少偏差增加 闭式解的岭回归
θ^(XTXαA)−1XTy\hat{\theta} (X^T X\alpha A)^{-1}X^T y θ^(XTXαA)−1XTy
A 是 (n1)×(n1)(n1) \times (n1)(n1)×(n1) 单位矩阵
使用随机梯度下降 sgd_reg SGDRegressor(penaltyl2)sgd_reg.fit(X, y.ravel())sgd_reg.predict([[1.5]])
array([1.47012588])超参数 penalty 设置的是使用正则项的类型12 表示希望 SGD 在成本函数中添加一个正则项等于权重向量的 ℓ2\ell_2ℓ2 范数的平方的一半即岭回归
2. Lasso 回归
Lasso 回归最小绝对收缩和选择算子回归Least Absolute Shrinkage and Selection Operator Regression简称 Lasso 回归向成本函数添加一个正则项权重向量的 ℓ1\ell_1ℓ1 范数
Lasso 回归成本函数
J(θ)MSE(θ)α∑i1n∣θi∣J(\theta) MSE(\theta) \alpha \sum_{i1}^{n} \lvert \theta_i \lvert J(θ)MSE(θ)αi1∑n∣θi∣
使用不同级别的 Lasso 正则化
from sklearn.linear_model import Lassoplt.figure(figsize(8, 4))
plt.subplot(121)
plot_model(Lasso, polynomialFalse, alphas(0, 0.1, 1), random_state42)
plt.ylabel($y$, rotation0, fontsize18)
plt.subplot(122)
plot_model(Lasso, polynomialTrue, alphas(0, 10**-7, 1), random_state42)plt.show()Lasso 回归倾向于完全消除掉最不重要的特征的权重α10−7\alpha 10^{-7}α10−7 看起来像二次的因为所有高阶多项式的特征权重都等于零Lasso 回归会自动执行特征选择并输出一个稀疏模型只有很少的特征有非零权重
Lasso 成本函数在 $ \theta 0 $ 处是不可微的可以使用子梯度向量 g 代替任何 θi0\theta_i 0θi0;
带有 Lasso 成本函数的梯度下降的子梯度向量方程
g(θ,J)∇θMSE(θ)α(sin(θ1)sin(θ2)...sin(θn))其中sin(θi){−1如果θi00如果θi01如果θi0g(\theta, J) \nabla_{\theta} MSE(\theta) \alpha \begin{pmatrix} sin(\theta_1) \\ sin(\theta_2) \\ ... \\ sin(\theta_n) \end{pmatrix} 其中 sin(\theta_i) \begin{cases} -1 \; 如果 \theta_i 0 \\ 0 \; 如果 \theta_i 0 \\ 1 \; 如果 \theta_i 0 \end{cases} g(θ,J)∇θMSE(θ)αsin(θ1)sin(θ2)...sin(θn)其中sin(θi)⎩⎨⎧−1如果θi00如果θi01如果θi0
3. 弹性网络
弹性网络介于岭回归和 Lasso 回归之间的中间地带正则项式岭和 Lasso 正则项的简单混合通过 r 控制混合比r0 时弹性网络等效于岭回归r1 时弹性网络等效于 Lasso 回归
弹性网络成本函数
J(θ)MSE(θ)rα∑i1n∣θi∣1−r2α∑i1nθi2J(\theta) MSE(\theta) r\alpha \sum_{i1}^{n} \lvert \theta_i \lvert \frac{1-r}{2} \alpha \sum_{i1}^{n} \theta_i^2 J(θ)MSE(θ)rαi1∑n∣θi∣21−rαi1∑nθi2
通常有正则化比没有更可取大多数情况下应避免纯线性回归此时岭回归是不错的默认选择当实际用到的特征只有少数几个可以考虑 Lasso 回归或弹性网络它们会将无用特征的权重降为零弹性网络一半由于 Lasso 回归特征数据超过实例数量或者几个特征强相关时Lasso 回归表现可能很不稳定
ElasticNet 示例 from sklearn.linear_model import ElasticNetelastic_net ElasticNet(alpha0.1, l1_ratio0.5, random_state42)elastic_net.fit(X, y)elastic_net.predict([[1.5]])
array([1.54333232])4. 提前停止
提前停止对于梯度下降这类迭代学习算法在验证误差达到最小值时停止训练通过早期停止法一旦验证误差达到最小值就立刻停止训练 随机和小批量梯度下降时曲线不是平滑的可能很难知道是否达到最小值此时可以仅在验证错误超过最小值一段时间后停止确信模型不会做到更好时然后回滚模型参数到验证误差最小的位置
提前停止法示例
np.random.seed(42)
m 100
X 6 * np.random.rand(m, 1) - 3
y 2 X 0.5 * X**2 np.random.randn(m, 1)X_train, X_val, y_train, y_val train_test_split(X[:50], y[:50].ravel(), test_size0.5, random_state10)from copy import deepcopypoly_scaler Pipeline([(poly_features, PolynomialFeatures(degree90, include_biasFalse)),(std_scaler, StandardScaler())
])X_train_poly_scaled poly_scaler.fit_transform(X_train)
X_val_poly_scaled poly_scaler.transform(X_val)sgd_reg SGDRegressor(max_iter1, warm_startTrue, penaltyNone,learning_rateconstant, eta00.0005, random_state42)minimum_val_error float(inf)
best_epoch None
best_model None
for epoch in range(1000):sgd_reg.fit(X_train_poly_scaled, y_train) # continues where it left offy_val_predict sgd_reg.predict(X_val_poly_scaled)val_error mean_squared_error(y_val, y_val_predict)if val_error minimum_val_error:minimum_val_error val_errorbest_epoch epochbest_model deepcopy(sgd_reg)warm_startTrue 表示调用 fit() 方法时在停止的地方继续训练而不是从头开始
6. 逻辑回归
逻辑回归Logistic 回归Logit 回归广泛应用于估算一个示例属于某个特定类别的概率二元分类器预估概率高于 50% 则模型预测该实例属于该类别称正类反之则预测不是该类别称负类
1. 估计概率
逻辑回归模型也是计算输入特征的加权和加上偏置项但不同于线性回归模型直接输出结果它输出的是梳理逻辑值
逻辑回归模型的估计概率向量化形式
p^hθ(x)σ(xTθ)\hat{p} h_\theta(x) \sigma(x^T\theta) p^hθ(x)σ(xTθ)
逻辑函数
σ(t)11exp(−t)\sigma(t) \frac{1}{1exp(-t)} σ(t)1exp(−t)1
分数 t 称为 logit估计概率 p 的对上logit§ log(p/(1-p))与 logistic 函数相反 对数也称对数奇数是正类的估计概率与父类的估计概率之比的对数
t np.linspace(-10, 10, 100)
sig 1 / (1 np.exp(-t))
plt.figure(figsize(9, 3))
plt.plot([-10, 10], [0, 0], k-)
plt.plot([-10, 10], [0.5, 0.5], k:)
plt.plot([-10, 10], [1, 1], k:)
plt.plot([0, 0], [-1.1, 1.1], k-)
plt.plot(t, sig, b-, linewidth2, labelr$\sigma(t) \frac{1}{1 e^{-t}}$)
plt.xlabel(t)
plt.legend(locupper left, fontsize20)
plt.axis([-10, 10, -0.1, 1.1])
plt.show()逻辑回归模型估算出实例 x 属于整理的概率 p^hθ(x)\hat{p} h_\theta(x)p^hθ(x)就可以预测 y^\hat{y}y^
逻辑回归模型预测
y^{0如果p^0.51如果p^≥0.5\hat{y} \begin{cases} 0如果 \hat{p} 0.5 \\ 1如果 \hat{p} \geq 0.5 \end{cases} y^{0如果p^0.51如果p^≥0.5
当 t0t 0t0 时σ(t)0.5\sigma(t) 0.5σ(t)0.5当 t≥0t \geq 0t≥0 时σ(t)≥0.5\sigma(t) \geq 0.5σ(t)≥0.5因此若 XTθX^T\thetaXTθ 是正类逻辑回归模型预测结果就是 1若是负类则预测结果为 0
2. 训练和成本函数
训练的目的是设置参数向量 θ\thetaθ是模型对正类实例做出高概率估算对负类实例做出低概率估算
单个训练实例的成本函数
c(θ){−log(p^)如果y1−log(1−p^)如果y0c(\theta) \begin{cases} -log(\hat{p})如果 y1 \\ -log(1-\hat{p})如果 y0 \end{cases} c(θ){−log(p^)如果y1−log(1−p^)如果y0
当 t 接近 0 时-log(t) 会变得非常大若模型估算一个正类实例的概率接近与 0成本降变得很高负类实例同理对一个负类实例估算概率接近 0对一个正类实例估算概率接近与 1而成本则都解决与 0这正式我们想要的
逻辑回归成本函数对数损失
整个训练集的成本函数是所有训练实例的平均成本可以用一个对数损失单一表达式表示
J(θ)−1m∑i1m[yilog(p^i)(1−y(i))log(1−p^(i))]J(\theta) -\frac{1}{m} \sum_{i1}^{m}[y^{i} log(\hat{p}^i) (1-y^{(i)})log(1 - \hat{p}^{(i)})] J(θ)−m1i1∑m[yilog(p^i)(1−y(i))log(1−p^(i))]
该函数没有已知的闭式方程不存在一个标准方程的等价方程来计算出最小化成本函数的 θ\thetaθ 值但这是一个凸函数通过梯度下降等任意优化算法可以找出全局最小值学习率不太高、运行足够长时间的情况下
逻辑成本函数偏导数
∂∂θjJ(θ)1m∑i1m(σ(θTx(i))−y(i))xj(i)\frac{\partial}{\partial\theta_j} J(\theta) \frac{1}{m} \sum_{i1}^{m} (\sigma (\theta^Tx^{(i)}) - y^{(i)}) x_j^{(i)} ∂θj∂J(θ)m1i1∑m(σ(θTx(i))−y(i))xj(i)
对每个实例计算预测误差并将其乘以第 j 个特征值然后计算所有训练实例的平均值有了包含所有偏导数的梯度向量就可以使用梯度下降算法
3. 决策边界
基于花瓣宽度特征创建一个分类器检测维吉尼亚鸢尾花 from sklearn import datasetsiris datasets.load_iris()list(iris.keys())
[data,target,frame,target_names,DESCR,feature_names,filename,data_module] print(iris.DESCR)
.. _iris_dataset:Iris plants dataset
--------------------**Data Set Characteristics:**:Number of Instances: 150 (50 in each of three classes):Number of Attributes: 4 numeric, predictive attributes and the class:Attribute Information:- sepal length in cm- sepal width in cm- petal length in cm- petal width in cm- class:- Iris-Setosa- Iris-Versicolour- Iris-Virginica:Summary Statistics: Min Max Mean SD Class Correlation sepal length: 4.3 7.9 5.84 0.83 0.7826
...on Information Theory, May 1972, 431-433.- See also: 1988 MLC Proceedings, 54-64. Cheeseman et als AUTOCLASS IIconceptual clustering system finds 3 classes in the data.- Many, many more ...X iris[data][:, 3:] # petal widthy (iris[target] 2).astype(np.int64) # 1 if Iris virginica, else 0训练一个逻辑回归模型
from sklearn.linear_model import LogisticRegression
log_reg LogisticRegression(solverlbfgs, random_state42)
log_reg.fit(X, y)花瓣宽度在 0 到 3cm 之间的鸢尾花模型估算出的概率如下
X_new np.linspace(0, 3, 1000).reshape(-1, 1)
y_proba log_reg.predict_proba(X_new)
decision_boundary X_new[y_proba[:, 1] 0.5][0][0]plt.figure(figsize(8, 3))
plt.plot(X[y0], y[y0], bs)
plt.plot(X[y1], y[y1], g^)
plt.plot([decision_boundary, decision_boundary], [-1, 2], k:, linewidth2)
plt.plot(X_new, y_proba[:, 1], g-, linewidth2, labelIris virginica)
plt.plot(X_new, y_proba[:, 0], b--, linewidth2, labelNot Iris virginica)
plt.text(decision_boundary0.02, 0.15, Decision boundary, fontsize14, colork, hacenter)
plt.arrow(decision_boundary, 0.08, -0.3, 0, head_width0.05, head_length0.1, fcb, ecb)
plt.arrow(decision_boundary, 0.92, 0.3, 0, head_width0.05, head_length0.1, fcg, ecg)
plt.xlabel(Petal width (cm), fontsize14)
plt.ylabel(Probability, fontsize14)
plt.legend(loccenter left, fontsize14)
plt.axis([0, 3, -0.02, 1.02])
plt.show()维吉尼亚鸢尾花三角形的花瓣宽度范围为 1.4 ~ 2.5 cm其他两种鸢尾花正方形花瓣宽度范围为 0.1 ~ 1.8 cm存在一部分重叠
花瓣宽度超过 2cm 的花和低于 1cm 的花可以很明确其分别对应维吉尼亚鸢尾花和非维吉尼亚鸢尾花对正类和负类输出了高概率值而两个极端中间部分不太好把握只能返回一个可能性最大的类别概率相等处表示正类和父类的可能性都是 50%这就是一个决策边界
基于花瓣宽度和花瓣长度两个特征创建一个分类器检测维吉尼亚鸢尾花
from sklearn.linear_model import LogisticRegressionX iris[data][:, (2, 3)] # petal length, petal width
y (iris[target] 2).astype(np.int64)log_reg LogisticRegression(solverlbfgs, C10**10, random_state42)
log_reg.fit(X, y)x0, x1 np.meshgrid(np.linspace(2.9, 7, 500).reshape(-1, 1),np.linspace(0.8, 2.7, 200).reshape(-1, 1),
)
X_new np.c_[x0.ravel(), x1.ravel()]y_proba log_reg.predict_proba(X_new)plt.figure(figsize(10, 4))
plt.plot(X[y 0, 0], X[y 0, 1], bs)
plt.plot(X[y 1, 0], X[y 1, 1], g^)zz y_proba[:, 1].reshape(x0.shape)
contour plt.contour(x0, x1, zz, cmapplt.cm.brg)left_right np.array([2.9, 7])
boundary -(log_reg.coef_[0][0] * left_right log_reg.intercept_[0]) / log_reg.coef_[0][1]plt.clabel(contour, inline1, fontsize12)
plt.plot(left_right, boundary, k--, linewidth3)
plt.text(3.5, 1.5, Not Iris virginica, fontsize14, colorb, hacenter)
plt.text(6.5, 2.3, Iris virginica, fontsize14, colorg, hacenter)
plt.xlabel(Petal length, fontsize14)
plt.ylabel(Petal width, fontsize14)
plt.axis([2.9, 7, 0.8, 2.7])
plt.show()虚线表示模型估算概率为 50% 的点即模型的决策边界线性的边界每条平行线代表一个模型输出的特定概率
逻辑回归模型可以用 ℓ1\ell_1ℓ1 或 ℓ2\ell_2ℓ2 惩罚函数来正则化Scikit-Learn 默认添加 ℓ2\ell_2ℓ2 函数CScikit-Learn LogisticRegression 模型的正则化强度超参数α\alphaα 的反值C 值越高对模型的正则化越少
4. Softmax 回归
Softmax 回归又叫多元逻辑回归逻辑回归模型的推广可以直接支持多个类别每次只能预测一个类即多类而非多输出只能与互斥的类一起使用而不需训练并组合多个二元分类器
类 k 的 Softmax 分数
Sk(x)xTθ(k)S_k(x) x^T\theta^{(k)} Sk(x)xTθ(k)
给定一个实例 xSoftmax 回归模型先计算出每个类 k 的分数 Sk(x)S_k(x)Sk(x)然后对这些分数应用 softmax 函数归一化指数估算出每个类的概率
每个类有自己的特定参数向量 θk\theta^{k}θk所有这些向量通常作为行存储在参数矩阵 Θ\ThetaΘ
Softmax 函数
p^kσ(s(x))kexp(sk(x))∑j1Kexp(sj(x))\hat{p}_k \sigma(s(x))_k \frac{exp(s_k(x))}{\sum_{j1}^{K} exp(s_j(x))} p^kσ(s(x))k∑j1Kexp(sj(x))exp(sk(x))
K类数s(x)一个向量包含实例 x 的每个类的分数σ(s(x))k\sigma(s(x))_kσ(s(x))k实例 x 属于类 k 的估计概率给定该实例每个类的分数
Softmax 回归分类预测
y^argmaxkσ(s(x))kargmaxksk(x)argmaxk((θ(k))Tx)\hat{y} argmax_k \; \sigma(s(x))_k argmax_k \; s_k(x) argmax_k((\theta^{(k)})^Tx) y^argmaxkσ(s(x))kargmaxksk(x)argmaxk((θ(k))Tx)
argmax 运算符返回使函数最大化的变量值此处返回使估计概率 σ(s(x))k\sigma(s(x))_kσ(s(x))k 最大化的 k 值
交叉熵成本函数
通常用于衡量一组估算出的类概率跟目标类的匹配程度
J(Θ)−1m∑i1m∑k1Kyk(i)log(p^k(i))J(\Theta) - \frac{1}{m} \sum_{i1}^{m} \sum_{k1}^{K} y_k^{(i)} log(\hat{p}_k^{(i)}) J(Θ)−m1i1∑mk1∑Kyk(i)log(p^k(i))
yk(i)y_k^{(i)}yk(i)属于类 k 的第 i 个实例的目标概率一般为 1 或 0表示实例是否属于该类
当只有两个类K2时此成本函数等效于逻辑回归的成本函数对数损失
类 k 的交叉熵梯度向量
成本函数相对于 θ(k)\theta^{(k)}θ(k) 的梯度向量计算每个类的梯度向量然后使用梯度下降或其他任意优化算法找到最小化成本函数的参数矩阵 Θ\ThetaΘ
∇θ(k)J(Θ)1m∑i1m(p^k(i)−yk(i))x(i)\nabla_{\theta(k)}J(\Theta) \frac{1}{m} \sum_{i1}^{m} (\hat{p}_k^{(i)} - y_k^{(i)}) x^{(i)} ∇θ(k)J(Θ)m1i1∑m(p^k(i)−yk(i))x(i)
使用 Softmax 回归将鸢尾花分为三类
X iris[data][:, (2, 3)] # petal length, petal width
y iris[target]softmax_reg LogisticRegression(multi_classmultinomial, solverlbfgs, C10, random_state42)
softmax_reg.fit(X, y)LogisticRegressio 默认使用一对多的训练方式设置超参数 multi_class 为 multinomial 可以切换为 Softmax 回归solverlbfgs指定支持 Softmax 回归的求解器C正则化超参数默认使用 ℓ2\ell_2ℓ2 正则化;
from matplotlib.colors import ListedColormap
x0, x1 np.meshgrid(np.linspace(0, 8, 500).reshape(-1, 1),np.linspace(0, 3.5, 200).reshape(-1, 1),
)
X_new np.c_[x0.ravel(), x1.ravel()]y_proba softmax_reg.predict_proba(X_new)
y_predict softmax_reg.predict(X_new)zz1 y_proba[:, 1].reshape(x0.shape)
zz y_predict.reshape(x0.shape)plt.figure(figsize(10, 4))
plt.plot(X[y 2, 0], X[y 2, 1], g^, labelIris virginica)
plt.plot(X[y 1, 0], X[y 1, 1], bs, labelIris versicolor)
plt.plot(X[y 0, 0], X[y 0, 1], yo, labelIris setosa)custom_cmap ListedColormap([#fafab0, #9898ff, #a0faa0])plt.contourf(x0, x1, zz, cmapcustom_cmap)
contour plt.contour(x0, x1, zz1, cmapplt.cm.brg)
plt.clabel(contour, inline1, fontsize12)
plt.xlabel(Petal length, fontsize14)
plt.ylabel(Petal width, fontsize14)
plt.legend(loccenter left, fontsize14)
plt.axis([0, 7, 0, 3.5])
plt.show()任何两个类之间的决策边界都是线性的估算概率可能是低于 50% 的在所有决策边界相交的地方所有类的估算概率都为 33% softmax_reg.predict([[5, 2]])
array([2]) softmax_reg.predict_proba([[5, 2]])
array([[6.38014896e-07, 5.74929995e-02, 9.42506362e-01]])花瓣长 5cm宽 2cm模型预测结果为 94.2% 是维吉尼亚鸢尾5.8% 是变色鸢尾
上一篇「ML 实践篇」分类系统图片数字识别专栏《机器学习》