好書快翻--《Python深度學習第二版》第五章 機器學習基礎

博主有話說:首先感謝您閱讀這篇博客!博主做大數據技術,平時喜歡閱讀英文原版大數據技術書籍,並翻譯成中文,分享出來。如要及時看到翻譯的章節,請關注博主微信公衆號 登峯大數據,微信號  bigdata_work

本章包括

  • 理解泛化和優化之間的平衡,這是機器學習的基本問題

  • 機器學習模型的評估方法

  • 改進模型擬合的最佳實踐

  • 實現更好泛化的最佳實踐

在第4章的三個實際示例之後,您應該開始熟悉如何使用神經網絡處理分類和迴歸問題,並且您已經看到了機器學習的核心問題:過擬合。這一章將把你對機器學習的一些新的直覺形成一個堅實的概念框架,強調準確的模型評估和訓練與泛化之間的平衡的重要性。

5.1 泛化:機器學習的目標

在第三章的三個例子中——預測電影評論,主題分類,房價迴歸----我們將數據分爲訓練集、驗證集和測試集。不根據訓練過的數據對模型進行評估的原因很快變得明顯起來:僅僅過了幾個epochs,在從未見過的數據上的性能就開始偏離訓練數據上的性能----這總是隨着訓練的進行而改善。模型開始過擬合。每一個機器學習問題都會發生過擬合。

機器學習的基本問題是最優化和泛化之間的平衡。優化是指調整模型,使其在訓練數據(機器學習中的學習)上獲得儘可能好的性能的過程,而泛化指的是經過訓練的模型在從未見過的數據上表現如何。目標當然是得到好的泛化,但是不能控制泛化;只能將模型與它的訓練數據相匹配。如果你做得太好,過度擬合就會出現,泛化就會受到影響。

但是什麼導致了過度擬合呢?如何實現良好的泛化?

5.1.1 欠擬合和過擬合

對於在前一章中看到的所有模型,在未見過的驗證數據上的性能開始時隨着訓練的進行而提高,然後在一段時間後達到峯值。這種模式(如圖TODO所示)是通用的。您將在任何模型類型和任何數據集中看到它。

圖5.1 典型的過度擬合

 

在訓練開始時,優化與泛化是相關的:訓練數據損失越小,測試數據損失越小。當這種情況發生時,你的模型被認爲是欠擬合的:仍然需要繼續訓練;該網絡還沒有對訓練數據中的所有相關模式進行建模。但是經過一定次數的訓練數據迭代後,泛化停止改善,驗證指標停滯,然後開始下降:模型開始過度擬合。也就是說,它開始學習特定於訓練數據的模式,但當涉及到新數據時,這些模式會產生誤導或不相關。

有噪聲的訓練數據

在真實的數據集中,一些輸入是無效的是相當普遍的。例如,一個MNIST數字可能是一個全黑的圖像。或者像這樣:

圖5.2 一些很奇怪的MNIST訓練樣本

這些是什麼?我也不知道。但他們都是MNIST訓練的一部分。然而,更糟糕的是,有完全有效的輸入,最後卻被錯誤地標記了。像這樣:

圖5.3 錯誤標記的MNIST訓練樣本

如果一個模型不顧一切地吸收這些異常值,它的泛化性能會下降,如圖5.4所示:例如,一個5看起來非常接近上面錯誤標記的5,最後可能被歸類爲7。

圖5.4 處理異常值:魯棒擬合與過度擬合

模糊的特徵

並非所有的數據噪音都來自不準確----當問題涉及到不確定性和模糊性時,即使是非常乾淨整潔的標記數據也可能是有噪聲的。在分類任務中,通常輸入特徵空間的某些區域同時與多個類相關聯。假設您正在開發一個模型,該模型採用香蕉的圖像並預測香蕉是未成熟的、成熟的還是腐爛的。這些類別沒有客觀的界限,所以同一幅畫可能被不同的人貼上未成熟或成熟的標籤。同樣,許多問題也涉及隨機性。你可以用大氣壓力數據來預測明天是否會下雨,但同樣的測量結果可能會有雨,也可能會有晴朗的天空——有一定的可能性。

圖5.5 魯棒擬合與過擬合給出了一個模糊的特徵空間

通過對特徵空間的模糊區域過於自信,模型可能會過度適合這種概率數據,如圖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 噪聲通道對驗證精度的影響

噪聲特徵不可避免地會導致過擬合。因此,在不確定特徵是有用的還是分散注意力的情況下,在訓練之前進行特徵選擇是很常見的。例如,將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 ),也就是說,通過一條所有點都落在流形上的連續路徑,將一個點變形爲另一個點。

樣本間的插值能力是理解深度學習中泛化的關鍵。

插值作爲一種泛化的來源

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章