欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

好书快翻--《Python深度学习第二版》第五章 机器学习基础

程序员文章站 2024-03-02 11:56:58
...

博主有话说:首先感谢您阅读这篇博客!博主做大数据技术,平时喜欢阅读英文原版大数据技术书籍,并翻译成中文,分享出来。如要及时看到翻译的章节,请关注博主微信公众号 登峰大数据,微信号  bigdata_work

好书快翻--《Python深度学习第二版》第五章 机器学习基础

本章包括

  • 理解泛化和优化之间的平衡,这是机器学习的基本问题

  • 机器学习模型的评估方法

  • 改进模型拟合的最佳实践

  • 实现更好泛化的最佳实践

在第4章的三个实际示例之后,您应该开始熟悉如何使用神经网络处理分类和回归问题,并且您已经看到了机器学习的核心问题:过拟合。这一章将把你对机器学习的一些新的直觉形成一个坚实的概念框架,强调准确的模型评估和训练与泛化之间的平衡的重要性。

5.1 泛化:机器学习的目标

在第三章的三个例子中——预测电影评论,主题分类,房价回归----我们将数据分为训练集、验证集和测试集。不根据训练过的数据对模型进行评估的原因很快变得明显起来:仅仅过了几个epochs,在从未见过的数据上的性能就开始偏离训练数据上的性能----这总是随着训练的进行而改善。模型开始过拟合。每一个机器学习问题都会发生过拟合。

机器学习的基本问题是最优化和泛化之间的平衡。优化是指调整模型,使其在训练数据(机器学习中的学习)上获得尽可能好的性能的过程,而泛化指的是经过训练的模型在从未见过的数据上表现如何。目标当然是得到好的泛化,但是不能控制泛化;只能将模型与它的训练数据相匹配。如果你做得太好,过度拟合就会出现,泛化就会受到影响。

但是什么导致了过度拟合呢?如何实现良好的泛化?

5.1.1 欠拟合和过拟合

对于在前一章中看到的所有模型,在未见过的验证数据上的性能开始时随着训练的进行而提高,然后在一段时间后达到峰值。这种模式(如图TODO所示)是通用的。您将在任何模型类型和任何数据集中看到它。

图5.1 典型的过度拟合

好书快翻--《Python深度学习第二版》第五章 机器学习基础

 

在训练开始时,优化与泛化是相关的:训练数据损失越小,测试数据损失越小。当这种情况发生时,你的模型被认为是欠拟合的:仍然需要继续训练;该网络还没有对训练数据中的所有相关模式进行建模。但是经过一定次数的训练数据迭代后,泛化停止改善,验证指标停滞,然后开始下降:模型开始过度拟合。也就是说,它开始学习特定于训练数据的模式,但当涉及到新数据时,这些模式会产生误导或不相关。

有噪声的训练数据

在真实的数据集中,一些输入是无效的是相当普遍的。例如,一个MNIST数字可能是一个全黑的图像。或者像这样:

图5.2 一些很奇怪的MNIST训练样本

好书快翻--《Python深度学习第二版》第五章 机器学习基础

这些是什么?我也不知道。但他们都是MNIST训练的一部分。然而,更糟糕的是,有完全有效的输入,最后却被错误地标记了。像这样:

图5.3 错误标记的MNIST训练样本

好书快翻--《Python深度学习第二版》第五章 机器学习基础

如果一个模型不顾一切地吸收这些异常值,它的泛化性能会下降,如图5.4所示:例如,一个5看起来非常接近上面错误标记的5,最后可能被归类为7。

图5.4 处理异常值:鲁棒拟合与过度拟合

好书快翻--《Python深度学习第二版》第五章 机器学习基础

模糊的特征

并非所有的数据噪音都来自不准确----当问题涉及到不确定性和模糊性时,即使是非常干净整洁的标记数据也可能是有噪声的。在分类任务中,通常输入特征空间的某些区域同时与多个类相关联。假设您正在开发一个模型,该模型采用香蕉的图像并预测香蕉是未成熟的、成熟的还是腐烂的。这些类别没有客观的界限,所以同一幅画可能被不同的人贴上未成熟或成熟的标签。同样,许多问题也涉及随机性。你可以用大气压力数据来预测明天是否会下雨,但同样的测量结果可能会有雨,也可能会有晴朗的天空——有一定的可能性。

图5.5 鲁棒拟合与过拟合给出了一个模糊的特征空间

好书快翻--《Python深度学习第二版》第五章 机器学习基础

通过对特征空间的模糊区域过于自信,模型可能会过度适合这种概率数据,如图5.5所示。一个更稳健(鲁棒性)的拟合会忽略个别数据点,而着眼于更大的图景。

罕见的特征和虚假的相关性

如果你一生中只见过两只橙色的虎斑猫,而它们碰巧都非常不合群,你可能会推断橙色的虎斑猫一般都是不合群的。这就是过拟合:如果你接触过更多种类的猫,包括更多橙色的猫,你就会发现猫的颜色和性格并不相关。

同样,在包含罕见特征值的数据集上训练的机器学习模型也很容易发生过拟合。在一项情绪分类任务中,如果“cherimoya”(一种产自安第斯山脉的水果)这个词只出现在训练数据的一篇文章中,而这篇文章恰好是负面情绪的,一个不规范的模型可能会非常重视这个词,并且总是把提到cherimoya的新文章归类为负面的。然而,客观地说,cherimoya没有任何负面的东西。----马克吐温甚至称它为“人类已知的最美味的水果”。

重要的是,一个特征值不需要只出现几次就会导致虚假的相关性。考虑一个在你的训练数据中100个样本中出现的单词,它在54%的情况下与积极情绪相关,在46%的情况下与消极情绪相关。这种差异很可能完全是统计上的侥幸,然而,您的模型很可能学会利用该特征来完成其分类任务。这是过拟合最常见的来源之一。

这里有一个明显的例子,MNIST,通过将784个白噪声维度连接到现有的784个数据维度来创建一个新的训练集----一半的数据都是噪音。为了进行比较,还可以通过连接784个全为零的维度来创建一个等效的数据集。我们将毫无意义的特征串联起来,完全不会影响数据的信息内容:我们只是增加了一些东西。这些转换根本不会影响人类分类的准确性。

代码清单5.1 添加白噪声信道或全零信道到MNIST

from tensorflow.keras.datasets import mnist
import numpy as np

(train_images, train_labels), _ = mnist.load_data()
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255

train_images_with_noise_channels = np.concatenate(
  [train_images, np.random.random((len(train_images), 784))], axis=1)

train_images_with_zeros_channels = np.concatenate(
    [train_images, np.zeros((len(train_images), 784))], axis=1)

现在,让我们在这两个训练集上对第2章中的模型进行训练。

代码清单5.2 使用噪声通道或全零通道对MNIST数据训练相同的模型

from tensorflow import keras
from tensorflow.keras import layers

def get_model():
  model = keras.Sequential([
    layers.Dense(512, activation='relu'),
    layers.Dense(10, activation='softmax')
  ])
  model.compile(optimizer='rmsprop',
                loss='sparse_categorical_crossentropy',
                metrics=['accuracy'])
  return model

model = get_model()
hist_noise = model.fit(
    train_images_with_noise_channels, train_labels,
    epochs=10,
    batch_size=128,
    validation_split=0.2)

model = get_model()
hist_zeros = model.fit(
    train_images_with_zeros_channels, train_labels,
    epochs=10,
    batch_size=128,
    validation_split=0.2)

代码清单5.3 绘制验证精度比较图

import matplotlib.pyplot as plt
val_acc_noise = hist_noise.history['val_accuracy']
val_acc_zeros = hist_zeros.history['val_accuracy']
epochs = range(1, 11)
plt.plot(epochs, val_acc_noise, 'b-',
         label='Validation accuracy with noise channels')
plt.plot(epochs, val_acc_zeros, 'b--',
         label='Validation accuracy with zeros channels')
plt.title('Effect of noise channels on validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()

尽管这两种情况下的数据包含相同的信息,但经过噪声通道训练的模型的验证精度最终会降低约一个百分点——这完全是由于虚假相关性的影响。添加的噪声通道越多,进一步的精度就会降低。

图5.6 噪声通道对验证精度的影响

好书快翻--《Python深度学习第二版》第五章 机器学习基础

噪声特征不可避免地会导致过拟合。因此,在不确定特征是有用的还是分散注意力的情况下,在训练之前进行特征选择是很常见的。例如,将IMDB数据限制在最常见的10,000个单词以内是一种粗糙的特性选择形式。进行特征选择的典型方法是为每个可用的特征计算一些有用性评分----关于任务的特征信息的度量,如特征和标签之间的相关信息----并且只保留那些高于某个阈值的特征。这样做可以过滤上面示例中的白噪声通道。我们将在后面章节中深入讨论特征选择的最佳实践。

5.1.2 深度学习中泛化的性质

关于深度学习模型,一个值得注意的事实是,它们可以被训练成适应(fit)任何东西,只要它们有足够的表示能力。

不相信我吗?尝试改变MNIST的标签,并在这方面训练一个模型。即使输入和打乱的标签之间没有任何关系,训练损失下降得很好,即使是一个相对较小的模型。当然,验证损失不会随时间而改善,因为在此设置中不可能泛化。

代码清单5.4 用随机打乱的标签拟合MNIST模型

(train_images, train_labels), _ = mnist.load_data()
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255

random_train_labels = train_labels[:]
np.random.shuffle(random_train_labels)

model = keras.Sequential([
  layers.Dense(512, activation='relu'),
  layers.Dense(10, activation='softmax')
])
model.compile(optimizer='rmsprop',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
model.fit(train_images, random_train_labels,
          epochs=100,
          batch_size=128,
          validation_split=0.2)

事实上,你甚至不需要用MNIST数据来做这些——你只需要生成白噪声输入和随机标签。只要它有足够的参数,你也可以在上面安装一个模型。它只需要记住特定的输入,就像Python字典一样。

如果是这样的话,那么深度学习模型是如何泛化的呢?他们不应该学习训练输入和目标之间的特殊映射,就像花哨的dict吗? 我们期望这种映射在新的输入下能够工作吗?

事实证明,深度学习中泛化的本质与深度学习模型本身关系不大,而与现实世界中的信息结构关系很大。让我们来看看到底发生了什么。

manifold hypothesis(流形假设)

MNIST分类器的输入(预处理之前)是一个由0到255之间的整数组成的28x28的数组。因此,可能输入值的总数是784的256次方——远远大于宇宙中原子的数目。然而,这些输入很少看起来像有效的MNIST样本:实际的手写数字在所有可能的28x28 uint8数组的父空间中只占很小的一个子空间。更重要的是,这个子空间不仅仅是在父空间中随机散布的一组点:它是高度结构化的。

首先,有效的手写数字的子空间是连续的:如果你取一个样本并对它进行一些修改,它仍然可以被识别为相同的手写数字。此外,有效子空间中的所有样本都由通过子空间的光滑路径连接。这意味着如果你取两个随机的MNIST数字A和B,就会存在一个将A变形为B的“中间”图像序列,这样两个连续的数字就会非常接近。也许在两个类之间的边界附近会有一些模糊的形状,但是即使这些形状看起来仍然非常像数字。

在技术术语中,您可能会说,手写数字在可能的28x28 uint8数组空间中形成了一个流形(manifold )。这是一个很重要的词,但是这个概念很直观。“manifold ”是某个父空间的低维子空间,它在局部上类似于线性(欧几里德)空间。例如,平面上的光滑曲线是二维空间中的一维流形,因为对于曲线上的每一点,都可以画一条切线(这条曲线可以用每一点上的一条直线来近似),三维空间中的光滑表面是二维流形。等等。

更一般地说,流形假设假定所有的自然数据都位于高维空间内的一个低维流形上,而这个高维空间是数据编码的地方。这是关于宇宙信息结构的一个非常有力的陈述。据我们所知,它是准确的,这也是为什么深度学习有效的原因。这不仅适用于MNIST数字,也适用于人脸、树木形态、人声甚至自然语言。

流形假设意味着:

机器学习模型只需要在其潜在的输入(潜在的流形)中适合相对简单、低维、高结构化的子空间。

在其中一个流形中,总是可以在两个输入之间插值(interpolate ),也就是说,通过一条所有点都落在流形上的连续路径,将一个点变形为另一个点。

样本间的插值能力是理解深度学习中泛化的关键。

插值作为一种泛化的来源

好书快翻--《Python深度学习第二版》第五章 机器学习基础