Python大規模機器學習》—1.1.3使用Python進行向上擴展">《Python大規模機器學習》—1.1.3使用Python進行向上擴展
741
2025-04-04
3.5????超參數調整
與成批學習一樣,在測試超參數的最佳組合時,在非核心算法中沒有捷徑,需要嘗試一定數量的組合,才能找出可能的最佳解決方案,并使用樣本外錯誤度量手段來評估其性能。
由于你實際上不知道所預測問題是否具有簡單平滑的凸損失或更復雜的損失,而且不確切知道超參數如何相互交互,所以沒有足夠組合很容易陷入次優的局部最小值。不幸的是,目前Scikitlearn還沒有針對非核心算法提供專門的優化程序。考慮到在長數據流上訓練SGD需要很長時間,調整超參數可能確實會成為使用這些技術在數據上構建模型的瓶頸。
這里,我們提出有助于節省時間和盡量達到最佳結果的經驗法則。
首先,調整適合放入內存的數據樣本或窗口上的參數。正如在核SVM中看到的那樣,即使數據流很大,使用庫樣本也會非常快。然后你可以在內存中進行優化,并使用流中找到的最佳參數。
如微軟研究院的Léon Bottou在其技術論文“Stochastic Gradient Descent Tricks”中所說的那樣:
“數學上隨機梯度下降與訓練集大小完全無關。”
所有關鍵參數都是如此,但僅學習率除外;對于樣本效果更好的學習率對整個數據來說效果最好。另外,通過在小采樣數據集上嘗試收斂,能猜測理想的數據傳遞次數。根據經驗,我們匯總了算法檢查的10**6個示例的指示性數量,正如Scikit-learn文檔所指出的那樣,我們經常發現該數字是準確的,盡管理想的迭代次數可根據正則化參數而改變。
雖然在使用SGD時大多數工作可以用相對較小的規模完成,但我們必須定義如何解決確定多個參數的問題。傳統上,手動搜索和網格搜索是最常用方法,網格搜索將通過系統測試可能參數的所有組合來解決問題(例如,使用10或2的不同乘方以對數尺度進行檢查)。
最近,James Bergstra和Yoshua Bengio在其論文“Random Search for Hyper-Parameter Optimization”中提出了一種基于超參數值隨機采樣的不同方法。盡管基于隨機選擇,但如果超參數的數量很少,并且可以超過當參數很多而且并非所有參數都與算法性能相關時系統搜索的性能,那么這種方法通常在結果上與網格搜索等價(但運行次數更少)。
關于為什么這種簡單而有吸引力的方法在理論上如此有效,我們把它留給讀者以發現更多的理由,
請參考前面提到的Bergstrom和Bengio的論文。在實踐中,我們已經體驗到了相比其他方法的優越性之后,我們提出了一種基于Scikit-learn中ParameterSampler函數的方法,它在上面示例代碼中對數據流運行良好,以下示例代碼中給出具體實現。ParameterSampler能夠隨機采樣不同組的超參數(來自分布函數或離散值列表),以便隨后通過set_params方法來學習SGD:
該代碼利用了共享單車數據集非常小并且不需要任何采樣這樣的事實。在其他情況下,限制被處理的行數很有意義,或者在通過蓄水池采樣或其他采樣技術之前創建一個較小的樣本是合理的。如果你想更深入地探索優化過程,可以更改random_tests變量,從而修改要測試的采樣超參數組合的數量。然后使用更接近1.0的數字(如果不是1.0本身)
修改if tmp_rmsle/print_rmsle <= 1.01條件,
從而讓算法完全收斂,直到有適當的預測能力。
雖然建議使用分布函數而不是從值列表中選取,但你仍然可通過簡單地擴大可能從列表中選取值的數量來適當使用之前討論的超參數范圍。例如,對于L1和L2正則化中的alpha,可以使用NumPy的函數arrange,用一個小步進,例如10.0**- np.arange(1,7,step=0.1),或者對num參數使用NumPy logspace:1.0/np.logspace(1,7,num=50)。
其他SVM快速學習方法
盡管Scikit-learn包提供了足夠的工具和算法來進行非核心學習,但在免費軟件中還有很多其他選擇方法。有些基于與Scikit本身相同的庫,例如Liblinear/SBM,其他是全新的,如sofia-ml、LASVM和Vowpal Wabbit。例如,Liblinear/SBMis基于選擇性塊最小化,并實現為原始庫liblinear-cdblock(https://www.csie.ntu.edu.tw/~cjlin/libSVMtools/#large_linear_classification_when_data_cannot_ fit_in_memory)的分叉。Liblinear/SBM使用新樣本數據訓練并通過使用學習器的技巧,來擬合非線性SVMS,以適應大量無法存儲在內存中的數據,并將其與先前用于最小化的樣本進行混合(因此算法名中采用blocked項)。
SofiaML(https://code.google.com/archive/p/sofiaml/)是另一種選擇方法,SofiaML基于一種名為Pegasos SVM的在線SVM優化算法,該算法是一種在線SVM近似,就像由Leon Bottou創建的另一種名為LaSVM的軟件一樣(http://leon.bottou.org/projects/laSVM)。所有這些方法都可以處理稀疏數據,特別是文本,并解決回歸、分類和排序問題。迄今為止,我們測試過的方案中,除了Vowpal Wabbit以外,
沒有別的方案更快速、功能更強大,下面將介紹該軟件,并用它演示如何將外部程序與Python集成。
Vowpal Wabbit快速實現非線性
Vowpal Wabbit(VW)是一個快速在線學習開源項目,最初于2007年由雅虎的John Langford、Lihong Li和Alex Strehl (http://hunch.net/?p=309)研究發布,然后由Microsoft Research贊助并且John Langford成為微軟首席研究員。該項目已經發展多年,而且有近百名貢獻者參與其中,目前為8.1.0版本(本章寫作時)。(若要查看多年累積的可視化效果,
請訪問使用軟件Gource制作的有趣視頻https://www.youtube.com/watch?v=-aXelGLMMgk)。迄今為止,VW仍在不斷發展,并在每次開發迭代中提高其學習能力。
相比于其他方法(LIBLINEAR、Sofia-ml、SVMgd和Scikit-learn),VM的突出特點是速度非常快。其秘密很簡單但非常有效:能同時加載數據并從中學習。異步線程對輸入的實例進行解析,學習線程在不相交的特征集上工作,從而確保即使解析過程涉及創建高維特征也具有高計算效率(如二次或三次多項式展開)。在大多數情況下,學習過程的真正瓶頸是磁盤或網絡傳輸數據給VM的傳輸帶寬。
VM可計算分類(甚至是多類和多標簽)、回歸(OLS和分位數)和主動學習問題,能夠提供大量附帶學習工具(稱為縮減),例如矩陣分解、潛在狄利克雷分布(LDA)、神經網絡、n-gram語言模型和拔靴法。
安裝VW
不幸的是,獲得Windows操作系統上運行的VW版本有點難度。為了創建它,請參考VW本身的文檔,其中詳細解釋了編譯過程(https://github.com/JohnLangford/vowpal_wabbit/blob/master/README.windows.txt)。
在本書附帶的網站上將提供書中用到的VW 8.1.0版本的32位和64位Windows二進制文件。
理解VW數據格式
VW使用特定數據格式,并從shell調用。John Langford在其在線教程(https://github.com/JohnLangford/vowpal_wabbit/wiki/Tutorial)中使用的樣本數據集代表
屋頂可更換的三棟房屋,非常有趣,推薦讀者一起學習:
很明顯,文件格式沒有標題,這是因為VW使用哈希技巧將特征分配到稀疏向量中,因此事先知道那些根本不需要的特征。數據塊通過管道(字符|)劃分成命名空間,作為不同的特征集群,每個集群都包含一個或多個特征。
第一個名稱空間始終是包含響應變量的名稱空間,而響應可以是指向要回歸的數值的實數(或整數)、二分類或多個類中的某類。響應始終是在一條線上找到的第一個數字。二分類中1表示正數,-1表示負數(0作為響應僅用于回歸)。多類的話,則從1開始編號,不建議使用間隔編號,因為VW訪問最后一個類時會考慮1和最后一個之間的所有整數。
緊鄰響應值后面的數字是權重(用來告訴你將實例看作單個實例還是整體的一部分),然后是起初始預測作用的基數(某種偏差)。最后,前有撇號字符(')的標簽可以是數字或者文本,它能在后面VW輸出(預測中,每個估計對應一個標簽)中找到。權重、基數和標簽不是強制性的:如果省略,權重賦值為1,基數和標簽無關緊要。
在第一個名稱空間后,可根據需要添加盡可能多的名稱空間,并用數字或字符串作為其標簽。為了說明是名稱空間的標簽,應該將它放在管道后,例如|label。
在名稱空間標簽的后面,可以按名稱添加任何特征,特征名可以為任何內容,但應包含管道或冒號。可以將整個文本放在名稱空間中,這樣每個單詞都將被視為一個特征,每個特征都將被賦值為1。如果想賦其他不同數字,只需在特征名末尾添加冒號,并將其值放在它后面即可。
例如,Vowpal Wabbit可讀取的有效行是:
第一個名稱空間中,響應為0,實例權重為1,基數為0.5,其標簽為third_house。名稱空間無名稱并且由四個特征構成,即price(值為.53)、sqft(值為.32)、age(值為.87)和1924(值為1)。
如果某個特征在一個實例中有,但在另一個實例中沒有,則算法會在第二個實例中假設此特征值為零。因此,上例中的1924這樣的特征可當作二進制變量,因為其存在時自動被賦值為1,缺少時則為0,這也告訴你VW如何處理缺失值——自動將其賦為0值。
缺少值時,可通過添加新特征輕松處理缺失值。例如,如果該特征為age,可以添加一個新特征age_missing,新特征將是一個值為1的二進制變量。在估計系數時,該變量將作為缺失值估計器。
http://hunch.net/~vw/validate.html
Python集成
vowpal_porpoise、Wabbit Wappa和pyvw等軟件包能與Python集成,并且在Linux系統中很容易安裝,但在Windows上安裝比較困難。無論使用Jupyter還是IDE,將VW與Python腳本集成的最簡單方式是利用來自subprocess包的Popen函數。它可以使VW與Python并行運行,Python只是等待VM完成其操作并捕獲其輸出,然后將輸出顯示在屏幕上:
這些函數返回學習過程的輸出列表,使其易于處理,并提取相關的可重用信息(如錯誤度量)。作為其正確運行的前提條件,請將VW可執行文件(vw.exe文件)放在Python工作目錄或系統路徑中以便找到它。
通過調用函數來處理先前記錄的房屋數據集,可以看到它的工作過程及其輸出結果:
輸出的初始行只是顯示所使用的參數,并確認正在使用哪個數據文件。最令人感興趣的是按流化實例數顯示的逐步驟過程(按2的冪報告,例如1、2、4、8、16等等)。損失函數顯示平均損失度量,在第一次迭代后漸進向前,通過將字母h放在后面來表示其損失(如果排除拒絕,則有可能只報告樣本內度量)。在example weight列上顯示實例權重,然后將實例進一步描述為current label、current predict,并顯示在該行上找到的特征數量(current features)。所有這些信息有助于監視流和學習過程。
學習完成后會顯示某些報告措施。平均損失最重要,特別是在使用保留時。出于比較原因,使用這種損失最有效,因為它能立即與best constant’s loss(簡單常數的基線預測能力)以及使用不同參數配置的不同運行結果進行對比。
集成VW和Python的另一個非常有用的函數是自動將CSV文件轉換為VW數據文件的函數。可以在下面代碼中找到它,它將幫助處理以前的共享單車和森林覆蓋類型問題,它很容易用在你自己的項目中:
幾個使用簡化SVM和神經網絡的示例
VM會最大限度地最小化一般成本函數,如下式所示:
與之前看到的其他公式一樣,w為系數向量,根據所選擇的損失函數(OLS,logistic或hinge)獲取每個xi和yi的最優化。lambda1和lambda2是正則化參數,默認情況下為零,但可以使用VW命令行中的“--l1”和“--l2”選項進行設置。
基于這種基本結構,隨著時間推移,通過使用簡化范式,VM已經變得更加復雜和完整。簡化只是一種重用現有算法以解決新問題的方法,這樣無須從頭開始編碼新的求解算法。換句話說,如果你有復雜的機器學習問題A,只需將其簡化到B。解決B的線索在A的解決方法中,這也很有道理。人們對機器學習的興趣越來越濃厚,問題數量爆炸式增長,卻無法創造新解決算法。一種可行的方法就是利用基本算法的已有功能,以及VM隨著時間推移適用性越來越強而程序依然很緊湊的原理。如果你對這種方法感興趣,請參考John Langford的兩篇教程:http://hunch.net/~reductions_tutorial/和http://hunch.net/~jl/projects/reductions/reductions.html。
為了進行說明,我們簡要介紹兩個簡化示例,即使用RBFkernel的SVM和以純非核心方式使用VW的淺層神經網絡,為此使用了一些簡單數據集。
Iris數據集更改為二分類問題,以預測鳶尾花卉屬于Setosa還是Virginica:
然后對回歸問題使用波士頓房屋定價數據集:
首先,我們嘗試使用SVM。kvsm是基于LaSVM算法(具有在線和主動學習功能的快速核分類器—http://www.jmlr.org/papers/volume6/bordes05a/bordes05a.pdf)的簡化,無偏差項。VW版本通常只需一次傳遞,并對隨機選取的支持向量進行1到2次重新處理(盡管有些問題需要多次傳遞和再處理)。在本例中,我們按順序使用單次傳遞和幾次重新處理來在二分類問題上擬合RBF核(KSVM僅用于分類問題)。實現的核是線性的徑向基函數和多項式。為使它工作,請使用“--kSVM”選項,可以通過“--reprocess”設置重新處理次數(默認值為1),通過“--kernel”選擇內核類型(選項為linear、poly和rbf)。如果內核為多項式,則將“--degree”設置為整數。如果使用RBF,則將“—floatband”設置為浮點數(默認值為1.0)。另外必須強制讓l2正則化;否則,簡化過程無法正常運行。示例中,我們將RBFkernel的帶寬設置為0.1:
神經網絡是VM的另一個很好的補充,由于Paul Mineiro的工作(http://www.machined-learnings.com/2012/11/unpimp-your-sigmoid.html), 讓VM能實現具有雙曲正切(tanh)激勵函數以及可選丟棄率(使用“--dropout”選項)的單層神經網絡。雖然只能決定神經元數量,但簡化神經網絡在回歸和分類問題上都效果很好,并且能順利進行以VM為輸入的其他轉換(如二次變量和n-gram),這樣使其成為一個多功能(神經網絡能解決很多問題)和快速的完整解決方法。示例中使用五個神經元和丟棄率處理波士頓數據集:
更快的共享單車
下面對以前創建的共享單車示例文件使用VW,以便解釋輸出組成。第一步,必須使用前面介紹的vw_convert函數將CSV文件轉換為VW文件。與以前一樣,通過使用由vw_convert函數的transform_target參數所傳遞的apply_log函數,來實現對數字響應的對數轉換:
幾秒鐘準備好新文件后,立即運行我們的算法,這是一種簡單的線性回歸(VW的默認選項)。預計學習100次,由VW自動實現的樣本外驗證進行控制(以可重復方式系統地進行抽取,每10次觀察一次進行驗證)。在此例中,我們決定在16 000個示例(使用“--holdout_after”選項)之后設置拒絕樣本。當驗證錯誤增加(而不是減少)時,VW在幾次迭代后停止(默認為3次,但可使用“--early_terminate”選項更改次數),以避免數據過擬合:
最終報告顯示完成了六次傳遞(從100種可能中),樣本外平均損失為0.428。由于我們關注RMSE和RMSLE,所以必須自己計算它們。
然后在文件pred.test中預測結果,以便能夠讀取它們并使用與訓練集中相同的拒絕策略計算錯誤度量。與之前用Scikitlearn的SGD所獲得的結果相比,這些結果確實要好很多(只用了一點時間):
使用VW處理森林覆蓋類型數據集
相比于以前的方法,VW能更好、更容易解決森林覆蓋類型問題。這一次,我們將不得不設置一些參數并控制糾錯競爭(ECT,VW使用“--ect”參數調用它),其中每個類在淘汰賽中競爭作為示例標簽。在很多實例中,ECT勝過一對多(OAA),但這不是通用規則,ECT是多類問題測試方法之一。(另一種選擇是“--log_multi”,它使用在線決策樹將樣本分成更小集合,并應用單預測模型。)我們將學習率設置為1.0,并使用“--cubic”參數創建三次多項式展開式,以指出哪些名稱空間必須互乘(在這種情況下,三次命名空間f用nnn字符串表示,后面緊接著是“--cubic”):
為讓示例運行更快速,我們將傳遞數限制為兩個,如果時間允許,你可將數字提高到100,并見證如何進一步提高所獲得的準確度。
在這里不需要進一步檢查錯誤度量,因為所報告的平均損失是對精確度1.0的補充,我們只是為了完整性
計算它,從而確認最后的拒絕精確度正好是0.769:
Python 機器學習
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。