這個章節的主要目標是學習各種邏輯斯回歸分類器演算法的實作與效能,包含二元分類、多類別分類、正規化和處理不平衡資料集等技術,使用Iris資料集當作學習範例。而Exercise則擴展至更多類型的分類器評估,不僅包含邏輯斯迴歸,還加入DecisionTreeClassifier、RandomForestClassifier、AdaBoost、XGBoost、LightGBM以及KNeighborsClassifier和RadiusNeighborsClassifier,並使用Olivetti人臉資料集和KDD Cup 1999資料集進行測試。透過這些程式碼,可以學習到該如何實作不同類型的分類器、如何進行資料預處理(如標準化和特徵轉換)、如何評估模型效能(準確率、訓練時間和評估時間),以及如何選擇適合特定問題的演算法。
OS: Windows 11 23H2
CPU: Intel Core i7-13700K
GPU: NVIDIA GeForce RTX 4070 SUPER 12G
RAM: DDR5 64G 5600MT/s
Python Package Manager: uv
Python Version: 3.10.16
Python Package: numpy, pandas, sklearn, rich, seaborn, matplotlib
IDE: Visual Studio Code
為方便查看運行結果,故額外使用rich函式庫建立兩個Function格式化印出指定內容。
16.1 Training a Binary Classifier
Code:
Explanation:
這段程式碼使用sklearn提供的LogisticRegression方法訓練邏輯斯迴歸分類器的過程。首先透過load_iris方法載入Iris數據集並取前100筆資料,接著使用StandardScalar方法標準化處理特徵,然後訓練邏輯斯迴歸模型。最後,使用訓練好的模型對一測試觀測值進行預測,並顯示預測結果及其機率。
Discussion:
邏輯斯迴歸的優點在於計算效率高且模型可解釋性強。然而,其限制包括只能處理線性決策邊界,且較複雜的非線性關係需要特徵工程來解決,同時容易受極端值影響。
Result:
16.2 Training a Multiclass Classifier
Code:
Explanation:
這段程式碼使用sklearn的LogisticRegression方法訓練多類別邏輯斯迴歸分類器的過程。與二元分類不同,這次使用完整的Iris數據集(包含三個類別),並設置multi_class為ovr,採用一對多進行多類別分類。使用StandardScaler標準化特徵後訓練模型,最後對一測試觀測值進行預測並顯示預測結果及其機率。
Discussion:
多類別的邏輯斯迴歸優點是可處理三個或更多類別的分類問題,保持了模型的可解釋性。然而,當類別數量增加時,計算成本會上升,且各類別間的不平衡可能影響模型表現,同時仍然受限於線性決策邊界。
Result:
16.3 Reducing Variance Through Regularization
Code:
Explanation:
這段程式碼使用帶有L2正則化的邏輯斯迴歸分類器,並透過設定Cs參數以交叉驗證自動選擇最佳正則化強度。首先載入Iris資料集,使用StandardScaler將特徵標準化後訓練LogisticRegressionCV模型,該模型會自動測試10個不同的C值並選擇最佳模型。最後透過model.C_印出自動選擇的最佳C值。
Discussion:
L2正則化的優點是可以減少模型過度擬合的風險,提高泛化能力,並能處理多重共線性問題。然而,過度正則化可能導致擬合不足,且自動選擇參數的交叉驗證過程會增加計算成本。另外,正則化參數的選擇範圍若不適當可能影響模型表現。
Result:
16.4 Training a Classifier on Very Large Data
Code:
Explanation:
這段程式碼使用sklearn訓練處理大規模資料的邏輯斯迴歸分類器。並設置solver參數為sag採用隨機平均梯度下降優化器來高效處理大型資料集。首先載入Iris資料集並使用StandardScaler標準化特徵,然後使用指定優化器訓練模型,最後對新觀測值進行預測並顯示結果及其機率。
Discussion:
SAG優化器特別適合處理大型資料集,能顯著縮短訓練時間且具有較好的收斂特性。然而,它在小型資料集上可能表現不如其他優化器,且對學習率敏感,記憶體消耗較高,在特徵數量極多時可能面臨效率挑戰。
Result:
16.5 Handling Imbalanced Classes
Code:
Explanation:
這段程式碼主要為建立一個可處理不平衡類別問題的邏輯斯迴歸分類器。首先從Iris資料集中選取部分資料,並將三個類別合併為二元分類問題,接著透過設定 class_weight參數為balanced來平衡不同類別的權重。這種方法會自動調整權重,使少數類別樣本在訓練過程中有更高的重要性,從而改善在不平衡資料上的分類效果。
Discussion:
平衡類別權重的優點是能有效處理類別不平衡問題,提高對少數類別的預測敏感度,且實現簡單。然而,過度重視少數類別可能導致過度擬合,並且在極度不平衡的情況下效果有限,同時可能降低整體準確率。
Result:
Settings
這邊使用scikit-learn的real-world datasets中的KDD CUP 1999(大型)與Olivetti Face(小型)作為兩個不同數量級的對比資料集,對之前所有章節中所有的分類類型模型進行訓練與比較差異。
KDD CUP 1999 是第三屆國際知識發現與資料挖掘工具競賽所使用的資料集,旨在建立網路入侵檢測系統。此資料集由美國麻省理工學院林肯實驗室於1998年處理DARPA入侵檢測系統評估項目的tcpdump數據而成。資料中包含了大量在封閉網路環境中人工注入的攻擊行為,記錄了超過40種不同類型的網路攻擊,包括拒絕服務攻擊、未授權訪問等。此資料集在機器學習領域被廣泛用於異常檢測研究,但需注意其人工生成的特性使得部分異常數據在真實世界中並不常見,這對無監督異常檢測可能造成限制。
Olivetti Face 是一個經典的人臉識別資料集,收集了40位不同人士各10張灰階人臉照片,總共400張圖像。每張圖像尺寸為64×64像素,以人臉為中心。這些照片在不同時間、不同光照條件以及不同面部表情(開眼/閉眼、微笑/不微笑)和面部細節(有眼鏡/無眼鏡)下拍攝。資料集中的「目標」是從0到39的整數,表示照片中人物的身份。由於每個類別僅有10個樣本,這個相對較小的資料集在無監督或半監督學習方面更具研究價值,被廣泛應用於人臉識別、圖像重建和降維技術等研究中。
Explanation:
這邊透過fetch_olivetti_faces與fetch_kddcup99兩個方法來載入兩個不同的資料集:Olivetti人臉辨識資料集和KDD Cup 99網路安全資料集。
首先下載Olivetti資料集與KDD Cup 99資料集並儲存在本地的./data位置,接著使用StandardScaler方法對Olivetti資料進行標準化處理。
KDD Cup資料集透過設定subset參數為'SA'可指定只載入"象徵性攻擊"的子集,而設定percent10參數為False可載入完整的資料集,而非僅10%的樣本。接著進行標籤轉換的處理,將正常連接標記為0,任何形式的攻擊則標記為1 ,然後對數值特徵部分使用StandardScaler方法進行標準化,對文字類別特徵使用OneHotEncoder進行編碼(透過使用ColumnTransformer方法將兩個不同的標準化方法整合為複合預處理器 )。
最後,兩組資料集皆使用train_test_split方法分割成訓練集和評估集,為後續的模型訓練做準備。
Code:
Explanation:
接著分別對此章節中的不同邏輯斯回歸分類器和之前所有章節中的Classifier類型模型如DecisionTreeClassifier、RandomForestClassifier、AdaBoostClassifier、XGBoost Classifier、LightGBM Classifier、KNeighborsClassifier、RadiusNeighborsClassifier這些不同的模型使用兩個不同的資料集進行訓練與評估,並分別記錄其所需訓練時間與所需評估時間。
Code:
Explanation:
對於KNeighborsClassifier與RadiusNeighborsClassifier這兩個模型在評估時,由於在KDD Cup資料集中使用model.predict方法回傳的numpy陣列會超過2GB的大小,會直接造成Jupyter Kernel當機,故特別創建一function可批次處理預測的結果,最終在回傳完整的結果給accuracy_score方法進行準確率評估,可有效避免記憶體出現問題。
Code:
Result:
Discussion:
首先觀察右上圖KDD CUP 1999資料集的結果,在此資料集上,幾乎所有模型都達到了接近100%的高準確度,顯示此類網絡安全資料具有明顯的分類特徵。然而,各模型在效能上仍有顯著差異。邏輯斯迴歸模型(標準版)以僅1秒多的訓練時間和極短的評估時間(約21ms)就可達到100%的準確度,展現出卓越的效能平衡。DecisionTreeClassifier和RandomForestClassifier也同樣達到100%的準確度,但RandomForestClassifier的訓練時間(約17秒)明顯高於DecisionTreeClassifier(約7秒)。此外,KNeighborsClassifier雖然訓練時間極短(僅77.57ms),但其評估時間卻高達91秒,這可能是因為KNN在預測階段需要計算與所有訓練樣本的距離。而RadiusNeighborsClassifier的評估時間更長,達到463秒,成為所有模型中評估最慢的,且準確度略低(98.65%)。
相比之下,Olivetti人臉資料集顯示出更多模型表現的變異性。此資料集的挑戰在於樣本較少但維度較高,通常用於測試模型的泛化能力。在此資料集上,邏輯斯迴歸模型依然表現最佳,標準版達到97%的準確度,且訓練時間僅為183ms。交叉驗證版本(CV)和使用SAG solver的版本不只準確度略降(96%),且訓練時間還大幅增加至7秒以上。這反映出當資料集規模較小時,複雜的優化方法可能導致過度擬合或計算負擔增加而效益不明顯。而DecisionTreeClassifier在此資料集上表現極差,僅達48%準確度,說明DecisionTreeClassifier在預設條件下適合處理高維度但樣本少的影像資料。
在Olivetti資料集上,RandomForestClassifier和改進後的AdaBoost展現出相當好的表現,分別達到92%和90%的準確度。然而,標準AdaBoost (未額外調整其他參數)卻只有4%的準確度,顯示出未經優化的模型在特定資料集上可能完全失效。這強調了模型參數調整的重要性。XGBoost和LightGBM在此資料集上的表現一般(分別為69%和77%的準確度),與KDD Cup資料集上的接近完美表現形成鮮明對比,說明這些模型在不同性質資料上的適應性差異。
從時間效能角度來看,KDD Cup資料集上的模型訓練時間普遍較長,但這與資料集規模相關。值得注意的是,KNeighborsClassifier和RadiusNeighborsClassifier在此資料集上評估時間極長,但在Olivetti資料集上評估時間僅為毫秒級。這突顯了基於距離計算的模型在大規模資料集上的效能局限。相反地,邏輯斯迴歸類模型在兩個資料集上都保持較短的評估時間,展現出在實時應用場景中的潛力。
綜合兩個資料集的結果可以得出幾個重要的發現。首先,邏輯斯迴歸模型在兩個不同性質的資料集上都表現優異,展現出良好的通用性和效能平衡。其次,RandomForestClassifier和AdaBoost需要適當調整才能發揮最佳性能,尤其在具有挑戰性的資料集上。第三,基於距離的分類器如KNeighborsClassifier和RadiusNeighborsClassifier在大規模資料集上的評估時間可能成為實際應用的瓶頸。最後,複雜的模型如XGBoost和LightGBM在某些資料集上並不一定優於傳統模型,選擇應依據具體問題特性。
Difficulties Encountered and Solutions
1. 載入KDD Cup 1999資料集標準化的問題
Difficulties:載入kddcup99資料集使用StandardScaler進行標準化時,若並未進行額外處理,則會無法對具有字串類型的資料進行處理。
Solution:由於StandardScaler只能處理數值型資料 ,故必須在載入資料集後,自行設定protocol、service與flag這幾個文字類別的值為0, 1, 2,再透過ColumnTransformer方法分別對數值類型的欄位使用StandardScaler,文字類型的欄位使用OneHotEncoder。最後再使用fit_transform方法對資料集進行標準化,即可進行後續處理。
2. Radius Classifier與KNN Classifier測試評估集的問題
Difficulties:使用RadiusNeighborsClassifier與KNeighborsClassifier方法訓練完模型後,對KDD CUP 1999評估資料集使用model.predict方法對整個評估集進行測試時,若並未進行額外處理,則會造成記憶體爆掉,出現以下問題,並導致Jupyter Notebook的Kernel直接停止運作。
19:36:33.066 [info] Restart requested e:\Coding\Python class file\ML\P6_ex.ipynb
19:36:33.073 [info] Process Execution: c:\Windows\System32\taskkill.exe /F /T /PID 67784
19:36:33.076 [info] Process Execution: e:\Coding\Python class file\ML\venv\Scripts\python.exe -c "import ipykernel; print(ipykernel.__version__); print("5dc3a68c-e34e-4080-9c3e-2a532b2ccb4d"); print(ipykernel.__file__)"
19:36:33.124 [info] Process Execution: e:\Coding\Python class file\ML\venv\Scripts\python.exe -m ipykernel_launcher --f=c:\Users\~\AppData\Roaming\jupyter\runtime\kernel-v300248db625a3a91aafd3bcfa6ec22a4693d4611c.json
> cwd: e:\Coding\Python class file\ML
19:36:33.806 [info] Restarted 82008dba-db37-4e64-9d93-c70c883c793b
19:42:08.774 [error] Disposing session as kernel process died ExitCode: 1073741845, Reason: e:\Coding\Python class file\ML\venv\lib\site-packages\sklearn\linear_model\_logistic.py:465: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. OF ITERATIONS REACHED LIMIT.
Increase the number of iterations (max_iter) or scale the data as shown in:
https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
n_iter_i = _check_optimize_result(
e:\Coding\Python class file\ML\venv\lib\site-packages\sklearn\linear_model\_logistic.py:465: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. OF ITERATIONS REACHED LIMIT.
Solution:雖然上述錯誤顯示的是ConvergenceWarning,但通過單純設置max_iter並無法解決問題,且主要運行錯誤之處也並非在訓練時出現,是在評估時出現,故將評估集透過多個batch進行分次評估以防止出現記憶體爆掉的問題。
References
[1] Machine Learning with Python Cookbook-2nd, by Kyle Gallatin and Chris Albon, O'Reilly, 2023, ISBN: 9781098135720
[2] 機器學習入門:使用Scikit-Learn與TensorFlow, 黃建庭, 碁峰, 2021, ISBN: 9786263240285
[3] 精通機器學習:使用Scikit-Learn, Keras與TensorFlow(第三版), Aurélien Géron, 歐萊禮, 2024, ISBN: 9786263246676
[4] scikit-learn 機器學習實戰, 鄧立國 郭雅秋 陳子堯 鄧淇文, 清華大學, 2022, ISBN: 9787302604396
[5] Python資料科學學習手冊(第二版), Jake VanderPlas , 歐萊禮, 2023, ISBN: 9786263246843