對比歸一化和標準化 —— 量化分析

賈瀾鵬發表於2019-04-28

停止使用 Sklearn 提供的 StandardScaler 作為你的特徵壓縮方法甚至可以讓你訓練好的模型有 7% 的準確率提升。

[https://365datascience.com/standardization/](https://365datascience.com/standardization/)

每一個 ML 的從業者都知道特徵的壓縮是一個重要的議題(更多

兩個最熱議的方法就是歸一化和標準化。歸一化通常來說是將數值壓縮到 [0,1] 範圍內。標準化指的是重新調整資料,使資料到均值為 0,標準差為 1。

本篇部落格希望通過一些實驗回答以下的問題:

  1. 我們總是需要壓縮特徵嗎?

  2. 是否有一個最好的壓縮方法?

  3. 不同的壓縮技術是如何影響不同的分類器?

  4. 壓縮方法是否也應該被考慮為一個重要的超參?

我將分析多個不同壓縮方法作用於不同特徵的實驗結果。

內容總覽

    1. 為何而來?
    1. 成熟的分類器
    1. 分類器 + 壓縮
    1. 分類器 + 壓縮 + PCA
    1. 分類器 + 壓縮 + PCA + 超參調整
    1. 用更多資料集重複進行實驗
  • — 5.1 Rain in Australia 資料集
  • — 5.2 Bank Marketing 資料集
  • — 5.3 Sloan Digital Sky Survey DR14 資料集
  • — 5.4 Income classification 資料集
  • 結論

0. 為何而來?

首先,我嘗試理解歸一化與標準化之間的區別。

然後,我發現了這篇由 Sebastian Raschka 寫的很不錯的 部落格,這篇文章從數學的角度滿足了我的好奇心。如果你不熟悉歸一化與標準化的概念,那麼請一定花五分鐘讀一下這篇部落格

這裡還有篇由 Hinton 大神寫的文章解釋了為什麼使用梯度下降來訓練的分類器(如神經網路)需要使用特徵的壓縮。

好的,我們已經惡補了一波數學的知識,是吧?遠遠不夠。

我發現 Sklearn 提供了很多不同的壓縮方法。我們可以通過 the effect of different scalers on data with outliers 有一個直觀的認識。但是他們沒有講清楚這些方法是如何影響不同分類器任務的。

我們閱讀了很多 ML 的主線教程,一般都是使用 StandardScaler(通常叫做零均值標準化 )或者 MinMaxScaler(通常叫做 Min-Max 歸一化)來壓縮特徵。為什麼沒人用其他的壓縮方法來分類呢?難道 StandardScaler 和 MinMaxScaler 已經是最好的壓縮方法了?

我在教程中沒有發現關於為什麼或者什麼時候使用這些方法的解釋。所以,我覺得應該通過實驗來研究這些技術的效能。這就是這篇文章所要講的全部東西。

專案細節

和許多資料科學的工程一樣,我們會讀取一些資料,並使用一些成熟的分類器來做實驗。

資料集

Sonar 資料集包含了 208 行和 60 列特徵。這個分類任務是為了判斷聲納的回傳訊號是來自金屬圓柱還是不規則的圓柱形石頭。

對比歸一化和標準化 —— 量化分析

這是一個平衡的資料集:

sonar[60].value_counts() # 60 是標籤列的名字

M    111
R     97
複製程式碼

資料集中所有特徵都在 0 和 1 之間,但是並不是每一個特徵都能保證 1 是最大值或者 0 是最小值。

我選擇這個資料集有兩個方面的考量,首先是這個資料集足夠的小,我可以快速的完成實驗。其次,這個問題比較複雜,沒有一個分類器可以將準確率做到 100%,我獲得的比對資料就更有意義。

在後面的章節,我們也會在其他資料集上做實驗。

程式碼

在預處理環節,我已經計算了所有結果(這個花費了不少時間)。所以,我們只讀取結果檔案並在其上進行分析。

你可以在我的 GitHub 上獲取產生結果的程式碼: github.com/shaygeller/…

我從 Sklearn 中選取了一些最流行的分類器,如下:

對比歸一化和標準化 —— 量化分析

(MLP 是一種多層級的感知器,一個神經網路)

使用的壓縮方法如下:

對比歸一化和標準化 —— 量化分析

  • 不要將上表的最後一個壓縮方法 Normalizer 和我們之前提到的極大極小歸一化混淆了。極大極小歸一化對應的是第二行的 MinMaxScalar。Sklearn 中的 Normalizer 是將樣本單獨歸一化為一個單位範數。這是一個基於行而非基於列的歸一化方法。

實驗細節:

  • 為了復現實驗場景,我們使用相同的隨機數種子。

  • 訓練集和測試集的比例為 8:2,並且是隨機劃分。

  • 所有的結果的準確率都是在 10 個取自訓練集的隨機交叉驗證集上得到的。

  • 我們不討論測試集上的結果。通常來講,測試集都是不可見的,並且我們的結論都是隻從分類器在交叉驗證集上的得分得到的。

  • 在第四部分,我使用巢狀的交叉驗證集。一個內部交叉驗證集包含 5 個隨機的分塊,並由超參進行調整。外部是 10 個隨機分割的交叉驗證集並使用最好的模型引數獲得對應得分。這一部分的資料都是源自訓練集。圖片是最具有說服力的:

[https://sebastianraschka.com/faq/docs/evaluate-a-model.html](https://sebastianraschka.com/faq/docs/evaluate-a-model.html)

我們來看看結果

import os
import pandas as pd

results_file = "sonar_results.csv"
results_df = pd.read_csv(os.path.join("..","data","processed",results_file)).dropna().round(3)
results_df
複製程式碼

1. 成熟的分類器

import operator

results_df.loc[operator.and_(results_df["Classifier_Name"].str.startswith("_"), ~results_df["Classifier_Name"].str.endswith("PCA"))].dropna()
複製程式碼

對比歸一化和標準化 —— 量化分析

一個不錯的結果,通過觀察交叉驗證集的均值,我們可以發現 MLP 是最棒的,而 SVM 效果最差。

標準差的結果都是基本一致的,所以我們主要是關注均值得分。我們使用 10 個隨機分割的交叉驗證集的均值作為結果。

那麼,讓我們來看看不同壓縮方法是怎麼改變每個分類器得分的。

2. 分類器 + 壓縮

import operator
temp = results_df.loc[~results_df["Classifier_Name"].str.endswith("PCA")].dropna()
temp["model"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[1])
temp["scaler"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[0])

def df_style(val):
    return 'font-weight: 800'

pivot_t = pd.pivot_table(temp, values='CV_mean', index=["scaler"], columns=['model'], aggfunc=np.sum)
pivot_t_bold = pivot_t.style.applymap(df_style,
                      subset=pd.IndexSlice[pivot_t["CART"].idxmax(),"CART"])
for col in list(pivot_t):
    pivot_t_bold = pivot_t_bold.applymap(df_style,
                      subset=pd.IndexSlice[pivot_t[col].idxmax(),col])
pivot_t_bold
複製程式碼

對比歸一化和標準化 —— 量化分析

第一行,沒有索引名稱的那一行,是我們沒有使用任何壓縮方法的原始演算法得分。

import operator

cols_max_vals = {}
cols_max_row_names = {}
for col in list(pivot_t):
    row_name = pivot_t[col].idxmax()
    cell_val = pivot_t[col].max()
    cols_max_vals[col] = cell_val
    cols_max_row_names[col] = row_name

sorted_cols_max_vals = sorted(cols_max_vals.items(), key=lambda kv: kv[1], reverse=True)

print("Best classifiers sorted:\n")
counter = 1
for model, score in sorted_cols_max_vals:
    print(str(counter) + ". " + model + " + " +cols_max_row_names[model] + " : " +str(score))
    counter +=1
複製程式碼

最好的組合如下:

  1. SVM + StandardScaler : 0.849
  2. MLP + PowerTransformer-Yeo-Johnson : 0.839
  3. KNN + MinMaxScaler : 0.813
  4. LR + QuantileTransformer-Uniform : 0.808
  5. NB + PowerTransformer-Yeo-Johnson : 0.752
  6. LDA + PowerTransformer-Yeo-Johnson : 0.747
  7. CART + QuantileTransformer-Uniform : 0.74
  8. RF + Normalizer : 0.723

我們來分析一下結果

  1. 沒有一個壓縮方法可以讓每一個分類器都獲得最好的結果。

  2. 我們發現壓縮是會帶來增益的。SVM、MLP、KNN 和 NB 又分別從不同的壓縮方法上獲得了長足的增益。

  3. 值得注意到是一些壓縮方法對 NB、RF、LDA 和 CART 是無效的。這個現象是和每一種分類器的工作原理是相關的。樹形分類器不受影響的原因是它們在分割前會先對數值進行排序並且為每一個分組計算熵。一些壓縮函式保持了這個順序,所以不會有什麼提高。NB 不受影響的原因是它模型的先驗是由每個類中的計數器決定的而不是實際值。線性判別分析(LDA)是通過類間的變化尋找一個係數,所以它也不受壓縮的影響。

  4. 一些壓縮方法,如:QuantileTransformer-Uniform,並不會儲存特徵的實際順序,因此它依然會改變上述的那些與其他壓縮方法無關的分類器的得分。

3. 分類器 + 壓縮 + PCA

我們知道一些眾所周知的 ML 方法,比如像 PCA 就可以從壓縮中獲益(部落格)。我們試著加上一個 PCA(n_components=4)到實驗中並分析結果。

import operator
temp = results_df.copy()
temp["model"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[1])
temp["scaler"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[0])

def df_style(val):
    return 'font-weight: 800'

pivot_t = pd.pivot_table(temp, values='CV_mean', index=["scaler"], columns=['model'], aggfunc=np.sum)
pivot_t_bold = pivot_t.style.applymap(df_style,
                      subset=pd.IndexSlice[pivot_t["CART"].idxmax(),"CART"])
for col in list(pivot_t):
    pivot_t_bold = pivot_t_bold.applymap(df_style,
                      subset=pd.IndexSlice[pivot_t[col].idxmax(),col])
pivot_t_bold
複製程式碼

對比歸一化和標準化 —— 量化分析

結果分析

  1. 大多數的情況下,壓縮都改進帶有 PCA 的模型, **但是,**沒有指定特定的壓縮方法。我們來觀察一下再大多數模型上都有較好效果的 “QuantileTransformer-Uniform”。它將 LDA-PCA 的準確率從 0.704 提升到了 0.783 提高了 8%!但是對於 RF-PCA 它卻起到了負增益,模型的準確率從 0.711 降到了 0.668,下降了 4.35%。另一個方面,如果使用 “QuantileTransformer-Normal” ,RF-PCA 的準確率又可以提高到 0.766 有 5% 的提高。

  2. 我們可以發現 PCA 只提高了 LDA 和 RF,所以 PCA 也並不是一個完美的解決方案。我們並沒有去調整 n_components 這個超參,其實,就算我們調整了,也不會有保證一定可以有提升。

  3. 同時我們會發現 StandardScaler 和 MinMaxScaler 只在 16 個實驗中的 4 個得到了最好的分數,所以,我們應該考慮一下如何去選取最合適的預設壓縮方法了。

我可以有如下結論,即使 PCA 作為一個眾所周知會從壓縮中獲得增益的單元,也沒有一個壓縮方法可以保證可以提高所有的實驗結果,它們中的一些甚至對 RF-PCA 這種模型使用 StandardScaler 還會產生負面的影響。

在上面的實驗中,資料集也是一個重要的因素。為了能更好地理解壓縮方法對 PCA 的影響,我們將在更多資料集上做實驗(其中資料集會包含類別不平衡、特徵尺度不同以及同時具有數值型和分型別特徵的資料集)。我們會在第五節進行分析。

4. 分類器 + 壓縮 + PCA + 超參調整

對於給定的分類器,不同的壓縮方法會導致準確率有很大的不同。我們認為超參在調整完畢後,不同的壓縮方法對模型的影響會變小,這樣我們就可以像很多網上的教程那樣使用 StandardScaler 或者 MinMaxScaler 作為分類器的壓縮方法。 我們來驗證一下。

對比歸一化和標準化 —— 量化分析

首先,NB 沒有在此章節中,因為它不存在引數調整。

我們與較早階段的結果做對比可以發現幾乎所有的演算法都會從超參調整中獲益。一個有趣的例外是 MLP,它變得更糟糕了。這個很可能是神經網路會很容易在資料集上過擬合(尤其是當引數量遠遠大於訓練樣本),同時我們又沒有用提前停止或者正則化的方式來避免過擬合。

然而,即使我們有一組調整好的超參,運用不同的壓縮方法所得的結果還是有很大區別的。當我們在其他方法進行實驗時會發現,用這些方法和廣泛使用的 StandardScaler 在 KNN 演算法上做對比,準確度居然可以獲得 7% 的提升。

這個章節的主要結論是,即使我們有一組除錯好的超參,變換不同的壓縮方法仍然會對模型結果有較大的影響。所以我們應該將模型使用的壓縮方法也當作一個關鍵的超參。

第五部分我們會在更多的資料集上進行深入的分析。如果你不想再深挖這個問題,可以直接去看結論。

5. 用更多資料集重複進行實驗

為了得到更好理解同時更為普適的結論,我們需要在更多的資料集上做更多的實驗。

我們會用到和第三節相似的分類器+壓縮+PCA 的形式在幾個具有不同特徵的資料集上進行實驗,並在不同的小節中分析結果。所有的資料集都來自於 Kaggel。

  • 為了方便起見,我從各個資料集中選擇了只有數值的列。多元化的資料集(數值和分類特徵)在如何進行壓縮上一直有爭議。

  • 我沒有調整分類器更多的引數。

5.1 Rain in Australia 資料集

連結 分類任務:預測是否下雨? 度量方法:精度 資料集大小:(56420, 18) 各個類別的數量: 不下雨 43993 下雨 12427

這裡我們展示了 5 行資料的部分列,沒法在一張圖中展示所有列。

對比歸一化和標準化 —— 量化分析

dataset.describe()
複製程式碼

對比歸一化和標準化 —— 量化分析

我們推測由於特徵的尺度不同,壓縮可能會提高分類器的效果(觀察上表的最大最小值,剩餘資料的尺度差異會比展示的還要大)。

結果

對比歸一化和標準化 —— 量化分析

結果分析

  • 我們會發現 StandardScaler 和 MinMaxScaler 從來沒有得到過最高的分數。

  • 我們可以發現在 CART-PCA 演算法上 StandardScaler 和其他的方法甚至有 20% 的區別

  • 我們也可以發現壓縮通常是有效果的。在 SVM 上準確率甚至從 78% 漲到了 99%。

5.2 Bank Marketing 資料集

連結 分類任務:預測客戶是否已經訂購了定期存款? 度量方法:AUC (資料集不平衡) 資料集大小:(41188, 11) 各類別數量: 沒訂購 36548 訂購 4640

這裡我們展示了 5 行資料的部分列,沒法在一張圖中展示所有列。

對比歸一化和標準化 —— 量化分析

dataset.describe()
複製程式碼

對比歸一化和標準化 —— 量化分析

再次說明,特徵的尺度不同。

結果

對比歸一化和標準化 —— 量化分析

結果分析

  • 我們會發現,在這個資料集上,即使特徵是不同尺度的,壓縮也不一定會對所有使用了 PCA 的模型帶來增益。儘管如此, 在所有帶 PCA 的模型上,第二高的得分和最高得分都十分接近。這個可能意味著調整 PCA 的最終維度同時使用壓縮方法是優於所有不進行壓縮的結果的。

  • 再次強調,依然沒有一個壓縮方法表現的非常優秀。

  • 另一個有趣的結果,所有壓縮方法在大多數的模型上都沒有帶來非常大的提升(基本都在 1% - 3% 之間)。這是因為資料集本身是不平衡的,我們也沒有調整引數。另一個原因是 AUC 的得分已經很高(在 90% 左右),這就很難再有大的提升了。

5.3 Sloan Digital Sky Survey DR14 資料集

連結 分類任務:預測目標是星系、恆星還是類星體? 度量方式:準確度 (多分類) 資料集大小:(10000, 18) 各類別數量: 星系 4998 行星 4152 類星體 850

這裡我們展示了 5 行資料的部分列,沒法在一張圖中展示所有列。

對比歸一化和標準化 —— 量化分析

dataset.describe()
複製程式碼

對比歸一化和標準化 —— 量化分析

再次說明,特徵的尺度不同。

結果

對比歸一化和標準化 —— 量化分析

結果分析

  • 壓縮對結果帶來了很大的提升。這是我們可以預期的,是因為資料集中的特徵尺度是不同的。

  • 我們會發現 RobustScaler 基本上在所有使用了 PCA 的模型上都表現的很好。這可能是大量的異常點導致 PCA 的特徵向量發生了平移。另一方面,這些異常點在我們不使用 PCA 時,又沒有那麼大的影響。這個我們需要深挖資料集才能確定。

  • StandardScaler 和其他壓縮方法的準度差異可以達到 5%。這也說明我們要用多種壓縮方法進行實驗。

  • PCA 總是可以從壓縮上獲得增益。

5.4 Income classification 資料集

連結 分類任務:收入是 >50K 還是 <=50K? 度量:AUC (不平衡資料集) 資料集大小:(32561, 7) 各類別數量: <=50K 24720

50K 7841

這裡我們展示了 5 行資料的部分列,沒法在一張圖中展示所有列。

對比歸一化和標準化 —— 量化分析

dataset.describe()
複製程式碼

對比歸一化和標準化 —— 量化分析

這又是個特徵的尺度不同的資料集。

結果

對比歸一化和標準化 —— 量化分析

結果分析

  • 再次說明,資料集是不平衡的,但是我們可以發現壓縮是十分有效的可以使結果出現高達 20% 的提升。這個很可能是 AUC 的得分相較於 Bank Marketing 資料集而言比較低(80%),所以很容易獲得較大的提高。

  • 雖然 StandardScaler 沒有被高亮(我只標亮了每列得分最高的一項),但是在很多列它都很接近最好的結果,當然也不總是有這樣的結論。在執行時(沒有展示),StandardScaler 的速度比大多數的壓縮方法都快。如果你比較關注速度,StandardScaler 是個很好的選擇。但是如果你關注的是精度,那麼你就需要試試其他壓縮方法了。

  • 再次強調,依然沒有一個壓縮方法在所有演算法上都表現的非常優秀。

  • PCA 幾乎總是可以從壓縮上獲得增益。

結論

  • 實驗表明即使在超參調整好的模型上,壓縮也可以在結果上帶來增益。所以,壓縮方法需要被當作一個重要的超參來考慮。

  • 不同的壓縮方法會對不同的分類器產生影響。SVM、KNN 和 MLP(神經網路)等基於距離的分類器都會從壓縮上獲得較大的收益。但即使是樹型(CART 和 RF)這種某些壓縮技術不起作用的分類器,也可以從其它的壓縮方法上獲益。

  • 明白模型和預處理方法背後的數學理論是理解這些結果的最好方法。(舉個例子,樹型分類器是怎麼工作的?為什麼一些壓縮方法對它們無效?)。這會節約你很多的時間,如果你知道在使用隨機森林時不能使用 StandardScaler。

  • 像 PCA 這樣的預處理方法確實是會從壓縮上獲得增益。如果沒有效果,可能是因為 PCA 的維度設定的不好,異常點較多或者錯誤的選擇壓縮方法。

如果你發現任何的錯誤、實驗覆蓋率的改進方法或者改進意見都可以聯絡我。

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章