浅尝辄止

理论是灰色的,而生命之树常青。这里是@Dilettante258 的个人博客,用于记载和分享学习。

模型选择、欠拟合和过拟合

Dilettante258's avatar
| 0 views
  1. 模式发现与泛化:机器学习的主要目标之一是发现数据中的模式,但这些模式必须是泛化的,而不仅仅是数据的记忆。这意味着模型应该能够应对未见过的数据并做出有效的预测。在分类中,标签必须能够适用于新样本,而不仅仅是那些出现在训练集中的样本。
  2. 数据记忆与过拟合:过拟合是一个常见的问题,它发生在模型在训练数据上表现得很好,但在未见过的数据上表现不佳的情况下。这通常是因为模型过于复杂,过度拟合了训练数据中的噪声和特定样本,而不是泛化到整个数据分布。例如,在实验中调整模型架构或超参数时会发现: 如果有足够多的神经元、层数和训练迭代周期, 模型最终可以在训练集上达到完美的精度,此时测试集的准确性却下降了。
  3. 正则化:为了对抗过拟合,机器学习中使用正则化技术。正则化方法有助于限制模型的复杂性,防止它们过度拟合训练数据。这可以通过添加惩罚项来实现,如L1或L2正则化,或者通过减少模型的容量来实现,如降低神经网络的层数或神经元数量。
  4. 数据量的挑战:通常,机器学习任务的训练数据量有限。这使得模型更容易过拟合,因为它们无法观察到数据的全面分布。因此,模型必须依赖于正则化和其他技术来提高泛化性能。
  5. 模型调优:在实际应用中,需要进行模型调优以找到合适的超参数和架构,以平衡模型的拟合能力和泛化能力。这通常需要使用验证集来评估不同模型配置的性能。
  6. 继续监测和改进:模型的泛化性能可能会随着时间和数据的积累而改变。因此,持续监测模型性能并进行改进是至关重要的,以确保模型在面对新数据时保持准确性。

训练误差和泛化误差

训练误差(training error)是指模型在训练数据集上的误差,而泛化误差(generalization error)是指模型在未曾在训练集中出现的数据样本上的误差期望。由于无法准确计算泛化误差,我们需要通过将模型应用于独立的测试集来估计泛化误差。

有三个思维实验进一步说明了泛化误差的概念。

  1. 学生备考考试:一个学生可以通过死记硬背考题答案来准备考试,但这并不保证在真正的考试中会表现出色。这类似于模型在训练数据上表现出色,但不能保证在未见过的数据上表现良好。理解问题背后的原因和概念通常能够导致更好的泛化,就像理解考题的原理有助于在考试中表现良好一样。
  2. 查表法模型:考虑一个使用查表法回答问题的模型,如果输入空间非常大,那么无法记住每个可能的输入对应的答案。这反映了泛化问题,即模型必须泛化到未见过的输入。即使在训练数据上表现良好,也不能保证在未见过的输入上有好的表现。
  3. 硬币翻转分类问题:在一个硬币翻转分类问题中,泛化误差始终是1/2,因为硬币是公平的。然而,训练误差可能在有限的训练数据上低于1/2,这是由于运气因素造成的。随着数据量的增加,模型更有可能泛化到真实的硬币翻转概率,训练误差会逐渐接近泛化误差。

总结这些实验的关键观点是:

  • 训练误差是模型在训练数据上的性能,而泛化误差是模型在未见过的数据上的性能期望。
  • 泛化是机器学习的核心挑战,因为我们无法准确地知道未来数据的分布。
  • 模型的训练误差可以低于泛化误差,但这并不一定意味着模型在未见过的数据上表现良好。
  • 理解问题的本质和概念有助于模型更好地泛化。
  • 随着更多的数据被引入,模型更有可能泛化到真实的数据分布,训练误差逐渐接近泛化误差。

统计学习理论

  1. 泛化和独立同分布假设:在监督学习中,我们通常假设训练数据和测试数据都是从相同的分布中独立提取的,这被称为独立同分布假设(i.i.d. assumption)。这意味着训练和测试数据的生成过程没有”记忆”,样本之间的相关性与时间无关。换句话说,抽取的第2个样本和第3个样本的相关性, 并不比抽取的第2个样本和第200万个样本的相关性更强。泛化是指模型在未见过的数据上的性能表现。
  2. 模型的泛化挑战:虽然独立同分布假设在理论上很有用,但现实世界中的数据往往不完全满足这一假设。数据可能来自不同的分布,具有时间相关性,或者受到其他因素的影响。因此,理论假设与实际数据之间存在差异,这可能会对模型的泛化性能产生影响。
  3. 泛化性能解释的困难:尽管独立同分布假设是常见的,但要理解深度神经网络等复杂模型的泛化性能仍然是一个困难的问题。目前,尚未完全理解这些模型的泛化性能的理论基础。这也是机器学习领域的研究和理论探索的重要方向之一。
  4. 过拟合问题:当模型在训练数据上表现得非常好,但在测试数据上表现不佳时,发生了过拟合。过拟合是因为模型过于复杂,过度拟合了训练数据中的噪声和特定样本。为了防止过拟合,可以使用正则化技术和其他启发式方法。
  5. 实际应用中的挑战:在实际应用中,数据往往复杂多样,不同的领域可能存在不同的数据生成机制。因此,机器学习科学家需要具备批判性思维,考虑独立同分布假设的合理性,并寻找适当的方法来应对数据的多样性。

模型复杂性

  1. 模型复杂性:模型的复杂性通常由以下因素构成:
    • 参数数量:具有更多可调整参数的模型往往被认为更复杂,因为它们有更多的自由度来适应数据。
    • 参数取值范围:如果模型的参数具有广泛的取值范围,它可能更容易过拟合,因为它可以适应各种数据模式。
    • 训练样本数量:即使模型相对简单,如果训练样本数量非常有限,也容易过拟合,因为模型可以过度适应这些少量的样本。
  2. 模型选择:选择合适的模型复杂性与问题的性质密切相关。复杂模型可能可以更好地拟合训练数据,但在泛化到未见过的数据时表现不佳。相反,简化模型可能更容易泛化,但可能无法捕捉数据中的复杂关系。模型选择应考虑到问题的领域知识、可用数据量以及泛化性能的需求。
  3. 科学理论和可证伪性:一些科学家认为,模型的好坏应该与其是否可以轻松解释与可证伪性相关。一个能够解释任意观察事实并能够通过特定测试来证明其错误的模型被认为复杂。这与科学哲学家卡尔·波普尔的可证伪性标准密切相关,即科学理论应该具有可能被证伪的性质。
  4. 数据数量与模型复杂性平衡:在实践中,需要在数据的数量和模型的复杂性之间取得平衡。当我们有简单的模型和大量的数据时,我们期望泛化误差与训练误差相近。 当我们有更复杂的模型和更少的样本时,我们预计训练误差会下降,但泛化误差会增大。大量数据可以支持更复杂的模型,而有限数据可能需要更简单的模型来避免过拟合。

总之,理解模型复杂性与泛化之间的关系是机器学习中的关键问题。在模型选择和训练过程中,科学家需要仔细权衡这些因素,以确保模型能够在未来数据上表现良好。同时,模型的可解释性和可证伪性也是一个重要的考虑因素,特别是在科学和领域应用中。

模型选择

在机器学习中,我们通常在评估几个候选模型后选择最终的模型。 这个过程叫做模型选择。 有时,需要进行比较的模型在本质上是完全不同的(比如,决策树与线性模型)。 又有时,我们需要比较不同的超参数设置下的同一类模型。

例如,训练多层感知机模型时,我们可能希望比较具有 不同数量的隐藏层、不同数量的隐藏单元以及不同的激活函数组合的模型。 为了确定候选模型中的最佳模型,我们通常会使用验证集。

验证集

在模型选择过程中,我们不应该依靠测试数据,因为这可能导致过拟合测试数据的风险。如果我们过拟合了训练数据,可以通过测试数据的评估来判断。但是如果我们过拟合了测试数据,就无法得知。因此,我们不能仅仅依靠测试数据进行模型选择,也无法估计训练数据的泛化误差。

为了解决这个问题,常见的做法是将数据分成三份,除了训练和测试数据集外,还增加一个验证数据集。然而,验证数据和测试数据之间的边界模糊,很难区分。

对于时间序列上的数据,训练集和验证集可能会有自相关。训练、验证、测试三个数据集在时间上应具有先后顺序。一般的办法是,比如你拿过去一个月的股票价格来做,拿最后一个礼拜的数据作为验证数据集,这个星期以前的数据做训练数据集。

K折交叉验证

K折交叉验证是一种常用的模型评估方法,用于评估机器学习模型的性能。在K折交叉验证中,将原始数据集分成K个子集,其中一个子集作为验证集,剩余的K-1个子集作为训练集。然后,使用训练集对模型进行训练,再使用验证集对模型进行评估。这个过程重复K次,每次选取不同的验证集。最后,将K次评估结果的平均值作为模型的性能指标。

K折交叉验证的优点是能够更充分地利用数据集,减少因数据分割不合理而导致的模型评估结果不准确的问题。同时,K折交叉验证还可以用于选择合适的模型超参数,通过对不同超参数组合进行K折交叉验证,选择性能最好的超参数组合作为最终的模型。

K折交叉验证的缺点是计算成本较高,因为需要对模型进行K次训练和评估。另外,如果数据集不平衡或存在较大的噪声,K折交叉验证可能会导致模型评估结果偏离真实情况。因此,在使用K折交叉验证时需要注意数据集的特点和问题的性质。所以做K折交叉验证的前提一定是你的数据量不够

K折交叉验证中的k的确定标准是,在你算力能承受的范围内。K越大越好,但是K越大计算成本也会增加,所以需要选一个能承受的代价。

Cross Validation是帮你选择超参数的,它不能解决别的问题。没有解决数据来源的问题。数据来源的问题是整个data science在做的事情。

如果每次都随机打乱数据,取出1/n做验证,这种叫bagging,目的往往就是为了训练出n个模型来,在测试集上跑n个模型取平均(惯常做法)。

超参数

超参数(Hyperparameter)是机器学习和深度学习模型中的一种参数,但与模型的权重参数不同,超参数不是通过训练数据学习得到的,而是在训练之前需要人为设置的参数。超参数控制了模型的训练过程和性能,它们决定了模型的结构、复杂度和训练方式。选择适当的超参数对于获得高性能的机器学习模型至关重要。

以下是一些常见的机器学习和深度学习模型中的超参数示例:

  1. 学习率(Learning Rate):学习率是训练过程中用于更新模型参数的步长大小。过大的学习率可能导致训练不稳定,而过小的学习率可能导致训练过慢或陷入局部最优解。
  2. 正则化参数(Regularization Parameter):正则化参数用于控制正则化项的强度,如 L1 正则化和 L2 正则化。合适的正则化参数有助于防止过拟合。
  3. 隐藏层的数量和神经元数量(Number of Hidden Layers and Neurons):对于神经网络,你需要决定隐藏层的数量以及每个隐藏层中神经元的数量。这会影响模型的复杂性和容量。
  4. 批量大小(Batch Size):批量大小定义了每次迭代中用于更新模型参数的训练样本数量。它会影响训练速度和内存需求。
  5. 迭代次数或训练周期数(Number of Epochs):指定模型应该训练多少次,通常以迭代次数或训练周期数来表示。过少的迭代次数可能导致模型欠拟合,而过多的迭代次数可能导致过拟合。
  6. 优化器参数(Optimizer Parameters):一些优化算法(如随机梯度下降)具有自己的超参数,如动量参数、学习率衰减等。
  7. 卷积核大小、池化大小等网络结构相关的超参数:对于卷积神经网络(CNN)等深度学习模型,还需要设置卷积核大小、池化大小等与网络结构相关的超参数。

选择适当的超参数通常需要经验和实验,可以使用交叉验证、网格搜索、随机搜索等技术来帮助确定最佳超参数配置。调整超参数是调优机器学习模型性能的重要一步,因为不同的超参数设置可以导致完全不同的模型性能。

超参数优化(HPO)

即使没有overfitting或者underfitting也需要hyperparameter tuning,来调参看参数选取效果如何。

设计超参数的有效方法取决于问题的复杂性和可用资源。以下是一些常见的方法,可以帮助你有效地设计超参数:

  1. 手动调整(Expert Knowledge):如果你对问题有深入的领域知识或经验,可以尝试手动调整超参数。基于你的理解,逐个尝试不同的超参数值,并观察模型性能的变化。这种方法对于初步调优非常有效,但可能不够自动化。
  2. 网格搜索(Grid Search):如果超参数空间相对较小,你可以使用网格搜索方法。在网格搜索中,你为每个超参数指定一组候选值,系统将尝试所有可能的组合,从中找到性能最好的组合。这种方法适用于较小的超参数空间,但在超参数维度增加时,计算成本会急剧上升。
  3. 随机搜索(Random Search):与网格搜索相比,随机搜索更适用于大型超参数空间。在随机搜索中,你随机选择一组超参数组合进行训练,并记录性能。通过多次随机选择和训练,你可以逐渐找到较优的超参数组合。这种方法更加高效,因为不需要尝试所有可能的组合。
  4. 贝叶斯优化:贝叶斯优化是一种更智能的超参数优化方法,它利用先前的训练结果来指导下一次选择的超参数。这种方法通常需要更多的计算资源,但在超参数空间复杂且昂贵的情况下,它可以更快地找到良好的超参数。
  5. 自动化超参数优化工具:有许多自动化工具可用于超参数优化,如Hyperopt、Optuna、AutoML工具(如Auto-Sklearn、H2O.ai等)。这些工具可以帮助你更轻松地进行超参数搜索和优化。

最终,选择哪种方法取决于问题的性质、可用的计算资源和时间限制。在实践中,通常建议使用随机搜索或贝叶斯优化这样的自动化方法,因为它们可以更高效地找到良好的超参数组合,而无需手动调整或穷尽搜索整个超参数空间。

欠拟合还是过拟合

当我们比较训练和验证误差时,我们要注意两种常见的情况。 首先,我们要注意这样的情况:训练误差和验证误差都很严重, 但它们之间仅有一点差距。 如果模型不能降低训练误差,这可能意味着模型过于简单(即表达能力不足), 无法捕获试图学习的模式。 此外,由于我们的训练和验证误差之间的泛化误差很小, 我们有理由相信可以用一个更复杂的模型降低训练误差。 这种现象被称为欠拟合(underfitting)。

另一方面,当我们的训练误差明显低于验证误差时要小心, 这表明严重的过拟合(overfitting)。 注意,过拟合并不总是一件坏事。 特别是在深度学习领域,众所周知, 最好的预测模型在训练数据上的表现往往比在保留(验证)数据上好得多。 最终,我们通常更关心验证误差,而不是训练误差和验证误差之间的差距。

模型复杂性

为了说明一些关于过拟合和模型复杂性的经典直觉, 我们给出一个多项式的例子。 给定由单个特征x和对应实数标签y组成的训练数据, 我们试图找到下面的d阶多项式来估计标签y。

y^=i=0dxiwi\hat{y}= \sum_{i=0}^d x^i w_i

这只是一个线性回归问题,我们的特征是x的幂给出的, 模型的权重是wiw_i给出的,偏置是w0w_0给出的 (因为对于所有的x都有x0=1x^0 = 1)。 由于这只是一个线性回归问题,我们可以使用平方误差作为我们的损失函数。

高阶多项式函数比低阶多项式函数复杂得多。 高阶多项式的参数较多,模型函数的选择范围较广。 因此在固定训练数据集的情况下, 高阶多项式函数相对于低阶多项式的训练误差应该始终更低(最坏也是相等)。 事实上,当数据样本包含了x的不同值时, 函数阶数等于数据样本数量的多项式函数可以完美拟合训练集。

模型复杂度对欠拟合和过拟合的影响

以上不说人话,解读:

当我们尝试为数据找到拟合模型时,多项式是常用的方法之一。以多项式为例,我们可以很好地理解过拟合与模型复杂性的关系。

  1. 模型的定义: 在给定的例子中,我们试图使用一个d阶多项式来拟合数据。这意味着我们的模型是x的各种幂次组合,并且每个幂次都有一个对应的权重wiw_i。例如,当d=2时,模型就是一个二次方程;当d=3时,模型是一个三次方程,以此类推。
  2. 模型的复杂性: 多项式的阶数越高,模型的复杂性越大。换句话说,高阶多项式比低阶多项式有更多的参数和更广的函数选择范围。因此,理论上,高阶多项式可以更好地捕捉数据中的更多细节和模式。
  3. 拟合与过拟合:
    • 当多项式阶数很低时,例如线性或二次,它可能不能完全捕捉数据中的所有模式。这种情况称为“欠拟合”
    • 另一方面,当多项式的阶数非常高时,它不仅可以捕捉到数据中的真实模式,还可能捕捉到数据中的噪声或异常值。这时候,虽然模型在训练数据上的表现非常好,但在新的、未见过的数据上的表现可能就不佳了。这种情况称为“过拟合”
  4. 完美拟合的观察: 当多项式的阶数d等于训练数据的样本数量时,多项式可以完美地拟合训练数据。这是因为高阶多项式有足够的灵活性来经过每一个数据点。但这并不意味着这是一个好的模型,因为它可能严重过拟合,对新数据的预测可能很差。

综上所述,选择合适的模型复杂性是机器学习中的一个关键挑战。过于简单的模型可能会欠拟合,而过于复杂的模型可能会过拟合。为了选择合适的模型,常常需要使用验证集或交叉验证等技术来评估不同复杂性模型在未见过的数据上的表现。

数据集大小

另一个重要因素是数据集的大小。 训练数据集中的样本越少,我们就越有可能(且更严重地)过拟合。 随着训练数据量的增加,泛化误差通常会减小。 此外,一般来说,更多的数据不会有什么坏处。 对于固定的任务和数据分布,模型复杂性和数据集大小之间通常存在关系。 给出更多的数据,我们可能会尝试拟合一个更复杂的模型。 能够拟合更复杂的模型可能是有益的。 如果没有足够的数据,简单的模型可能更有用。 对于许多任务,深度学习只有在有数千个训练样本时才优于线性模型。 从一定程度上来说,深度学习目前的生机要归功于 廉价存储、互联设备以及数字化经济带来的海量数据集。

多项式回归

import math
import numpy as np
import torch
from torch import nn
from d2l import torch as d2l

生成数据集

给定x,我们将使用以下三阶多项式来生成训练和测试数据的标签:

y=5+1.2x3.4x22!+5.6x33!+ϵ where ϵN(0,0.12).y = 5 + 1.2x - 3.4\frac{x^2}{2!} + 5.6 \frac{x^3}{3!} + \epsilon \text{ where } \epsilon \sim \mathcal{N}(0, 0.1^2).

噪声项ϵ\epsilon服从均值为0且标准差为0.1的正态分布。 在优化的过程中,我们通常希望避免非常大的梯度值或损失值。 这就是我们将特征从xix^i调整为xii!\frac{x^i}{i!}的原因, 这样可以避免很大的i带来的特别大的指数值。 我们将为训练集和测试集各生成100个样本。

max_degree = 20  # 多项式的最大阶数
n_train, n_test = 100, 100  # 训练和测试数据集大小
true_w = np.zeros(max_degree)  # 分配空间 填充为0
true_w[0:4] = np.array([5, 1.2, -3.4, 5.6])
# 将真实权重的前4个元素设置为[5, 1.2, -3.4, 5.6],所以实际上是个四次方程
features = np.random.normal(size=(n_train + n_test, 1))
# 生成大小为(n_train + n_test, 1)的正态分布随机数数组,作为特征。
np.random.shuffle(features) # 对生成的特征进行随机打乱。
poly_features = np.power(features, np.arange(max_degree).reshape(1, -1))
# 计算特征的各阶次幂,并将结果存储在poly_features中。这样,每一列poly_features[:, i]表示features的第i阶次幂
# np.arange(max_degree).reshape(1, -1) 的效果是创建一个NumPy数组,其中包含从0到 max_degree - 1 的整数,并将数组的形状改变为 (1, max_degree)。
for i in range(max_degree):
    poly_features[:, i] /= math.gamma(i + 1)  # gamma(n)=(n-1)!
# labels的维度:(n_train+n_test,)
# 遍历多项式的所有阶次,将poly_features的每一列除以对应阶次的gamma函数值。特征从x^i调整为{x^i}/{i!}的,避免很大的i带来的特别大的指数值
labels = np.dot(poly_features, true_w)
# 通过矩阵乘法计算标签值。这里的标签值是不含噪声的真实标签值。
labels += np.random.normal(scale=0.1, size=labels.shape)
# 向标签值中添加正态分布噪声,噪声的标准差为0.1。这模拟了在实际问题中,观测值往往会受到一些随机因素的影响。

同样,存储在poly_features中的单项式由gamma函数重新缩放, 其中Γ(n)=(n1)!\Gamma(n)=(n-1)!。 从生成的数据集中查看一下前2个样本, 第一个值是与偏置相对应的常量特征。

# NumPy ndarray转换为tensor
true_w, features, poly_features, labels = [torch.tensor(x, dtype=
    torch.float32) for x in [true_w, features, poly_features, labels]]

features[:2], poly_features[:2, :], labels[:2]

对模型进行训练和测试

首先让我们实现一个函数来评估模型在给定数据集上的损失。

def evaluate_loss(net, data_iter, loss):  #@save
    """评估给定数据集上模型的损失"""
    # net代表你的神经网络模型,data_iter代表用于评估模型的数据迭代器,loss代表损失函数。
    metric = d2l.Accumulator(2)  # 累加器(Accumulator)对象 损失的总和,样本数量
    for X, y in data_iter:
        out = net(X) # 用神经网络模型net来进行前向传播
        y = y.reshape(out.shape) # 进行形状调整
        l = loss(out, y) # 计算了模型输出out和标签y之间的损失
        metric.add(l.sum(), l.numel()) # 累积当前批次的损失值l的总和以及样本数量
    return metric[0] / metric[1] # 返回平均损失值

现在定义训练函数。

def train(train_features, test_features, train_labels, test_labels,
          num_epochs=400): # 接受训练特征、测试特征、训练标签和测试标签,训练轮数默认为400轮
    loss = nn.MSELoss(reduction='none') # 创建了均方误差(MSE)损失函数对象
    # 参数reduction='none'表示不对损失进行求和或平均,而是返回每个样本的损失值。
	# 每个训练周期结束后对每个样本的损失进行个别处理,然后使用这些值进行可视化或其他分析。
    input_shape = train_features.shape[-1] # 获取训练特征的最后一个维度
    # 不设置偏置,因为我们已经在多项式中实现了它
    net = nn.Sequential(nn.Linear(input_shape, 1, bias=False))
    batch_size = min(10, train_labels.shape[0]) # 确定每个小批次的大小,取较小值
    train_iter = d2l.load_array((train_features, train_labels.reshape(-1,1)),
                                batch_size)
    test_iter = d2l.load_array((test_features, test_labels.reshape(-1,1)),
                               batch_size, is_train=False)
    # 将训练和测试数据加载到数据迭代器中
    trainer = torch.optim.SGD(net.parameters(), lr=0.01)
    # 随机梯度下降(SGD)优化器,更新模型参数 学习率为0.01
    animator = d2l.Animator(xlabel='epoch', ylabel='loss', yscale='log',
                            xlim=[1, num_epochs], ylim=[1e-3, 1e2],
                            legend=['train', 'test'])
    # 创建一个动画对象,用于可视化训练过程中的损失变化
    for epoch in range(num_epochs):
        d2l.train_epoch_ch3(net, train_iter, loss, trainer)
        # 执行一个训练周期,更新模型参数以减小损失
        if epoch == 0 or (epoch + 1) % 20 == 0:
            animator.add(epoch + 1, (evaluate_loss(net, train_iter, loss),
                                     evaluate_loss(net, test_iter, loss)))
    print('weight:', net[0].weight.data.numpy())

三阶多项式函数拟合(正常)

我们将首先使用三阶多项式函数,它与数据生成函数的阶数相同。 结果表明,该模型能有效降低训练损失和测试损失。 学习到的模型参数也接近真实值w=[5,1.2,3.4,5.6]w = [5, 1.2, -3.4, 5.6]

# 从多项式特征中选择前4个维度,即1,x,x^2/2!,x^3/3!
train(poly_features[:n_train, :4], poly_features[n_train:, :4],
      labels[:n_train], labels[n_train:])
Out: weight: [[ 5.010476   1.2354498 -3.4229028  5.503297 ]]

../_images/output_underfit-overfit_ec26bd_81_1.svg

线性函数拟合(欠拟合)

让我们再看看线性函数拟合,减少该模型的训练损失相对困难。 在最后一个迭代周期完成后,训练损失仍然很高。 当用来拟合非线性模式(如这里的三阶多项式函数)时,线性模型容易欠拟合。

# 从多项式特征中选择前2个维度,即1和x
train(poly_features[:n_train, :2], poly_features[n_train:, :2],
      labels[:n_train], labels[n_train:])
Out: weight: [[3.4049764 3.9939284]]

../_images/output_underfit-overfit_ec26bd_96_1.svg

高阶多项式函数拟合(过拟合)

现在,让我们尝试使用一个阶数过高的多项式来训练模型。 在这种情况下,没有足够的数据用于学到高阶系数应该具有接近于零的值。 因此,这个过于复杂的模型会轻易受到训练数据中噪声的影响。 虽然训练损失可以有效地降低,但测试损失仍然很高。 结果表明,复杂模型对数据造成了过拟合。

# 从多项式特征中选取所有维度
train(poly_features[:n_train, :], poly_features[n_train:, :],
      labels[:n_train], labels[n_train:], num_epochs=1500)
Out: weight: [[ 4.9849787   1.2896876  -3.2996354   5.145749   -0.34205326  1.2237961
   0.20393135  0.3027379  -0.20079008 -0.16337848  0.11026663  0.21135856
  -0.00940325  0.11873583 -0.15114897 -0.05347819  0.17096086  0.1863975
  -0.09107699 -0.02123026]]

../_images/output_underfit-overfit_ec26bd_111_1.svg