公眾號關注 「Python遇見機器學習」
設為「星標」,第一時間知曉最新乾貨~
本次分享是基於scikit-learn工具包的基本分類方法,包括常見的Logisitic Regression、支持向量機、決策樹、隨機森林以及K近鄰方法KNN。本文在基於讀者已經基本了解這些基本算法的原理以及推導的基礎上,使用sklearn工具包進行算法實踐,如果大家沒有掌握基本算法原理,文中也會給出一些優秀的連結方便大家學習。如果大家對基本分類算法的基本原理有需求,可以在評論區寫下自己的需求,我們會根據大家的意見推出相應的分享。機器學習算法主要步驟有:
調整算法
本次分享主要把目光聚集在"選擇分類器並優化算法",我們將用學術界和工業界常用的機器學習庫sklearn,對算法進行實踐。本文內容:
1. 數據準備我們使用鳶尾花數據集,進行分析考核可視化
# 引入數據from sklearn import datasetsimport numpy as np
iris = datasets.load_iris()X = iris.data[:,[2,3]]y = iris.targetprint("Class labels:",np.unique(y)) #列印分類類別的種類切分訓練數據和測試數據
# 切分訓練數據和測試數據from sklearn.model_selection import train_test_split## 30%測試數據,70%訓練數據,stratify=y表示訓練數據和測試數據具有相同的類別比例X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3,random_state=1,stratify=y)數據標準化
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()## 估算訓練數據中的mu和sigmasc.fit(X_train)## 使用訓練數據中的mu和sigma對數據進行標準化X_train_std = sc.transform(X_train)X_test_std = sc.transform(X_test)定製可視化函數:畫出決策邊界圖(只有在2個特徵才能畫出來)
## 畫出決策邊界圖(只有在2個特徵才能畫出來)import matplotlib.pyplot as plt%matplotlib inlinefrom matplotlib.colors import ListedColormap
def plot_decision_region(X,y,classifier,resolution=0.02): markers = ('s','x','o','^','v') colors = ('red','blue','lightgreen','gray','cyan') cmap = ListedColormap(colors[:len(np.unique(y))])
# plot the decision surface x1_min,x1_max = X[:,0].min()-1,X[:,0].max()+1 x2_min,x2_max = X[:,1].min()-1,X[:,1].max()+1 xx1,xx2 = np.meshgrid(np.arange(x1_min,x1_max,resolution), np.arange(x2_min,x2_max,resolution)) Z = classifier.predict(np.array([xx1.ravel(),xx2.ravel()]).T) Z = Z.reshape(xx1.shape) plt.contourf(xx1,xx2,Z,alpha=0.3,cmap=cmap) plt.xlim(xx1.min(),xx1.max()) plt.ylim(xx2.min(),xx2.max())
# plot class samples for idx,cl in enumerate(np.unique(y)): plt.scatter(x=X[y==cl,0], y = X[y==cl,1], alpha=0.8, c=colors[idx], marker = markers[idx], label=cl, edgecolors='black')2. 基於邏輯回歸的分類概率建模2.1 原理介紹
可參考閱讀:一文詳盡系列之邏輯回歸
2.2 參考文檔詳細解釋class sklearn.linear_model.LogisticRegression(penalty='l2', *, dual=False, tol=0.0001, C=1.0, fit_intercept=True, intercept_scaling=1, class_weight=None, random_state=None, solver='lbfgs', max_iter=100, multi_class='auto', verbose=0, warm_start=False, n_jobs=None, l1_ratio=None)
2.2.1可選參數penalty:正則化方式,可選擇『l1』, 『l2』, 『elasticnet』, 『none』,默認'l2'
dual:是否選擇對偶,當n_samples> n_features時,首選dual = False
tol:算法停止的誤差條件,默認是0.0001
C:正則強度的倒數;必須為正浮點數,較小的值指定更強的正則化,默認為1.0
fit_intercept:是否應將常量(也稱為偏差或截距)添加到決策函數。默認是True。
intercept_scaling:不常用
class_weight:對類別進行加權,可以使用字典形式加權,輸入『balanced』代表權重為類別頻率,默認是"None"。
random_state:選擇隨機種子,打亂樣本時候指定。
solver:指定優化器類型,可選『newton-cg』, 『lbfgs』, 『liblinear』, 『sag』, 『saga』
具體的優化方法參考:機器學習中的優化算法!
max_iter:算法收斂的最大迭代次數,默認100。
multi_class:不常用。
verbose:對於liblinear和lbfgs,求解器將verbose設置為任何正數以表示詳細程度。
warm_start:不常用。
n_jobs:使用內核數。
l1_ratio:彈性網絡參數,其中0 <= l1_ratio <=1。僅當penalty=「 elasticnet」時使用。
2.2.2 返回標籤
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression(C=100.0,random_state=1)lr.fit(X_train_std,y_train)print("Class:",lr.classes_)print("Coef:",lr.coef_)print("intercept",lr.intercept_)print("n_iter",lr.n_iter_)plot_decision_region(X_train_std,y_train,classifier=lr,resolution=0.02)plt.xlabel('petal length [standardized]')plt.ylabel('petal width [standardized]')plt.legend(loc='upper left')plt.show()預測:# 預測## 預測前三樣本在各個類別的概率print("前三樣本在各個類別的預測概率為:\n",lr.predict_proba(X_test_std[:3,:]))print("\n============================")## 獲得前三個樣本的分類標籤print("\n前三樣本在各個類別的預測類別為:\n",lr.predict(X_test_std[:3,:]))print("\n============================")
我們可以看到邏輯回歸的決策邊界是一個線性邊界,這也就是為什麼邏輯回歸作為線性分類模型的原因了。大家不要小瞧線性模型,線性模型在現實生產中還發揮的重要作用,在金融、經濟中尤為明顯,因為線性模型的模型複雜度較小,它的可解釋性很好,能夠給決策者決策提供更加強大的依據,而不是像類似於深度學習那些複雜的網絡模型一樣是個黑箱子。
3. 基於支持向量機的分類模型
3.1 原理介紹
可參考閱讀:一文詳盡之支持向量機算法!
3.2 參考文檔詳細解釋
class sklearn.svm.SVC(*, C=1.0, kernel='rbf', degree=3, gamma='scale', coef0=0.0, shrinking=True, probability=False, tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, decision_function_shape='ovr', break_ties=False, random_state=None)
C:正則化參數。正則化的強度與C成反比。必須嚴格為正。懲罰是平方的l2懲罰。(默認1.0)kernel:核函數類型,可選『linear』, 『poly』, 『rbf』, 『sigmoid』, 『precomputed』;degree:當選擇核函數為poly多項式時,表示多項式的階數gamma:可選『scale』和『auto』,表示為「 rbf」,「 poly」和「 Sigmoid」的內核係數。,默認是'scale',gamma取值為1 / (n_features * X.var());當選『auto』參數時gamma取值為1 / n_features。
coef0:當核函數選為「 poly」和「 sigmoid」有意義。
shrinking:是否使用縮小的啟發式方法,默認是True。
probability:是否啟用概率估計,默認是False。必須在調用fit之前啟用此功能,因為該方法內部使用5倍交叉驗證,因而會減慢該方法的速度,並且predict_proba可能與dict不一致。tol:算法停止的條件,默認為0.001。cache_size:指定內核緩存的大小(以MB為單位),默認是200。class_weight:每個類樣本的權重,可以用字典形式給出,選擇'balanced',權重為n_samples / (n_classes * np.bincount(y));默認是None,表示每個樣本權重一致。verbose:是否使用詳細輸出,默認是False。max_iter:算法迭代的最大步數,默認-1表示無限制decision_function_shape:多分類的形式,1 vs 多(『ovo』)還是1 vs 1(』ovr』),默認』ovr』.break_ties:如果為true,decision_function_shape ='ovr',並且類別數> 2,則預測將根據Decision_function的置信度值打破平局;否則,將返回綁定類中的第一類。請注意,與簡單預測相比,打破平局的計算成本較高。random_state:隨機種子,隨機打亂樣本。
3.2.2 可選標籤
fit_status_:如果正確擬合,則為0,否則為1(將發出警告)線性支持向量機:
## 線性支持向量機from sklearn.svm import SVCsvm = SVC(kernel='linear',C=1.0,random_state=1)svm.fit(X_train_std,y_train)plot_decision_region(X_train_std,y_train,classifier=svm,resolution=0.02)plt.xlabel('petal length [standardized]')plt.ylabel('petal width [standardized]')plt.legend(loc='upper left')plt.show()使用核函數對非線性分類問題建模(gamma=0.20)
## 使用核函數對非線性分類問題建模(gamma=0.20)svm = SVC(kernel='rbf',random_state=1,gamma=0.20,C=1.0) ##較小的gamma有較松的決策邊界svm.fit(X_train_std,y_train)plot_decision_region(X_train_std,y_train,classifier=svm,resolution=0.02)plt.xlabel('petal length [standardized]')plt.ylabel('petal width [standardized]')plt.legend(loc='upper left')plt.show()使用核函數對非線性分類問題建模(gamma=100)
## 使用核函數對非線性分類問題建模(gamma=100)svm = SVC(kernel='rbf',random_state=1,gamma=100.0,C=1.0,verbose=1) svm.fit(X_train_std,y_train)plot_decision_region(X_train_std,y_train,classifier=svm,resolution=0.02)plt.xlabel('petal length [standardized]')plt.ylabel('petal width [standardized]')plt.legend(loc='upper left')plt.show()從不同的gamma取值的圖像來看:對於高斯核函數,增大gamma值,將增大訓練樣本的影響範圍,導致決策邊界緊縮和波動;較小的gamma值得到的決策邊界相對寬鬆。雖然較大的gamma值在訓練樣本中有很小的訓練誤差,但是很可能泛化能力較差,容易出現過擬合。
4. 構建決策樹分類器
4.1 原理介紹
可參考閱讀:最常用的決策樹算法!Random Forest、Adaboost、GBDT 算法
4.2 參考文檔詳細解釋
class sklearn.tree.DecisionTreeClassifier(*, criterion='gini', splitter='best', max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, class_weight=None, presort='deprecated', ccp_alpha=0.0)
criterion:分裂節點所用的標準,可選「gini」, 「entropy」,默認「gini」。splitter:用於在每個節點上選擇拆分的策略。可選「best」, 「random」,默認「best」。max_depth:樹的最大深度。如果為None,則將節點展開,直到所有葉子都是純淨的(只有一個類),或者直到所有葉子都包含少於min_samples_split個樣本。默認是None。min_samples_split:拆分內部節點所需的最少樣本數:如果為int,則將min_samples_split視為最小值。如果為float,則min_samples_split是一個分數,而ceil(min_samples_split * n_samples)是每個拆分的最小樣本數。默認是2。min_samples_leaf:在葉節點處需要的最小樣本數。僅在任何深度的分割點在左分支和右分支中的每個分支上至少留下min_samples_leaf個訓練樣本時,才考慮。這可能具有平滑模型的效果,尤其是在回歸中。如果為int,則將min_samples_leaf視為最小值。如果為float,則min_samples_leaf是分數,而ceil(min_samples_leaf * n_samples)是每個節點的最小樣本數。默認是1。min_weight_fraction_leaf:在所有葉節點處(所有輸入樣本)的權重總和中的最小加權分數。如果未提供sample_weight,則樣本的權重相等。max_features:尋找最佳分割時要考慮的特徵數量:如果為int,則在每個拆分中考慮max_features個特徵。如果為float,則max_features是一個分數,並在每次拆分時考慮int(max_features * n_features)個特徵。如果為「auto」,則max_features = sqrt(n_features)。如果為「 sqrt」,則max_features = sqrt(n_features)。如果為「 log2」,則max_features = log2(n_features)。如果為None,則max_features = n_features。注意:在找到至少一個有效的節點樣本分區之前,分割的搜索不會停止,即使它需要有效檢查多個max_features功能也是如此。random_state:隨機種子,負責控制分裂特徵的隨機性,為整數。默認是None。max_leaf_nodes:最大葉子節點數,整數,默認為Nonemin_impurity_decrease:如果分裂指標的減少量大於該值,則進行分裂。min_impurity_split:決策樹生長的最小純淨度。默認是0。自版本0.19起不推薦使用:不推薦使用min_impurity_split,而建議使用0.19中的min_impurity_decrease。min_impurity_split的默認值在0.23中已從1e-7更改為0,並將在0.25中刪除。class_weight:每個類的權重,可以用字典的形式傳入{class_label: weight}。如果選擇了「balanced」,則輸入的權重為n_samples / (n_classes * np.bincount(y))。presort:此參數已棄用,並將在v0.24中刪除。ccp_alpha:將選擇成本複雜度最大且小於ccp_alpha的子樹。默認情況下,不執行修剪。4.2.2 可選標籤
classes_:類標籤(單輸出問題)或類標籤數組的列表(多輸出問題)。feature_importances_:特徵重要度。max_features_:max_features的推斷值。n_classes_:類數(用於單輸出問題),或包含每個輸出的類數的列表(用於多輸出問題)。決策樹分類器:
from sklearn.tree import DecisionTreeClassifiertree = DecisionTreeClassifier(criterion='gini',max_depth=4,random_state=1)tree.fit(X_train_std,y_train)plot_decision_region(X_train_std,y_train,classifier=tree,resolution=0.02)plt.xlabel('petal length [standardized]')plt.ylabel('petal width [standardized]')plt.legend(loc='upper left')plt.show()決策樹可視化:
從http://www.graphviz.orz免費下載程序
pip3 install pydotplus
pip3 install graphviz
pip3 install pyparsing
from pydotplus import graph_from_dot_datafrom sklearn.tree import export_graphvizdot_data = export_graphviz(tree,filled=True,class_names=['Setosa','Versicolor','Virginica'], feature_names=['petal_length','petal_width'],out_file=None)graph = graph_from_dot_data(dot_data)graph.write_png('/home/leo/文檔/大四下學期/zhihu/sklearn的基本分類模型詳解/tree.png')從樹的邊界來看,決策樹在鳶尾花分類問題上表現不錯,但是sklearn不提供手工決策樹修剪功能。
5. 通過隨機森林組合多棵決策樹
5.1 原理介紹
可參考閱讀:機器學習必知必會10大算法
5.2 參考文檔詳細解釋
class sklearn.ensemble.RandomForestClassifier(n_estimators=100, *, criterion='gini', max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features='auto', max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, bootstrap=True, oob_score=False, n_jobs=None, random_state=None, verbose=0, warm_start=False, class_weight=None, ccp_alpha=0.0, max_samples=None)
n_estimators:森林中決策樹的數量。默認100criterion:分裂節點所用的標準,可選「gini」, 「entropy」,默認「gini」。max_depth:樹的最大深度。如果為None,則將節點展開,直到所有葉子都是純淨的(只有一個類),或者直到所有葉子都包含少於min_samples_split個樣本。默認是None。min_samples_split:拆分內部節點所需的最少樣本數:如果為int,則將min_samples_split視為最小值。如果為float,則min_samples_split是一個分數,而ceil(min_samples_split * n_samples)是每個拆分的最小樣本數。默認是2。min_samples_leaf:在葉節點處需要的最小樣本數。僅在任何深度的分割點在左分支和右分支中的每個分支上至少留下min_samples_leaf個訓練樣本時,才考慮。這可能具有平滑模型的效果,尤其是在回歸中。如果為int,則將min_samples_leaf視為最小值。如果為float,則min_samples_leaf是分數,而ceil(min_samples_leaf * n_samples)是每個節點的最小樣本數。默認是1。min_weight_fraction_leaf:在所有葉節點處(所有輸入樣本)的權重總和中的最小加權分數。如果未提供sample_weight,則樣本的權重相等。max_features:尋找最佳分割時要考慮的特徵數量:如果為int,則在每個拆分中考慮max_features個特徵。如果為float,則max_features是一個分數,並在每次拆分時考慮int(max_features * n_features)個特徵。如果為「auto」,則max_features = sqrt(n_features)。如果為「 sqrt」,則max_features = sqrt(n_features)。如果為「 log2」,則max_features = log2(n_features)。如果為None,則max_features = n_features。注意:在找到至少一個有效的節點樣本分區之前,分割的搜索不會停止,即使它需要有效檢查多個max_features功能也是如此。max_leaf_nodes:最大葉子節點數,整數,默認為Nonemin_impurity_decrease:如果分裂指標的減少量大於該值,則進行分裂。min_impurity_split:決策樹生長的最小純淨度。默認是0。自版本0.19起不推薦使用:不推薦使用min_impurity_split,而建議使用0.19中的min_impurity_decrease。min_impurity_split的默認值在0.23中已從1e-7更改為0,並將在0.25中刪除。bootstrap:是否進行bootstrap操作,bool。默認True。oob_score:是否使用袋外樣本來估計泛化精度。默認False。random_state:控制bootstrap的隨機性以及選擇樣本的隨機性。verbose:在擬合和預測時控制詳細程度。默認是0。class_weight:每個類的權重,可以用字典的形式傳入{class_label: weight}。如果選擇了「balanced」,則輸入的權重為n_samples / (n_classes * np.bincount(y))。ccp_alpha:將選擇成本複雜度最大且小於ccp_alpha的子樹。默認情況下,不執行修剪。
max_samples:如果bootstrap為True,則從X抽取以訓練每個基本分類器的樣本數。如果為None(默認),則抽取X.shape [0]樣本。如果為int,則抽取max_samples樣本。如果為float,則抽取max_samples * X.shape [0]個樣本。因此,max_samples應該在(0,1)中。是0.22版中的新功能。5.2.2 可選標籤
classes_:類標籤(單輸出問題)或類標籤數組的列表(多輸出問題)。n_classes_:類數(用於單輸出問題),或包含每個輸出的類數的列表(用於多輸出問題)。oob_score_:使用袋外估計獲得的訓練數據集的分數。僅當oob_score為True時,此屬性才存在。oob_decision_function_:使用訓練集上的實際估計值計算的決策函數。如果n_estimators小,則有可能在引導過程中從未遺漏任何數據點。在這種情況下,oob_decision_function_可能包含NaN。僅當oob_score為True時,此屬性才存在。使用隨機森林分類器:
from sklearn.ensemble import RandomForestClassifier
forest = RandomForestClassifier(criterion='gini',n_estimators=25,random_state=1,n_jobs=2,verbose=1)forest.fit(X_train_std,y_train)plot_decision_region(X_train_std,y_train,classifier=forest,resolution=0.02)plt.xlabel('petal length [standardized]')plt.ylabel('petal width [standardized]')plt.legend(loc='upper left')plt.show()
6. K近鄰(KNN)6.1 原理介紹可參考閱讀:機器學習必知必會10大算法
6.2 參考文檔詳細解釋
class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, _, weights='uniform', algorithm='auto', leaf_size=30, p=2, metric='minkowski', metric_params=None, n_jobs=None, *_kwargs)
weights:預測中使用的權重函數。可能的取值:『uniform』:統一權重,即每個鄰域中的所有點均被加權。『distance』:權重點與其距離的倒數,在這種情況下,查詢點的近鄰比遠處的近鄰具有更大的影響力。[callable]:用戶定義的函數,該函數接受距離數組,並返回包含權重的相同形狀的數組。algorithm:用於計算最近鄰居的算法:「 ball_tree」將使用BallTree,「 kd_tree」將使用KDTree,「brute」將使用暴力搜索。「auto」將嘗試根據傳遞給fit方法的值來決定最合適的算法。注意:在稀疏輸入上進行擬合將使用蠻力覆蓋此參數的設置。leaf_size:葉大小傳遞給BallTree或KDTree。這會影響構造和查詢的速度,以及存儲樹所需的內存。最佳值取決於問題的性質。默認30。p:Minkowski距離的指標的功率參數。當p = 1時,等效於使用manhattan_distance(l1)和p=2時使用euclidean_distance(l2)。對於任意p,使用minkowski_distance(l_p)。默認是2。metric:樹使用的距離度量。默認度量標準為minkowski,p = 2等於標準歐幾裡德度量標準。metric_params:度量函數的其他關鍵字參數。6.2.2 可選標籤
effective_metric_:使用的距離度量。它將與度量參數相同或與其相同,例如如果metric參數設置為「 minkowski」,而p參數設置為2,則為「 euclidean」。effective_metric_params_:度量功能的其他關鍵字參數。對於大多數指標而言,它與metric_params參數相同,但是,如果將valid_metric_屬性設置為「 minkowski」,則也可能包含p參數值。outputs_2d_:在擬合的時候,當y的形狀為(n_samples,)或(n_samples,1)時為False,否則為True。使用KNN分類器:
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=2,p=2,metric="minkowski")knn.fit(X_train_std,y_train)plot_decision_region(X_train_std,y_train,classifier=knn,resolution=0.02)plt.xlabel('petal length [standardized]')plt.ylabel('petal width [standardized]')plt.legend(loc='upper left')plt.show()值得注意的是:KNN容易過擬合,因為在高維空間上,隨著維數越來越大,特徵空間越來越稀疏,大家可以想像在一個球體裡面,大部分的信息集中在球面,那KNN需要找最近的點就會十分困難,那麼也就無法合適進行估計。
重磅!
Python遇見機器學習交流群已成立!
邱錫鵬深度學習與神經網絡,pytorch官方中文教程,利用Python進行數據分析,機器學習學習筆記,pandas官方文檔中文版,effective java(中文版)等20項福利資源
獲取方式:進入群後點開群公告即可領取下載連結
注意:請大家添加時修改備註為
[學校/公司 + 姓名 + 方向]
例如 —— 哈工大+張三+對話系統。
號主,微商等廣告請自覺繞道。謝謝!
推薦閱讀• 開源教程 「nlp-tutorial」!用百行代碼搞定各類NLP模型
• 機器學習、數據科學、人工智慧、深度學習和統計學之間的區別!
• 做好數據可視化的技巧和原則!
• 深度學習環境配置指南!(Windows、Mac、Ubuntu全講解)
• 國家發錢了!研究生補貼一覽表!
• 最牛損失函數解讀:A General and Adaptive Robust Loss Function
• CV中的Attention機制:簡單而有效的CBAM模塊
• 通俗講解從Transformer到BERT模型!
• 算法工程師當前選哪個方向好?1,計算機視覺;2,自然語言處理;3,風控;4,推薦系統?
• 寫出漂亮 Python 代碼的 20條準則
• 深度學習需要掌握的 13 個概率分布(附代碼)
• 最新Transformer模型大盤點,NLP學習必備,Google AI研究員出品丨資源