第四章 训练模型
· Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow, 2nd Edition, by Aurélien Géron (O’Reilly). Copyright 2019 Aurélien Géron, 978-1-492-03264-9.
· 环境:Anaconda(Python 3.8) + Pycharm
· 学习时间:2022.04.16
到目前为止,我们已经探讨了不同机器学习的模型,但是它们各自的训练算法在很大程度上还是一个黑匣子。回顾前几章里的部分案例,你大概感到非常惊讶,在对系统内部一无所知的情况下,居然已经实现了这么多:优化了一个回归系统,改进了一个数字图片分类器,从零开始构建了一个垃圾邮件分类器,所有这些,你都不知道它们实际是如何工作的。确实是这样,在许多情况下,你并不需要了解实施细节。
但是,很好地理解系统如何工作也是非常有帮助的。针对你的任务,它有助于快速定位到合适的模型、正确的训练算法,以及一套适当的超参数。不仅如此,后期还能让你更高效地执行错误调试和错误分析。最后还要强调一点,本章探讨的大部分主题对于理解、构建和训练神经网络(本书第二部分)是至关重要的。
本章我们将从最简单的模型之一——线性回归模型,开始介绍两种非常不同的训练模型的方法:
- 通过“闭式”方程,直接计算出最拟合训练集的模型参数(也就是使训练集上的成本函数最小化的模型参数);
- 使用迭代优化的方法,即梯度下降(GD),逐渐调整模型参数直至训练集上的成本函数调至最低,最终趋同于第一种方法计算出来的模型参数。我们还会研究几个梯度下降的变体,包括批量梯度下降、小批量梯度下降以及随机梯度下降。等我们进入到第二部分神经网络的学习时,会频繁地使用这几个的变体。
接着我们将会进入多项式回归的讨论,这是一个更为复杂的模型,更适合非线性数据集。由于该模型的参数比线性模型更多,因此更容易造成对训练数据过拟合,我们将使用学习曲线来分辨这种情况是否发生。然后,再介绍几种正则化技巧,降低过拟合训练数据的风险。
最后,我们将学习两种经常用于分类任务的模型:Logistic回归和Softmax回归。
本章将会出现不少数学公式,需要用到线性代数和微积分的一些基本概念。要理解这些方程式,你需要知道什么是向量和矩阵,如何转置向量和矩阵,什么是点积、逆矩阵、偏导数。如果你不熟悉这些概念,请先通过在线补充材料中的Jupyter notebook,进行线性代数和微积分的入门学习。对于极度讨厌数学的读者,还是需要学习这一章,但是可以跳过那些数学公式,希望文字足以让你了解大多数的概念。
4.1 线性回归
线性模型就是对输入特征加权求和,再加上一个我们称为偏置项(也称为截距项)的常数,以此进行预测。
y = θ 0 + θ 1 x 1 + θ 2 x 2 + … … + θ n x n y = θ_0 + θ_1x_1 +θ_2x_2+ …… +θ_nx_n y=θ0+θ1x1+θ2x2+……+θnxn
线性回归模型预测(向量化形式): y = h θ ( x ) = θ ⋅ x y = h_θ(x) = θ·x y=hθ(x)=θ⋅x。
在机器学习中,向量通常表示为列向量,是有单一列的二维数组。如果 θ θ θ和 x x x为列向量,则预测为$y = θ^Tx , 其 中 ,其中 ,其中θT$为$θ$(行向量而不是列向量)的转置,且$θTx 为 θ 为θ 为θT 和 和 和x$的矩阵乘积。
这就是线性回归模型,我们该怎样训练线性回归模型呢?回想一下,训练模型就是设置模型参数直到模型最拟合训练集的过程。为此,我们首先需要知道怎么测量模型对训练数据的拟合程度是好还是差。在第2章中,我们了解到回归模型最常见的性能指标是均方根误差(RMSE)。因此,在训练线性回归模型时,你需要找到最小化RMSE的 θ θ θ值。在实践中,将均方误差(MSE)最小化比最小化RMSE更为简单,二者效果相同(因为使函数最小化的值,同样也使其平方根最小)。
线性回归模型的MSE成本函数: M S E = ( X , h 0 ) = 1 m ∑ i = 1 m ( θ T x ( i ) − y ( i ) ) 2 MSE = (X, h_0) = \frac{1}{m}\sum^m_{i=1}(θ^Tx^{(i)}-y^{(i)})^2 MSE=(X,h0)=m1∑i=1m(θTx(i)−y(i))2。
4.1.1 标准方程
为了得到使成本函数最小的θ值,有一个闭式解方法——也就是一个直接得出结果的数学方程,即标准方程。
θ ′ = ( X T X ) − 1 X T y θ' = (X^TX)^{-1}X^Ty θ′=(XTX)−1XTy,我们生成一些线性数据来测试这个公式:
import numpy as np
import matplotlib.pyplot as plt
# 随机生成数据
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
X_b = np.c_[np.ones((100, 1)), X] # add x0 = 1 to each instance
theta_best = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y) # dot()方法计算矩阵内积
print(theta_best)
# 输出:期待的是θ0=4,θ1=3得到的是θ0=3.6,θ1=3.2。非常接近,噪声的存在使其不可能完全还原为原本的函数
# 根据参数做出预测
X_new = np.array([[0], [2]])
X_new_b = np.c_[np.ones((2, 1)), X_new] # add x0 = 1 to each instance
y_predict = X_new_b.dot(theta_best)
print(y_predict)
# 绘制模型的预测结果
plt.plot(X_new, y_predict, "r-")
plt.plot(X, y, "b.")
plt.axis([0, 2, 0, 15])
plt.show()
使用Scikit-Learn执行线性回归很简单:
from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression() # 实例化线性模型
lin_reg.fit(X, y) # 训练模型
print(lin_reg.intercept_, lin_reg.coef_) # 输出模型训练后的参数
print(lin_reg.predict(X_new)) # 进行预测
# LinearRegression类基于scipy.linalg.lstsq()函数(名称代表“最小二乘”),你可以直接调用它:
theta_best_svd, residuals, rank, s = np.linalg.lstsq(X_b, y, rcond=1e-6)
print(theta_best_svd) # 输出最优的参数
# LinearRegression()模型的参数和scipy.linalg.lstsq()函数的参数输出是一致的
scipy.linalg.lstsq()
函数计算 θ ′ = X + y θ' = X^+y θ′=X+y ,其中 X + X^+