從零開始學機器學習—分類器詳解
首先給大家介紹一個很好用的學習地址:https://cloudstudio.net/columns
今天我們將結合第一章節(jié)中清洗得到的菜品數據,利用多種分類器對這些數據進行訓練,以構建有效的模型。在這個過程中,我會詳細講解每一種分類器的原理及其重要性。
盡管這些知識點對于實踐來說并不是必須掌握的,因為第三方依賴包已經為我們完成了大量的封裝,使得調用這些功能僅需一行代碼,但理解其背后的原理仍然至關重要。這將有助于我們在實際應用中更好地把握模型的表現和改進的方向。
分類路線圖
在上一章節(jié)中,我們已經查看了微軟的小抄表,并對其進行了中文翻譯,希望這些內容對你有所幫助。今天,我們將繼續(xù)探索Scikit-learn提供的一個類似的速查表,但它的細粒度和信息量更加豐富。這份速查表不僅能幫助您快速查找相關信息,還能為您在調整估計器(分類器的另一個術語)時提供實用的指導。
速查表原文地址:https://scikit-learn.org/stable/machine_learning_map.html
圖片
表情??符號應理解為“如果此估計器沒有達到預期結果,則按照箭頭嘗試下一個”
然后,我們根據此路線圖選擇我們的分類器:
- 我們有超過 50 個樣本
- 我們想要預測一個類別
- 我們有標記過的數據
- 我們的樣本數少于 100000
- 我們可以嘗試 ? K-近鄰分類器
- 如果那不起作用,試試 ? SVC 和 ? 集成分類器
- ? 我們可以選擇線性 SVC
- 如果那不起作用,既然我們有數值數據,沒有文本數據
模型構建
接下來第一步則是將數據分為訓練集、測試集。
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import accuracy_score,precision_score,confusion_matrix,classification_report, precision_recall_curve
import numpy as np
cuisines_df = pd.read_csv("../data/cleaned_cuisines.csv")
cuisines_label_df = cuisines_df['cuisine']
cuisines_feature_df = cuisines_df.drop(['Unnamed: 0', 'cuisine'], axis=1)
X_train, X_test, y_train, y_test = train_test_split(cuisines_feature_df, cuisines_label_df, test_size=0.3)
線性 SVC 分類器
根據我們的學習路線圖,第一步我們需要嘗試線性SVC分類器。在深入講解SVC之前,我們有必要先了解一下支持向量機(SVM)。這是因為在你搜索SVC時,通常會找到大量關于SVM的資料,所以理解這兩者之間的區(qū)別是十分重要的。
接下來,我們將探討這兩者的不同之處,以及它們各自的特點和應用場景,以便為后續(xù)的學習奠定更扎實的基礎。
支持向量機(SVM)
支持向量機是一種強大的監(jiān)督學習算法,用于分類和回歸問題。SVM是一個廣泛的概念,涵蓋了分類和回歸問題;而SVC是SVM的特定應用,專門用于分類任務。在機器學習庫中,SVC通常是實現SVM的分類器的名稱,比如在Scikit-learn庫中。
支持向量機(SVM)有幾個子類,主要包括:支持向量分類(SVC)、支持向量回歸(SVR)、一類支持向量機(One-Class SVM)、 多類支持向量機(Multi-Class SVM)、概率支持向量機(Probabilistic SVM)。這些子類允許支持向量機在不同類型的任務中表現出色。每個子類都有其獨特的實現和優(yōu)化方式,以適應特定的應用場景。
舉個例子
如果理解線性 SVC 有些困難,我們來舉一個例子:
想象你在一個學校,有兩個班級:數學班和藝術班。每個學生都有不同的特點,比如他們的數學成績和藝術成績。你想根據這兩個成績把學生分到這兩個班級。
- 數據點:
每個學生可以用一個點在圖上表示:X1軸代表數學成績,X2軸代表藝術成績。
數學班的學生通常數學成績高,藝術成績相對低。
藝術班的學生通常藝術成績高,數學成績相對低。
- 分類目標: 你希望找到一條線(就像一個“分界線”)來把兩個班級的學生分開。
- 最大間隔: SVC會尋找一條最好的分界線,使得這條線和最近的學生(支持向量)之間的距離最大。這樣,即使有一些新的學生在數學和藝術成績上介于兩者之間,這條線依然能夠較好地分類他們。
- 處理復雜情況: 假設有一個學生的數學和藝術成績都很中等。用一條線可能很難將這個學生明確地分到一個班級。SVC可以通過“增加維度”,想象一下你有一個第三個維度,比如“運動成績”。在這個三維空間中,SVC可以找到一個更復雜的分界面,來更好地分開這兩個班級的學生。
通過這個比喻,SVC的核心就是:
- 它找出一種最佳的方法來區(qū)分不同的群體(如班級)。
- 通過最大化與最近的學生(支持向量)之間的距離,確保分類更加穩(wěn)健。
- 在面對復雜情況時,可以使用其他特征(如運動成績)來幫助更準確地分類。
為此我找了一張圖片說明一下,更容易讓你理解。H3則是最佳分界線。
圖片
讓我們直接來看一下代碼。盡管實現了如此復雜的功能,代碼的結構卻相對簡單明了。
C = 10
# 創(chuàng)建不同的分類器
classifiers = {
'Linear SVC': SVC(kernel='linear', C=C, probability=True,random_state=0)
}
n_classifiers = len(classifiers)
for index, (name, classifier) in enumerate(classifiers.items()):
classifier.fit(X_train, np.ravel(y_train))
y_pred = classifier.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy (train) for %s: %0.1f%% " % (name, accuracy * 100))
print(classification_report(y_test,y_pred))
運行結果如下,從表面上看,性能表現相當不錯,準確率至少接近80%。
Accuracy (train) for Linear SVC: 78.7%
precision recall f1-score support
chinese 0.69 0.80 0.74 242
indian 0.89 0.84 0.87 239
japanese 0.73 0.71 0.72 223
korean 0.90 0.75 0.82 250
thai 0.76 0.83 0.79 245
accuracy 0.79 1199
macro avg 0.79 0.79 0.79 1199
weighted avg 0.80 0.79 0.79 1199
K-近鄰分類器
K-近鄰分類器(K-Nearest Neighbors, KNN)是一種簡單且直觀的監(jiān)督學習算法,主要用于分類和回歸任務。它的基本思想是通過計算數據點之間的距離,將待分類的數據點歸類到其最近的 K 個鄰居的類別中。
舉個例子
在社交網絡中,我們常常能看到某些用戶與特定興趣群體的聯系。比如,假設我們想要判斷一個新用戶的興趣所在,我們可以觀察他周圍的朋友。
當我們分析這個新用戶的社交網絡時,可以查看與他最親近的 K 個朋友。這些朋友的共同興趣和活動可以為我們提供線索。如果這 K 個朋友大多數都喜歡攝影,那么我們可以推測,這位新用戶很可能也對攝影感興趣。
通過這種方式,我們利用社交網絡中朋友的影響,判斷一個用戶的興趣和愛好,從而更好地為他推薦內容和連接。
也就是說,根據近鄰樣本推測當前數據點屬于哪一類。
圖片
classifiers = {
'Linear SVC': SVC(kernel='linear', C=C, probability=True,random_state=0),
'KNN classifier': KNeighborsClassifier(C),
}
其他代碼無需修改,我們只需在分類對象中添加一個 KNN 分類器即可。接下來,我們將繼續(xù)觀察運行結果。值得注意的是,這一調整并未產生顯著的效果,KNN 分類器的引入似乎對模型的整體性能沒有帶來太大的提升。
Accuracy (train) for KNN classifier: 74.1%
precision recall f1-score support
chinese 0.70 0.76 0.73 242
indian 0.88 0.78 0.83 239
japanese 0.64 0.82 0.72 223
korean 0.94 0.54 0.68 250
thai 0.68 0.82 0.74 245
accuracy 0.74 1199
macro avg 0.77 0.74 0.74 1199
weighted avg 0.77 0.74 0.74 1199
Support Vector 分類器(SVC)
支持向量分類(SVC)和線性支持向量分類(Linear SVC)都是支持向量機(SVM)的一種實現,但它們在一些關鍵方面存在區(qū)別:
- 核函數
SVC:可以使用多種核函數(如線性核、多項式核、徑向基函數核等),適用于線性可分和非線性可分的數據集。
Linear SVC:只使用線性核,專注于處理線性可分的數據。它在優(yōu)化過程中不進行核變換。
- 適用性
SVC:適合處理更復雜的數據集,能夠捕捉到非線性決策邊界。
Linear SVC:適合高維特征空間的數據,尤其是特征維數大于樣本數時(例如文本分類任務)。
如果你知道數據是線性可分的或者特征維數非常高,使用 Linear SVC 可能更高效。如果數據存在非線性關系,選擇 SVC 并使用適當的核函數更合適。
classifiers = {
'Linear SVC': SVC(kernel='linear', C=C, probability=True,random_state=0),
'KNN classifier': KNeighborsClassifier(C),
'SVC': SVC(),
}
我們將繼續(xù)觀察SVC的運行結果,似乎表現得更為理想。
Accuracy (train) for SVC: 81.7%
precision recall f1-score support
chinese 0.73 0.82 0.77 242
indian 0.89 0.90 0.89 239
japanese 0.81 0.73 0.76 223
korean 0.90 0.77 0.83 250
thai 0.79 0.86 0.82 245
accuracy 0.82 1199
macro avg 0.82 0.82 0.82 1199
weighted avg 0.82 0.82 0.82 1199
集成分類器
盡管之前的測試結果已經相當令人滿意,但為了確保我們能夠全面評估模型的性能,我們決定沿著既定路線走到最后。因此,我們將嘗試一些集成分類器,特別是隨機森林和AdaBoost。
隨機森林
隨機森林就是用很多棵決策樹來做判斷,通過隨機選擇樣本和特征來確保多樣性,最后結合這些樹的結果來提高整體的準確性和穩(wěn)定性。這樣的方法讓模型更可靠,也更能適應復雜的數據。
想象一下,你想要決定今天的午餐吃什么,但你有很多朋友,每個朋友都有不同的口味。你可以做以下幾件事:
- 請教多個朋友:你詢問每個朋友的建議,而不是只聽一個人的意見。這樣,你能得到多種不同的選擇。
- 隨機選擇朋友:你不是每次都問所有朋友,而是隨機挑選幾個朋友來聽聽他們的意見。這樣可以避免受到個別朋友強烈偏好的影響。
- 記住他們的意見:你把每個朋友的建議記下來,比如有幾個朋友推薦了意大利面,有幾個推薦了壽司。
- 最終決定:最后,你根據朋友們的推薦,選擇那個被最多人推薦的餐點。
關鍵知識點
- 多樣性:隨機森林就是這樣一個想法,它通過“請教”很多個決策樹(這些樹就像你不同的朋友),每棵樹都是在不同的數據和特征上訓練出來的。
- 減少錯誤:通過多個“朋友”的建議,最終的選擇(預測)往往更準確,不容易受到單個決策的錯誤影響。
- 投票機制:所有的決策樹給出的預測結果匯總后,就像你的朋友們投票一樣,最終選擇那個“得票最多”的結果。
AdaBoost
AdaBoost 的核心思想是通過不斷學習和調整,結合多個弱分類器的力量,來提高整體的預測能力。每次迭代都關注之前的錯誤,從而使模型逐步改進。
想象一下,你在學校里參加一個辯論比賽,但你是個初學者,可能不太擅長辯論。你決定請教一些同學,他們的辯論水平不同,有的很厲害,有的剛剛開始。
- 請教不同同學:你找來了幾位同學來幫你,他們各自有不同的觀點和方法。每個同學都有可能在某個方面比你更擅長。
- 學習和調整:第一次練習時,可能有一些論點你說得不夠好,這些同學會給你反饋,告訴你哪些地方可以改進。你會記住這些錯誤,并在下次練習時更加注意。
- 重視反饋:對于那些你之前說錯的論點,給這些錯誤的部分“加重”。這意味著在接下來的練習中,你會特別關注這些問題,確保你能做到更好。
- 綜合意見:每次練習結束后,你會把所有同學的建議結合起來。雖然每個同學的能力不同,但通過不斷調整和綜合意見,最終你會變得更強。
關鍵知識點
- 逐步改進:AdaBoost 就是這樣一個過程。它通過多個“弱分類器”(就像你不同的同學),每個分類器可能都不是特別強,但通過不斷的調整和學習,它們一起能夠構成一個更強的“強分類器”。
- 重視錯誤:AdaBoost 特別關注那些之前預測錯誤的樣本,通過增加它們的權重,來讓后續(xù)的分類器更加關注這些難分類的樣本。
- 加權組合:最后,所有的分類器的結果會結合在一起,就像你綜合了所有同學的意見一樣,通過投票或加權來決定最終的預測結果。
區(qū)別與聯系
隨機森林:每棵樹都是相對獨立的,組合后形成的模型通常更穩(wěn)健,尤其在數據集比較復雜時,隨機森林的每棵樹之間的相關性較低,有助于減少方差,通常在特征數量很大或數據集復雜時表現良好,適用于分類和回歸任務。
AdaBoost:分類器是串行的,每個新分類器都依賴于前一個分類器的結果,建立在前一個模型的基礎上,AdaBoost 更容易受到噪聲數據的影響,因為它會對錯誤分類的樣本給予更高的關注。更適合處理一些簡單的、需要更高準確性的任務,尤其在面對數據噪聲較少的情況下。
隨機森林更注重多樣性和獨立性,而 AdaBoost 則通過聚焦于難點來提升整體性能。
接下來,對于我們實現的代碼來說就是兩行代碼:
# 創(chuàng)建不同的分類器
classifiers = {
'Linear SVC': SVC(kernel='linear', C=C, probability=True,random_state=0),
'KNN classifier': KNeighborsClassifier(C),
'SVC': SVC(),
'RFST': RandomForestClassifier(n_estimators=100),
'ADA': AdaBoostClassifier(n_estimators=100)
}
n_estimators在隨機森林中表示將生成 100 棵決策樹。每棵樹都是通過隨機選擇樣本和特征來訓練的。通過增加樹的數量,模型的表現通常會更穩(wěn)定,且更不容易過擬合。
n_estimators在AdaBoost 這表示將創(chuàng)建 100 個弱分類器(通常是簡單的決策樹)。每個分類器都會基于前一個分類器的表現進行訓練,關注那些之前分類錯誤的樣本。增加分類器的數量通常能提高模型的表現,但也可能增加過擬合的風險。
運行結果如下:
Accuracy (train) for RFST: 83.4%
precision recall f1-score support
chinese 0.78 0.80 0.79 242
indian 0.89 0.91 0.90 239
japanese 0.81 0.78 0.80 223
korean 0.89 0.81 0.85 250
thai 0.80 0.87 0.83 245
accuracy 0.83 1199
macro avg 0.83 0.83 0.83 1199
weighted avg 0.84 0.83 0.83 1199
Accuracy (train) for ADA: 69.5%
precision recall f1-score support
chinese 0.66 0.48 0.56 242
indian 0.88 0.79 0.84 239
japanese 0.66 0.64 0.65 223
korean 0.67 0.73 0.70 250
thai 0.64 0.82 0.72 245
accuracy 0.69 1199
macro avg 0.70 0.69 0.69 1199
weighted avg 0.70 0.69 0.69 1199
到此為止,我們已經對整個路線圖中能夠應用的所有分類器進行了全面的研究。雖然在代碼實現上,這可能僅僅涉及一行代碼或幾個參數的調整,但在背后,我們仍需對這些模型的基本邏輯和原理有一個大致的理解。
總結
在這個學習旅程中,我們不僅深入探討了各類分類器的原理和應用,還通過實踐加深了對模型構建過程的理解。通過使用不同的算法,如線性SVC、K-近鄰分類器、支持向量分類器及集成方法如隨機森林和AdaBoost,我們看到了數據處理和模型訓練的多樣性。在每一步的探索中,我們不僅關注了準確率,還思考了每種算法的適用場景及其優(yōu)勢。雖然使用機器學習庫簡化了實現的復雜性,但背后每個模型的邏輯與機制依然是值得我們深入了解的重要內容。
此外,我們學習到,模型的性能不僅依賴于選擇的算法,還與數據的特性、預處理的質量和參數的調優(yōu)緊密相關。面對不同的數據集,靈活地選擇適合的分類器和調整其參數,是提升模型效果的關鍵。通過使用Scikit-learn的速查表,我們能夠快速定位到合適的算法,為實際應用提供了有效的指導。
當然,最后我也想鼓勵大家去看看這個學習平臺,它非常適合新手,提供了豐富的資源和易于理解的教程。