- 原文地址:Normalization vs Standardization — Quantitative analysis
- 原文做者:Shay Geller
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:ccJia
- 校對者:Fengziyin1234, portandbridge
中止使用 Sklearn 提供的 StandardScaler 做爲你的特徵壓縮方法甚至可讓你訓練好的模型有 7% 的準確率提高。html
每個 ML 的從業者都知道特徵的壓縮是一個重要的議題(更多)前端
兩個最熱議的方法就是歸一化和標準化。歸一化一般來講是將數值壓縮到 [0,1] 範圍內。標準化指的是從新調整數據,使數據到均值爲 0,標準差爲 1。android
本篇博客但願經過一些實驗回答如下的問題:ios
咱們老是須要壓縮特徵嗎?git
是否有一個最好的壓縮方法?github
不一樣的壓縮技術是如何影響不一樣的分類器?算法
壓縮方法是否也應該被考慮爲一個重要的超參?後端
我將分析多個不一樣壓縮方法做用於不一樣特徵的實驗結果。bash
首先,我嘗試理解歸一化與標準化之間的區別。網絡
而後,我發現了這篇由 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 是一種多層級的感知器,一個神經網絡)
使用的壓縮方法以下:
爲了復現實驗場景,咱們使用相同的隨機數種子。
訓練集和測試集的比例爲 8:2,而且是隨機劃分。
全部的結果的準確率都是在 10 個取自訓練集的隨機交叉驗證集上獲得的。
咱們不討論測試集上的結果。一般來說,測試集都是不可見的,而且咱們的結論都是隻從分類器在交叉驗證集上的得分獲得的。
在第四部分,我使用嵌套的交叉驗證集。一個內部交叉驗證集包含 5 個隨機的分塊,並由超參進行調整。外部是 10 個隨機分割的交叉驗證集並使用最好的模型參數得到對應得分。這一部分的數據都是源自訓練集。圖片是最具備說服力的:
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
複製代碼
import operator
results_df.loc[operator.and_(results_df["Classifier_Name"].str.startswith("_"), ~results_df["Classifier_Name"].str.endswith("PCA"))].dropna()
複製代碼
一個不錯的結果,經過觀察交叉驗證集的均值,咱們能夠發現 MLP 是最棒的,而 SVM 效果最差。
標準差的結果都是基本一致的,因此咱們主要是關注均值得分。咱們使用 10 個隨機分割的交叉驗證集的均值做爲結果。
那麼,讓咱們來看看不一樣壓縮方法是怎麼改變每一個分類器得分的。
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
複製代碼
最好的組合以下:
沒有一個壓縮方法可讓每個分類器都得到最好的結果。
咱們發現壓縮是會帶來增益的。SVM、MLP、KNN 和 NB 又分別從不一樣的壓縮方法上得到了長足的增益。
值得注意到是一些壓縮方法對 NB、RF、LDA 和 CART 是無效的。這個現象是和每一種分類器的工做原理是相關的。樹形分類器不受影響的緣由是它們在分割前會先對數值進行排序而且爲每個分組計算熵。一些壓縮函數保持了這個順序,因此不會有什麼提升。NB 不受影響的緣由是它模型的先驗是由每一個類中的計數器決定的而不是實際值。線性判別分析(LDA)是經過類間的變化尋找一個係數,因此它也不受壓縮的影響。
一些壓縮方法,如:QuantileTransformer-Uniform,並不會保存特徵的實際順序,所以它依然會改變上述的那些與其餘壓縮方法無關的分類器的得分。
咱們知道一些衆所周知的 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
複製代碼
大多數的狀況下,壓縮都改進帶有 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% 的提升。
咱們能夠發現 PCA 只提升了 LDA 和 RF,因此 PCA 也並非一個完美的解決方案。咱們並無去調整 n_components 這個超參,其實,就算咱們調整了,也不會有保證必定能夠有提高。
同時咱們會發現 StandardScaler 和 MinMaxScaler 只在 16 個實驗中的 4 個獲得了最好的分數,因此,咱們應該考慮一下如何去選取最合適的默認壓縮方法了。
我能夠有以下結論,即便 PCA 做爲一個衆所周知會從壓縮中得到增益的單元,也沒有一個壓縮方法能夠保證能夠提升全部的實驗結果,它們中的一些甚至對 RF-PCA 這種模型使用 StandardScaler 還會產生負面的影響。
在上面的實驗中,數據集也是一個重要的因素。爲了能更好地理解壓縮方法對 PCA 的影響,咱們將在更多數據集上作實驗(其中數據集會包含類別不平衡、特徵尺度不一樣以及同時具備數值型和分類型特徵的數據集)。咱們會在第五節進行分析。
對於給定的分類器,不一樣的壓縮方法會致使準確率有很大的不一樣。咱們認爲超參在調整完畢後,不一樣的壓縮方法對模型的影響會變小,這樣咱們就能夠像不少網上的教程那樣使用 StandardScaler 或者 MinMaxScaler 做爲分類器的壓縮方法。 咱們來驗證一下。
首先,NB 沒有在此章節中,由於它不存在參數調整。
咱們與較早階段的結果作對比能夠發現幾乎全部的算法都會從超參調整中獲益。一個有趣的例外是 MLP,它變得更糟糕了。這個極可能是神經網絡會很容易在數據集上過擬合(尤爲是當參數量遠遠大於訓練樣本),同時咱們又沒有用提早中止或者正則化的方式來避免過擬合。
然而,即便咱們有一組調整好的超參,運用不一樣的壓縮方法所得的結果仍是有很大區別的。當咱們在其餘方法進行實驗時會發現,用這些方法和普遍使用的 StandardScaler 在 KNN 算法上作對比,準確度竟然能夠得到 7% 的提高。
這個章節的主要結論是,即便咱們有一組調試好的超參,變換不一樣的壓縮方法仍然會對模型結果有較大的影響。因此咱們應該將模型使用的壓縮方法也看成一個關鍵的超參。
第五部分咱們會在更多的數據集上進行深刻的分析。若是你不想再深挖這個問題,能夠直接去看結論。
爲了獲得更好理解同時更爲普適的結論,咱們須要在更多的數據集上作更多的實驗。
咱們會用到和第三節類似的分類器+壓縮+PCA 的形式在幾個具備不一樣特徵的數據集上進行實驗,並在不一樣的小節中分析結果。全部的數據集都來自於 Kaggel。
爲了方便起見,我從各個數據集中選擇了只有數值的列。多元化的數據集(數值和分類特徵)在如何進行壓縮上一直有爭議。
我沒有調整分類器更多的參數。
連接 分類任務:預測是否下雨? 度量方法:精度 數據集大小:(56420, 18) 各個類別的數量: 不下雨 43993 下雨 12427
這裏咱們展現了 5 行數據的部分列,無法在一張圖中展現全部列。
dataset.describe()
複製代碼
咱們推測因爲特徵的尺度不一樣,壓縮可能會提升分類器的效果(觀察上表的最大最小值,剩餘數據的尺度差別會比展現的還要大)。
結果
結果分析
咱們會發現 StandardScaler 和 MinMaxScaler 歷來沒有獲得過最高的分數。
咱們能夠發如今 CART-PCA 算法上 StandardScaler 和其餘的方法甚至有 20% 的區別。
咱們也能夠發現壓縮一般是有效果的。在 SVM 上準確率甚至從 78% 漲到了 99%。
連接 分類任務:預測客戶是否已經訂購了按期存款? 度量方法:AUC (數據集不平衡) 數據集大小:(41188, 11) 各種別數量: 沒訂購 36548 訂購 4640
這裏咱們展現了 5 行數據的部分列,無法在一張圖中展現全部列。
dataset.describe()
複製代碼
再次說明,特徵的尺度不一樣。
結果
結果分析
咱們會發現,在這個數據集上,即便特徵是不一樣尺度的,壓縮也不必定會對全部使用了 PCA 的模型帶來增益。儘管如此, 在全部帶 PCA 的模型上,第二高的得分和最高得分都十分接近。這個可能意味着調整 PCA 的最終維度同時使用壓縮方法是優於全部不進行壓縮的結果的。
再次強調,依然沒有一個壓縮方法表現的很是優秀。
另外一個有趣的結果,全部壓縮方法在大多數的模型上都沒有帶來很是大的提高(基本都在 1% - 3% 之間)。這是由於數據集自己是不平衡的,咱們也沒有調整參數。另外一個緣由是 AUC 的得分已經很高(在 90% 左右),這就很難再有大的提高了。
連接 分類任務:預測目標是星系、恆星仍是類星體? 度量方式:準確度 (多分類) 數據集大小:(10000, 18) 各種別數量: 星系 4998 行星 4152 類星體 850
這裏咱們展現了 5 行數據的部分列,無法在一張圖中展現全部列。
dataset.describe()
複製代碼
再次說明,特徵的尺度不一樣。
結果
結果分析
壓縮對結果帶來了很大的提高。這是咱們能夠預期的,是由於數據集中的特徵尺度是不一樣的。
咱們會發現 RobustScaler 基本上在全部使用了 PCA 的模型上都表現的很好。這多是大量的異常點致使 PCA 的特徵向量發生了平移。另外一方面,這些異常點在咱們不使用 PCA 時,又沒有那麼大的影響。這個咱們須要深挖數據集才能肯定。
StandardScaler 和其餘壓縮方法的準度差別能夠達到 5%。這也說明咱們要用多種壓縮方法進行實驗。
PCA 老是能夠從壓縮上得到增益。
連接 分類任務:收入是 >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 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。