通過正則化擴展回歸庫

2021-02-20 磐創AI

作者 | Paul Hiemstra 

編譯 | VK 

來源 | Towards Datas Science

你也可以在GitHub上閱讀這篇文章。這個GitHub存儲庫包含你自己運行分析所需的一切:https://github.com/PaulHiemstra/lasso_tsfresh_article/blob/master/lasso_tsfresh_article.ipynb

介紹

對於許多數據科學家來說,最基本的模型是多元線性回歸。在許多分析中,它是第一個被調用的,並作為更複雜模型的基準。它的一個優點是容易解釋得到的係數,這是神經網絡特別難以解決的問題。

然而,線性回歸併非沒有挑戰。在本文中,我們關注一個特殊的挑戰:處理大量的特徵。大數據集的具體問題是如何為模型選擇相關的特徵,如何克服過擬合以及如何處理相關特徵。

正則化是一種非常有效的技術,有助於解決上述問題。正則化是通過用一個限制係數大小的項來擴展標準最小二乘目標或損失函數來實現的。本文的主要目的是讓你熟悉正則化及其提供的優勢。

在本文中,你將了解以下主題:

有哪些不同類型的正則化,以及術語L1和L2正則化意味著什麼

我們將從更理論上介紹正則化開始本文,並以一個實際例子結束。

為什麼使用正則化,什麼是正則化

下圖顯示了一個綠色和藍色的函數,與紅色觀察值相匹配。這兩個函數都完美地符合觀測值,我們該以何種方式選擇這2個函數。

我們的問題是不確定的,這導致我們任意不能選擇這兩個函數中的任何一個。在回歸分析中,有兩個因素減低了性能:多重共線性(相關特徵)和特徵的數量。

通常可以手工以得到少量特徵。然而,在更多的數據驅動方法中,我們通常使用許多特徵,這導致特徵之間有很多相關,而我們事先並不知道哪些特徵會很好地工作。為了克服不確定性,我們需要在問題中添加信息。在我們的問題中添加信息的數學術語是正則化。

回歸中執行正則化的一種非常常見的方法是用附加項擴展損失函數。Tibshirani(1997)提出用一種稱為Lasso的方法將係數的總大小添加到損失函數中。表示係數總大小的數學方法是使用所謂的範數:

其中p值決定了我們使用什麼樣的正則化。p值為1稱為L1範數,值為2稱為L2範數等。既然我們有了範數的數學表達式,我們就可以擴展我們通常在回歸中使用的最小二乘損失函數:

注意,這裡我們使用L2範數,我們也用L2範數表示了損失函數的平方差部分。另外,lambda是正則化強度。正則化強度決定了係數大小與損失函數平方差部分的關係。注意,範數項主要優點是減少了模型中的方差。

包含L2範數的回歸稱為嶺回歸。嶺回歸減少了預測中的方差,使其更穩定,更不容易過擬合。此外,方差的減少還可以對抗多重共線性帶來的方差。

當我們在損失函數中加入L1範數時,這稱為Lasso。Lasso在減小係數大小方面比嶺回歸更進一步,會降到零。這實際上意味著變量從模型中退出,因此lasso是在執行特徵選擇。這在處理高度相關的特徵(多重共線性)時有很大的影響。Lasso傾向於選擇一個相關變量,而嶺回歸平衡所有特徵。Lasso的特徵選擇在你有很多輸入特徵時特別有用,而你事先並不知道哪些特徵會對模型有利。

如果要混合Lasso回歸和嶺回歸,可以同時向損失函數添加L1和L2範數。這就是所謂的Elastic正則化。在理論部分結束後,讓我們進入正則化的實際應用。

正則化的示例使用用例

人類很善於識別聲音。僅憑音頻,我們就能夠區分汽車、聲音和槍枝等事物。如果有人特別有經驗,他們甚至可以告訴你什麼樣聲音屬於哪種汽車。在這種情況下,我們將建立一個正則化回歸模型。

數據集

我們的數據是75個鼓樣品,每種類型的鼓有25個:底鼓、圈套鼓和湯姆鼓。每個鼓樣本存儲在wav文件中,例如:

sample_rate, bass = wavfile.read('./sounds/bass1.wav')
bass_pd = pd.DataFrame(bass, columns=['left', 'right']).assign(time_id = range(len(bass)))
bass_pd.head()

# 注意,本文中的所有圖形都使用了plotnine
(
    ggplot(bass_pd.melt(id_vars = ['time_id'], value_name='amplitude', var_name='stereo')) 
      + geom_line(aes(x = 'time_id', 
                      y = 'amplitude'))
      + facet_wrap('stereo') 
      + theme(figure_size=(4,2))
)

wav文件是立體聲的,包含兩個聲道:左聲道和右聲道。該文件包含隨時間變化的波形,在x軸上隨時間變化,在y軸上包含振幅。振幅基本上列出了揚聲器圓錐應該如何振動。

以下代碼構造了一個包含所有75個鼓樣本的數據幀:

import glob

wav_files = glob.glob('sounds/kick/*.wav') + glob.glob('sounds/snare/*.wav') + glob.glob('sounds/tom/*.wav')
all_audio = pd.concat([audio_to_dataframe(path) for path in wav_files])
all_labels = pd.Series(np.repeat(['kick', 'snare', 'tom'], 25), 
                      index = wav_files)
all_audio.head()

附加函數audio_to_dataframe可以在github倉庫的helper_functions.py找到。

使用tsfresh生成特徵

為了擬合一個監督模型,sklearn需要兩個數據集:一個帶有我們的特徵的樣本特徵x矩陣(或數據幀)和一個帶有標籤的樣本向量。

因為我們已經有了標籤,所以我們把精力集中在特徵矩陣上。因為我們希望我們的模型對每個聲音文件進行預測,所以特徵矩陣中的每一行都應該包含一個聲音文件的所有特徵。

接下來的挑戰是提出我們想要使用的特徵。例如,低音鼓的聲音中可能有更多的低音頻率。因此,我們可以在所有樣本上運行FFT並將低音頻率分離成一個特徵。

採用這種手動特徵工程方法可能會非常耗費人力,並且很有可能排除重要特徵。tsfresh(docs)是一個Python包,它極大地加快了這個過程。該包基於timeseries數據生成數百個潛在的特徵,還包括預選相關特徵的方法。有數百個特徵強調了在這種情況下使用某種正則化的重要性。

為了熟悉tsfresh,我們首先使用MinimalFCParameters設置生成少量特徵:

from tsfresh import extract_relevant_features
from tsfresh.feature_extraction import MinimalFCParameters
settings = MinimalFCParameters()

audio_tsfresh_minimal = extract_relevant_features(all_audio, all_labels, 
                                          column_id='file_id', column_sort='time_id', 
                                          default_fc_parameters=settings)
                                          
print(audio_tsfresh_minimal.shape)
audio_tsfresh_minimal.head()

這就給我們留下了11個特徵。我們使用extract_related_features函數來允許tsfresh根據標籤和生成的潛在特徵預先選擇有意義的特徵。在這種最小的情況下,tsfresh查看由file_id列標識的每個聲音文件,並生成諸如振幅的標準偏差、平均振幅等特徵。

但是tsfresh的強大之處在於我們產生了更多的特徵。在這裡,我們使用相關默認設置來節省一些時間,而不是使用完整的設置。注意,我直接讀取了dataframe的pickle數據,它是使用github倉庫中用generate_drum_model.py腳本生成的。我這樣做是為了節省時間,因為在我的12線程機器上計算大約需要10分鐘。

from tsfresh.feature_extraction import EfficientFCParameters
settings = EfficientFCParameters()

audio_tsfresh = pd.read_pickle('pkl/drum_tsfresh.pkl')
print(audio_tsfresh.shape)
audio_tsfresh.head()

這使得特徵的數量從11個擴展到327個。這些特徵為我們的正則化回歸模型提供了一個非常廣闊的學習空間。

正則回歸模型的擬合

現在我們已經有了一組輸入特徵和所需的標籤,我們可以繼續並擬合我們的正則化回歸模型。我們使用來自sklearn的邏輯回歸模型:

from sklearn.linear_model import LogisticRegression

base_log_reg = LogisticRegression(penalty='l1', 
                                  multi_class='ovr',
                                  solver='saga',
                                  tol=1e-6,
                                  max_iter=int(1e4), 
                                  C=1)

並使用以下設置:

我們將懲罰設置為l1,即我們使用l1範數的正則化。

我們將multi_class設置為1 vs rest(ovr)。這意味著我們的模型由三個子模型組成,每種可能類型的鼓各有一個。當用整體模型進行預測時,我們只需選擇表現最好的模型。

我們使用saga求解器來擬合我們的損失函數。還有更多可用的,但saga能夠完成我們所需要的功能。

現在將C設為1,其中C等於1/正則化強度。請注意,sklearn Lasso實現使用了𝛼,它等於1/2C。我發現𝛼是一個更直觀的度量,我們將在本文的其餘部分使用它。

基於這些設置,我們進行了一些實驗。首先,我們將比較基於少量和大量tsfresh特徵的模型的性能。之後,我們將重點討論如何使用交叉驗證來擬合正則化強度,並對擬合模型的性能進行更全面的討論。

最小tsfresh vs 有效tsfresh

我們的第一個分析測試了這樣一個假設:使用更多生成的tsfresh特徵可以得到更好的模型。為了測試這一點,我們使用最小tsfresh和有效tsfresh特徵來擬合一個模型。我們通過模型在測試集上的準確性來判斷模型的性能。我們重複20次,以了解由於在選擇訓練和測試集時的隨機性而導致的精確度差異:

from sklearn.model_selection import train_test_split

def get_score(audio_data, labels):
    # 用cross_val_score代替?
    audio_train, audio_test, label_train, label_test = train_test_split(audio_data, labels, test_size=0.3)
    log_reg = base_log_reg.fit(audio_train, label_train)
    return log_reg.score(audio_test, label_test)
accuracy_minimal = [get_score(audio_tsfresh_minimal, all_labels) for x in range(20)]
accuracy_efficient = [get_score(audio_tsfresh, all_labels) for x in range(20)]

plot_data = pd.concat([pd.DataFrame({'accuracy': accuracy_minimal, 'tsfresh_data': 'minimal'}),
                       pd.DataFrame({'accuracy': accuracy_efficient, 'tsfresh_data': 'efficient'})])
(
    ggplot(plot_data) + geom_boxplot(aes(x='tsfresh_data', y='accuracy')) + 
      coord_flip() + 
      labs(y = 'Accuracy', x = 'TSfresh setting')
)

得到的箱線圖清楚地表明,與基於最小特徵的模型相比,有效tsfresh變量顯示了更高的平均精度0.75,而不是0.4。這證實了我們的假設,我們將在本文的其餘部分使用有效的特徵。

通過交叉驗證選擇正則化強度

在使用正則化時,我們必須做出的一個主要選擇是正則化的強度。在這裡,我們使用交叉驗證來測試C的一系列潛在值的準確性。

sklearn很方便地包含了一個用於邏輯回歸分析的函數:LogisticRegressionCV。它本質上具有與LogisticRegression相同的接口,但是你可以傳遞一個潛在的C值列表來進行測試。

有關代碼的詳細信息,請參閱generate_drum_model.py,我們將結果從磁碟加載到此處以節省時間:

from sklearn.svm import l1_min_c
from joblib import dump, load

cs = l1_min_c(audio_tsfresh, all_labels, loss='log') * np.logspace(0, 7, 16)
cv_result = load('pkl/drum_logreg_cv.joblib')

註:我們使用l1_min_c來獲得模型包含非零係數的最小c值。然後我們在上面乘上一個0到7之間的16個對數,這樣得到16個潛在的C值。我沒有一個很好的理由來解釋這些數字。轉換為α,並取log10,我們得到:

np.log10(1/(2*cs))

這其中包含一個很好的正則化強度範圍,我們將在結果的解釋中看到。

交叉驗證選擇了以下𝛼值:

np.log10(1/(2*cv_result.C_))

注意我們有三個值,每個子模型一個(kick-model, tom-model, snare-model)。在這裡,我們看到,6左右的正則化強度被認為是最優的(C=4.5e-07)。

基於CV結果對模型的進一步解釋

cv_result對象包含更多關於交叉驗證的數據,而不是擬合的正則化強度。在這裡,我們首先看看交叉驗證模型中的係數,以及它們在不斷變化的正則化強度下所遵循的路徑。注意,我們使用helper_functions,py中的plot_coef_paths函數:

plot_coef_paths(cv_result, 'kick', audio_tsfresh) + theme(figure_size=(16,12))

註:我們在圖中看到5條線,因為默認情況下我們執行5折交叉驗證。另外,我們重點研究了kick子模型。圖中有以下有趣的觀察結果:

增加正則化強度會減小係數的大小。這正是正則化應該做的,但是結果支持這一點是很好的。

增加的褶皺線減少了強度之間的變化。這符合正則化的目標:減少模型中的方差。然而,褶皺之間的變化仍然非常劇烈。

對於交叉驗證的正則化強度(6),相當多的係數從模型中消失。在tsfresh生成的327個潛在特徵中,只有大約10個被選為最終模型。

許多有影響的變量是fft分量。這很直觀,因為鼓樣本之間的差異集中在特定頻率(低音鼓->低頻,圈套鼓->高頻)。

這些觀察結果描繪了這樣一幅圖景:正則化回歸按預期工作,但肯定還有改進的餘地。在這種情況下,我懷疑每種類型的鼓有25個樣本是主要的限制因素。

除了看係數及其變化,我們還可以看看子模型的總體精度與正則化強度的關係。注意,我們使用helper_functions.py中的plot_reg_strength_vs_score,你可以在github上找到。

plot_reg_strength_vs_score(cv_result) + theme(figure_size=(10,5))

請注意,準確度覆蓋的不是一條線而是一個區域,因為在交叉驗證中,我們對每一次都有一個準確度分數。圖中的觀察結果:

在擬合的正則化強度(6->0.95)下,kick 模型總體表現最佳。

性能峰值介於5–6之間,這與所選值一致。在強度較小的情況下,我懷疑模型中剩餘的多餘變量會產生太多的噪聲,然後正則化會去掉太多的相關信息。

結論:正則回歸模型的性能

基於交叉驗證的準確度得分,我得出結論,我們在生成鼓聲識別模型方面相當成功。尤其是底鼓很容易區別於其他兩種類型的鼓。正則化回歸也為模型增加了很多價值,降低了模型的整體方差。最後,tsfresh展示了從這些基於時間序列的數據集生成特徵的巨大潛力。

改進模型的潛在途徑有:

原文連結:https://towardsdatascience.com/expanding-your-regression-repertoire-with-regularisation-903d2c9f7b28

相關焦點

  • 線性回歸的正則化 ——嶺回歸與LASSO回歸
    ,但有時使用線性回歸可能會產生過擬合的現象,此時我們通常有兩種途徑解決:一是對特徵進行選擇,減少特徵數量,二是使用正則化的方法,這樣可以保留所有的特徵,而在正則化時我們通常會採用嶺回歸或LASSO回歸,今天我們就來介紹一下這兩種正則化方法。
  • 線性模型(二)正則化的回歸
    正則化的回歸正則化的回歸是在普通回歸經驗風險中加入正則項構成的回歸,如式(9-10)所示:正則化原理最常見的正則化方法是使用Lp正則化項,即Lp範數,其數學表達式為式(9-11):最小𝛽周圍不斷擴展的等高線與上述幾何圖形相切的點,即為𝛽的滿足限制條件的取值,L1的限制下該等高線會和Y軸相切得到X軸上係數為0的𝛽,而與L2得到的是非零的兩個𝛽Lasso和Ridge回歸L1的回歸稱為Lasso(套索)回歸,L2的回歸稱為Ridge(嶺)回歸
  • sklearn中的邏輯回歸中及正則化
    0x00 前言 在邏輯回歸中添加多項式項,從而得到不規則的決策邊界,進而對非線性的數據進行很好的分類。但是眾所周知,添加多項式項之後,模型會變變得很複雜,非常容易出現過擬合。因此就需要使用正則化,且sklearn中的邏輯回歸,都是使用的正則化。0x01 邏輯回歸中使用正則化 對損失函數增加L1正則或L2正則。
  • 吳恩達《Machine Learning》精煉筆記 3:回歸問題和正則化
    主要講解的內容包含:邏輯回歸代價函數線性回歸和邏輯回歸的比較正則化問題分類問題hθ(x)作用是對於給定的輸入變量,根據選擇的參數計算輸出變量=1的可能性,即:hθ(x)=P(y=1|x;θ)例如:對於給定的x,通過已經確定的參數計算得出
  • 最全的線性回歸算法庫總結—— scikit-learn篇
    ,這些類庫都可以用來做線性回歸分析,本文就對這些類庫的使用做一個總結,重點講述這些線性回歸算法庫的不同和各自的使用場景。為了得到線性回歸係數θθ,我們需要定義一個損失函數,一個極小化損失函數的優化方法,以及一個驗證算法的方法。損失函數的不同,損失函數的優化方法的不同,驗證方法的不同,就形成了不同的線性回歸算法。scikit-learn中的線性回歸算法庫可以從這三點找出各自的不同點。
  • 機器學習 - 正則化
    如果我們通過另一種方式允許b修改,那麼學習將有效地在一到兩個自由度之間。這個模型比兩個自由度的模型簡單,但比只有一個自由度的模型複雜。你需要在完美地擬合訓練數據和保持模型足夠簡單以確保它能很好地推廣之間找到合適的平衡。
  • 機器學習中的正則化到底是什麼意思?
    L1正則化和L2正則化可以看做是損失函數的懲罰項。所謂『懲罰』是指對損失函數中的某些參數做一些限制。對於線性回歸模型,使用L1正則化的模型建叫做Lasso回歸,使用L2正則化的模型叫做Ridge回歸(嶺回歸)。下圖是Python中Lasso回歸的損失函數,式中加號後面一項α||w||1即為L1正則化項。
  • sklearn學習(二):邏輯回歸
    梯度下降法:這裡推薦梯度下降算法原理講解    https://blog.csdn.net/qq_41800366/article/details/86583789        實踐中,我們一般不用操心優化方法,大部分機器學習庫都內置了各種邏輯回歸的優化方法。5.
  • 一文詳解正則化(regularization)
    以下通過一個簡單的實驗說明正則化的作用。對直線 y=x 進行等間距採樣,並且加入隨機噪聲,得到 10 個數據樣本如下:▲ 圖1採用以 Sigmoid 為激活函數的 2 層神級網絡模型擬合訓練數據,圖 2.1、2.2 分別為 λ=0、λ=0.5 的模型擬合結果:可以看到,通過正則化
  • 正則化方法小結
    Reference在總結正則化(Regularization)之前,我們先談一談正則化是什麼,為什麼要正則化。L2範數有很多名稱,有人把它的回歸叫「嶺回歸」(Ridge Regression),也有人叫它「權值衰減」(Weight Decay)。
  • (基礎篇) PHP需要它—PHP擴展庫
    MySQL、MySQLi、Overload、GD2等這些庫則被放在PECL外部擴展庫中,需要時在php.ini配置文件中選擇加載。在Windows下加載擴展庫,是通過修改php.ini文件來完成的。用戶也可以在腳本中通過使用dl()函數來動態加載。PHP擴展庫的DLL文件都具有php_前綴。很多擴展庫都內置於Windows版本的PHP中,要加載這些擴展庫不需要額外的DLL文件和extension配置指令。Windows下的PHP擴展庫列表列出了需要或曾經需要額外DLL文件的擴展庫。
  • 機器學習入門之範數與正則化
    0.導語研究一下範數與正則化,並做相應記錄!
  • 邏輯回歸算法介紹及其參數講解
    它們的模型形式基本上相同,都具有 w'x+b,其中w和b是待求參數,其區別在於他們的因變量不同,多重線性回歸直接將w'x+b作為因變量,即y=w'x+b,而邏輯回歸則通過函數L將w'x+b對應一個隱狀態p,p =L(w'x+b),然後根據p與1-p的大小決定因變量的值。如果L是logistic函數,就是邏輯回歸,如果L是多項式函數就是多項式回歸。
  • 二.線性回歸(二)
    2.APIsklearn.linear_model.SGDRegressor(loss="squared_loss", fit_intercept=True, learning_rate ='invscaling', eta0=0.01) 支持不同的loss函數和正則化懲罰項來擬合線性回歸模型參數 loss
  • TensorFlow(Keras)中的正則化技術及其實現(附代碼)
    可以通過減少訓練數據中的特徵數量並通過各種技術降低網絡的複雜性來解決過度擬合問題正則化技術通過限制網絡內權重值所保持的值範圍來減少神經網絡過度擬合的可能性(稍後會對此進行更多介紹)。本文介紹了兩種對損失函數的結果施加約束條件的正則化策略。
  • 徹底搞懂機器學習中的正則化
    Reference在總結正則化(Regularization)之前,我們先談一談正則化是什麼,為什麼要正則化。個人認為正則化這個字眼有點太過抽象和寬泛,其實正則化的本質很簡單,就是對某一問題加以先驗的限制或約束以達到某種特定目的的一種手段或操作。在算法中使用正則化的目的是防止模型出現過擬合。一提到正則化,很多同學可能馬上會想到常用的L1範數和L2範數,在匯總之前,我們先看下LP範數是什麼鬼。
  • 在機器學習的世界裡打怪升級——談談正則化
    前面幾篇我們主要介紹了線性回歸模型,它易於理解,可解釋性強。但它有一個弱點,就是容易發生過擬合,尤其是在高維特徵下。 我們再來回顧下線性回歸模型: 可以看到,模型給每一個特徵都「配備」了一個參數w。
  • 8種用Python實現線性回歸的方法
    為什麼我們還需要線性回歸呢?一方面,線性回歸所能夠模擬的關係其實遠不止線性關係。線性回歸中的「線性」指的是係數的線性,而通過對特徵的非線性變換,以及廣義線性模型的推廣,輸出和特徵之間的函數關係可以是高度非線性的。
  • 徹底搞懂機器學習裡的L1與L2正則化
    特徵錦囊:今天一起搞懂機器學習裡的L1與L2正則化今天我們來講講一個理論知識,也是老生常談的內容,在模型開發相關崗位中出場率較高的,那就是L1與L2正則化了,這個看似簡單卻十分重要的概念,還是需要深入了解的。網上有蠻多的學習資料,今天我就著自己的理解也寫一下筆記。
  • 7種執行簡單的線性回歸的分析與討論!
    由於scikit-learn是一種免費的機器學習庫,它具有回歸、分類、聚類、模型選擇和降維等功能,所以常用的方法是從該庫調用線性模型類並擬合數據。雖然這可以為應用機器學習的其他流水線特性(例如數據規範化,模型係數正則化,將線性模型提供給另一個下遊模型)提供額外的優勢,但這通常不是確定回歸係數(和一些基本的相關統計)最快或最乾淨、簡單的方法。