邏輯回歸:
邏輯回歸是最常用的分類算法之一。
from sklearn.linear_model import LogisticRegression logreg=LogisticRegression().fit(x_train,y_train) print("Training set score:{:.3f}".format(logreg.score(x_train,y_train))) print("Test set score:{:.3f}".format(logreg.score(x_test,y_test)))
Training set score:0.781
Test set score:0.771
正則化參數C=1(默認值)的模型在訓練集上准確度為78%,在測試集上准確度為77%。
logreg100=LogisticRegression(C=100).fit(x_train,y_train) print("Training set score:{:.3f}".format(logreg100.score(x_train,y_train))) print("Test set score:{:.3f}".format(logreg100.score(x_test,y_test)))
Training set score:0.785
Test set score:0.766
而將正則化參數C設置為100時,模型在訓練集上准確度稍有提高但測試集上准確度略降,說明較少正則化和更復雜的模型並不一定會比默認參數模型的預測效果更好。
因此,我們選擇默認值C=1。
讓我們用可視化的方式來看一下用三種不同正則化參數C所得模型的系數。
更強的正則化(C = 0.001)會使系數越來越接近於零。仔細地看圖,我們還能發現特征“DiabetesPedigreeFunction”(糖尿病遺傳函數)在 C=100, C=1 和C=0.001的情況下, 系數都為正。這表明無論是哪個模型,DiabetesPedigreeFunction(糖尿病遺傳函數)這個特征值都與樣本為糖尿病是正相關的。
diabetes_features=[x for i,x in enumerate(diabetes.columns) if i!=8] plt.figure(figsize=(8,6)) plt.plot(logreg.coef_.T,'o',label="C=1") plt.plot(logreg100.coef_.T,'^',label="C=100") plt.plot(logreg001.coef_.T,'v',label="C=0.001") plt.xticks(range(diabetes.shape[1]),diabetes_features,rotation=90) plt.hlines(0,0,diabetes.shape[1]) plt.ylim(-5,5) plt.xlabel("Feature") plt.ylabel("Coefficient magnitude") plt.legend()
決策樹:
from sklearn.tree import DecisionTreeClassifier tree=DecisionTreeClassifier(random_state=0) tree.fit(x_train,y_train) print("Accuracy on training set:{:.3f}".format(tree.score(x_train,y_train))) print("Accuracy on test set:{:.3f}".format(tree.score(x_test,y_test)))
Accuracy on training set:1.000
Accuracy on test set:0.714
訓練集的准確度可以高達100%,而測試集的准確度相對就差了很多。這表明決策樹是過度擬合的,不能對新數據產生好的效果。因此,我們需要對樹進行預剪枝。
我們設置max_depth=3,限制樹的深度以減少過擬合。這會使訓練集的准確度降低,但測試集准確度提高。
tree=DecisionTreeClassifier(max_depth=3,random_state=0) tree.fit(x_train,y_train) print("Accuracy on training set:{:.3f}".format(tree.score(x_train,y_train))) print("Accuracy on test set:{:.3f}".format(tree.score(x_test,y_test)))
Accuracy on training set:0.773
Accuracy on test set:0.740
決策樹中的特征重要度:
決策樹中的特征重要度是用來衡量每個特征對於預測結果的重要性的。對每個特征有一個從0到1的打分,0表示“一點也沒用”,1表示“完美預測”。各特征的重要度加和一定是為1的。
print("Feature importances:\n{}".format(tree.feature_importances_))
Feature importances: [ 0.04554275 0.6830362 0. 0. 0. 0.27142106 0. 0. ]
然后我們能可視化特征重要度:
def plot_feature_importances_diabetes(model): plt.figure(figsize=(8,6)) n_features=8 plt.barh(range(n_features),model.feature_importances_,align='center') plt.yticks(np.arange(n_features),diabetes_features) plt.xlabel("Feature importance") plt.ylabel("Feature") plt.ylim(-1,n_features) plot_feature_importances_diabetes(tree)
特征“血糖”是目前最重要的特征。
隨機森林:
讓我們在糖尿病數據集中應用一個由100棵樹組成的隨機森林:
from sklearn.ensemble import RandomForestClassifier rf=RandomForestClassifier(n_estimators=100,random_state=0) rf.fit(x_train,y_train) print("Accuracy on training set:{:.3f}".format(rf.score(x_train,y_train))) print("Accuracy on test set:{:.3f}".format(rf.score(x_test,y_test)))
Accuracy on training set:1.000
Accuracy on test set:0.786
沒有更改任何參數的隨機森林有78.6%的准確度,比邏輯回歸和單一決策樹的預測效果更好。然而,我們還是可以調整max_features設置,看看效果是否能夠提高。
rf1=RandomForestClassifier(max_depth=3,n_estimators=100,random_state=0) rf1.fit(x_train,y_train) print("Accuracy on training set:{:.3f}".format(rf1.score(x_train,y_train))) print("Accuracy on test set:{:.3f}".format(rf1.score(x_test,y_test)))
Accuracy on training set:0.800
Accuracy on test set:0.755
結果並沒有提高,這表明默認參數的隨機森林在這里效果很好。
隨機森林的特征重要度:
plot_feature_importances_diabetes(rf1)
與單一決策樹相似,隨機森林的結果仍然顯示特征“血糖”的重要度最高,但是它也同樣顯示“BMI(身體質量指數)”在整體中是第二重要的信息特征。隨機森林的隨機性促使算法考慮了更多可能的解釋,這就導致隨機森林捕獲的數據比單一樹要大得多。