python 机器学习算法(用Python做科学计算工具篇)
python 机器学习算法(用Python做科学计算工具篇)我们可以使用另一个使用正则化的线性估计器,即 Ridge估计器。这个估计器通过将系数缩小到零来规范化系数,假设非常高的相关性通常是虚假的。alpha 参数控制使用的收缩量。np.random.seed(0) for _ in range(6): noisy_X = X np.random.normal(loc=0 scale=.1 size=X.shape) plt.plot(noisy_X y 'o') regr.fit(noisy_X y) plt.plot(X_test regr.predict(X_test)) 正如我们所见,我们的线性模型捕获并放大了数据中的噪声。它显示了很多差异。让我们从一个简单的一维回归问题开始。这将帮助我们轻松地可视化数据和模型,并将结果轻松推广到更高维的数据集。我们将探讨一个简单的 线性回归问
所需基本库
- numpy
- scipy
- matplotlib
- 简介:问题设置
- 使用 scikit-learn 进行机器学习的基本原理
- 监督学习:手写数字的分类
- 监督学习:住房数据的回归
- 测量预测性能
- 无监督学习:降维和可视化
- 特征脸示例:链接 PCA 和 SVM
- 参数选择、验证和测试
6.8. 参数选择、验证和测试6.8.1. 超参数、过拟合和欠拟合
与验证和交叉验证相关的问题是机器学习实践中最重要的一些方面。为您的数据选择最佳模型至关重要,并且是机器学习从业者经常不理解的一个问题。
核心问题是:如果我们的估算器表现不佳,我们应该如何前进?
- 使用更简单或更复杂的模型?
- 为每个观察到的数据点添加更多特征?
- 添加更多训练样本?
答案往往是违反直觉的。特别是,有时使用更复杂的模型会产生更差的结果。此外,有时添加训练数据不会改善您的结果。确定哪些步骤将改进您的模型的能力是将成功的机器学习从业者与不成功的人区分开来。
偏差方差权衡:简单回归问题的说明让我们从一个简单的一维回归问题开始。这将帮助我们轻松地可视化数据和模型,并将结果轻松推广到更高维的数据集。我们将探讨一个简单的 线性回归问题,其中sklearn.linear_model.
X = np.c_[ .5 1].T
y = [.5 1]
X_test = np.c_[ 0 2].T
没有噪音,因为线性回归完美地拟合了数据
from sklearn import linear_model
regr = linear_model.LinearRegression()
regr.fit(X y)
plt.plot(X y 'o')
plt.plot(X_test regr.predict(X_test))
在现实生活中,我们的数据中有噪声(例如测量噪声):
np.random.seed(0)
for _ in range(6):
noisy_X = X np.random.normal(loc=0 scale=.1 size=X.shape)
plt.plot(noisy_X y 'o')
regr.fit(noisy_X y)
plt.plot(X_test regr.predict(X_test))
正如我们所见,我们的线性模型捕获并放大了数据中的噪声。它显示了很多差异。
我们可以使用另一个使用正则化的线性估计器,即 Ridge估计器。这个估计器通过将系数缩小到零来规范化系数,假设非常高的相关性通常是虚假的。alpha 参数控制使用的收缩量。
regr = linear_model.Ridge(alpha=.1)
np.random.seed(0)
for _ in range(6):
noisy_X = X np.random.normal(loc=0 scale=.1 size=X.shape)
plt.plot(noisy_X y 'o')
regr.fit(noisy_X y)
plt.plot(X_test regr.predict(X_test))
plt.show()
正如我们所看到的,估计器显示的方差要小得多。然而,它系统地低估了系数。它表现出有偏见的行为。
这是偏差/方差权衡的典型示例:非正则化估计器没有偏差,但它们可以显示很多方差。高度正则化的模型方差很小,但偏差很大。这种偏差不一定是坏事:重要的是选择偏差和方差之间的权衡,以实现最佳预测性能。对于特定的数据集,有一个与数据可以支持的最高复杂度相对应的最佳位置,具体取决于噪声量和可用观察值。
6.8.2. 可视化偏差/方差权衡给定特定的数据集和模型(例如多项式),我们想了解偏差(欠拟合)或方差是否会限制预测,以及如何调整超参数(此处d为多项式的次数)以提供最佳拟合。
在给定的数据上,让我们拟合一个不同程度的简单多项式回归模型:
在上图中,我们看到了三个不同值的拟合d。对于,数据欠拟合。这意味着该模型过于简单:没有一条直线可以很好地拟合这些数据。在这种情况下,我们说该模型存在高偏差。模型本身是有偏差的,这将反映在数据拟合不佳的事实上。在另一个极端,对于d = 1d = 6数据过拟合。这意味着该模型有太多的自由参数(在这种情况下为 6 个),可以对其进行调整以完美拟合训练数据。但是,如果我们在该图中添加一个新点,它很可能与代表 6 度拟合的曲线相距甚远。在这种情况下,我们说模型存在高方差。术语“高方差”的原因是,如果任何输入点略有变化,可能会导致模型非常不同。
在中间,对于,我们找到了一个很好的中点。它很好地拟合了数据,并且不会受到两边图中所示的偏差和方差问题的影响。我们想要的是一种定量识别偏差和方差的方法,并优化元参数(在本例中为多项式次数 d)以确定最佳算法。d = 2
使用 scikit-learn 进行多项式回归
多项式回归是通过流水线 polynomialFeatures 和 a构建的LinearRegression:
>>>
>>> from sklearn.pipeline import make_pipeline
>>> from sklearn.preprocessing import PolynomialFeatures
>>> from sklearn.linear_model import LinearRegression
>>> model = make_pipeline(PolynomialFeatures(degree=2) LinearRegression())
验证曲线
让我们像上面的例子一样创建一个数据集:
>>>
>>> def generating_func(x err=0.5):
... return np.random.normal(10 - 1. / (x 0.1) err)
>>> # randomly sample more data
>>> np.random.seed(1)
>>> x = np.random.random(size=200)
>>> y = generating_func(x err=1.)
量化模型偏差和方差的核心是将其应用于测试数据,从与火车相同的分布中采样,但这将捕获独立的噪声:
>>>
>>> xtrain xtest ytrain ytest = train_test_split(x y test_size=0.4)
验证曲线验证曲线包括改变模型参数,该参数控制其复杂性(这里是多项式的次数)并测量模型在训练数据和测试数据上的误差(例如,使用交叉验证)。然后调整模型参数以使测试误差最小化:
我们sklearn.model_selection.validation_curve()用来计算训练和测试误差,并绘制它:
>>>
>>> from sklearn.model_selection import validation_curve
>>> degrees = np.arange(1 21)
>>> model = make_pipeline(PolynomialFeatures() LinearRegression())
>>> # Vary the "degrees" on the pipeline step "polynomialfeatures"
>>> train_scores validation_scores = validation_curve(
... model x[: np.newaxis] y
... param_name='polynomialfeatures__degree'
... param_range=degrees)
>>> # Plot the mean train score and validation score across folds
>>> plt.plot(degrees validation_scores.mean(axis=1) label='cross-validation')
[<matplotlib.lines.Line2D object at ...>]
>>> plt.plot(degrees train_scores.mean(axis=1) label='training')
[<matplotlib.lines.Line2D object at ...>]
>>> plt.legend(loc='best')
<matplotlib.legend.Legend object at ...>
该图显示了为什么验证很重要。在图的左侧,我们有非常低的多项式,它对数据的拟合不足。这导致训练集和验证集的解释方差都很低。在图的最右侧,我们有一个非常高的多项式,它过度拟合了数据。这可以从训练解释方差非常高的事实中看出,而在验证集上却很低。选择d大约 4 或 5 可以让我们获得最佳权衡。
精明的读者会意识到这里有些不对劲:在上面的情节中,给出了最好的结果。但在前面的图中,我们发现这大大过度拟合了数据。这里发生了什么?不同之处在于使用的训练点数。在前面的示例中,只有八个训练点。在这个例子中,我们有 100 个。作为一般经验法则,使用的训练点越多,可以使用的模型就越复杂。但是,对于给定的模型,您如何确定更多的训练点是否会有所帮助?对此有用的诊断是学习曲线。d = 4d = 6
学习曲线学习曲线将训练和验证分数显示为训练点数的函数。请注意,当我们在训练数据的一个子集上进行训练时,训练分数是使用这个子集计算的,而不是完整的训练集。该曲线给出了添加训练样本的益处的定量视图。
问题:
- 随着训练样本数量的增加,您期望看到的训练分数是多少?对于验证分数?
- 您希望训练分数高于还是低于验证分数?你会期望这会改变吗?
scikit-learn提供 sklearn.model_selection.learning_curve():
>>>
>>> from sklearn.model_selection import learning_curve
>>> train_sizes train_scores validation_scores = learning_curve(
... model x[: np.newaxis] y train_sizes=np.logspace(-1 0 20))
>>> # Plot the mean train score and validation score across folds
>>> plt.plot(train_sizes validation_scores.mean(axis=1) label='cross-validation')
[<matplotlib.lines.Line2D object at ...>]
>>> plt.plot(train_sizes train_scores.mean(axis=1) label='training')
[<matplotlib.lines.Line2D object at ...>]
对于一个degree=1模型
请注意,验证分数通常会随着训练集的增加而增加,而训练分数通常会随着训练集的增加而降低。随着训练规模的增加,它们将收敛到一个值。
从上面的讨论中,我们知道这是一个与数据欠拟合的高偏差估计量。训练和验证分数都很低的事实表明了这一点。当面对这种类型的学习曲线时,我们可以预期添加更多的训练数据将无济于事:两条线都收敛到相对较低的分数。d = 1
当学习曲线收敛到低分时,我们就有了一个高偏差模型。
可以通过以下方式改进高偏差模型:
- 使用更复杂的模型(即在这种情况下,增加d)
- 为每个样本收集更多特征。
- 减少正则化模型中的正则化。
然而,增加样本数量并不能改善高偏差模型。
现在让我们看一个高方差(即过拟合)模型:
对于一个degree=15模型
在这里,我们展示了 的学习曲线。从上面的讨论中,我们知道这是一个过拟合数据的高方差估计量。训练分数远高于验证分数这一事实表明了这一点。随着我们向这个训练集添加更多样本,训练分数会不断下降,而交叉验证误差会不断增加,直到它们在中间相遇。d = 15d = 15
尚未与完整训练集收敛的学习曲线表示高方差、过拟合模型。
可以通过以下方式改进高方差模型:
- 收集更多的训练样本。
- 使用不太复杂的模型(即在这种情况下,使模型d 更小)
- 增加正则化。
特别是,为每个样本收集更多特征将无助于结果。
6.8.3. 选型总结我们在上面已经看到,性能不佳的算法可能是由于两种可能的情况:高偏差(欠拟合)和高方差(过拟合)。为了评估我们的算法,我们留出了一部分训练数据用于交叉验证。使用学习曲线技术,我们可以在逐渐变大的数据子集上进行训练,评估训练误差和交叉验证误差,以确定我们的算法是否具有高方差或高偏差。但是我们如何处理这些信息?
高偏差如果模型显示出高偏差,以下操作可能会有所帮助:
- 添加更多功能。在我们预测房价的示例中,利用诸如房屋所在社区、房屋建造年份、地块大小等信息可能会有所帮助。将这些特征添加到训练和测试集中可以改进高偏差估计器
- 使用更复杂的模型。增加模型的复杂性有助于改善偏差。对于多项式拟合,这可以通过增加次数 d 来实现。每种学习技术都有自己增加复杂性的方法。
- 使用更少的样本。尽管这不会改善分类,但高偏差算法可以用较小的训练样本获得几乎相同的误差。对于计算量大的算法,减少训练样本量可以大大提高速度。
- 减少正则化。正则化是一种用于在某些机器学习模型中强加简单性的技术,方法是添加一个取决于参数特征的惩罚项。如果模型具有高偏差,则减少正则化的效果可以带来更好的结果。
如果模型显示高方差,以下操作可能会有所帮助:
- 使用更少的功能。使用特征选择技术可能是有用的,并且可以减少估计器的过拟合。
- 使用更简单的模型。模型复杂性和过度拟合是相辅相成的。
- 使用更多的训练样本。添加训练样本可以减少过度拟合的影响,并导致高方差估计器的改进。
- 增加正则化。正则化旨在防止过度拟合。在高方差模型中,增加正则化可以带来更好的结果。
这些选择在现实世界中变得非常重要。例如,由于望远镜时间有限,天文学家必须在观测大量天体和观测每个天体的大量特征之间寻求平衡。确定哪个对特定的学习任务更重要可以为天文学家采用的观测策略提供信息。
6.8.4. 最后要注意的是:单独的验证和测试集使用验证方案来确定超参数意味着我们将超参数拟合到特定的验证集。与参数可以过拟合训练集的方式相同,超参数可以过拟合验证集。因此,验证错误往往会低估新数据的分类错误。
为此,建议将数据分成三组:
- 训练集,用于训练模型(通常约为 60% 的数据)
- 验证集,用于验证模型(通常约为 20% 的数据)
- 测试集,用于评估验证模型的预期误差(通常约为数据的 20%)
许多机器学习从业者并没有将测试集和验证集分开。但是,如果您的目标是衡量模型在未知数据上的误差,那么使用独立的测试集至关重要。用Python做科学计算(工具篇)——sympy使用指南(符号运算)
相关文章
- 用Python做科学计算(工具篇)——scikit-learn(机器学习)7
- 用Python做科学计算(工具篇)——scikit-learn(机器学习)6
- 用Python做科学计算(工具篇)——scikit-learn(机器学习)5
- 用Python做科学计算(工具篇)——scikit-learn(机器学习)4
- 用Python做科学计算(工具篇)——scikit-learn(机器学习)3
- 用Python做科学计算(工具篇)——scikit-learn(机器学习)2
- 用Python做科学计算(工具篇)——scikit-learn(机器学习)1
- 用Python做科学计算(工具篇)——1.1. NumPy 数组对象
- 用Python做科学计算(工具篇)——numpy1.2.数组的数值运算
- 用Python做科学计算(工具篇)——numpy1.3 更精细的数组
- 用Python做科学计算(工具篇)——numpy1.4 高级操作
- 用Python做科学计算——matplotlib绘图实例
- 用Python做科学计算(工具篇)——scipy 使用指南
- 用Python做科学计算(工具篇)——sympy使用指南(符号运算)
- Python 数据处理 panda 可视化