機器學習--邏輯迴歸及乳腺癌預測
邏輯迴歸演算法是用來解決分類問題的演算法。
邏輯迴歸模型由sklearn.linear_model.LogisticRegression實現
例項:乳腺癌預測
a. 模型訓練
# 載入自帶乳腺癌資料集 from sklearn.datasets import load_breast_cancer cancer=load_breast_cancer() X=cancer.data y=cancer.target print('data.shape:{0};no. positive:{1};no. negative:{2}'.format(X.shape,y[y==1].shape[0],y[y==0].shape[0])) print(cancer.data[0])
data.shape:(569, 30);no. positive:357;no. negative:212 [1.799e+01 1.038e+01 1.228e+02 1.001e+03 1.184e-01 2.776e-01 3.001e-01 1.471e-01 2.419e-01 7.871e-02 1.095e+00 9.053e-01 8.589e+00 1.534e+02 6.399e-03 4.904e-02 5.373e-02 1.587e-02 3.003e-02 6.193e-03 2.538e+01 1.733e+01 1.846e+02 2.019e+03 1.622e-01 6.656e-01 7.119e-01 2.654e-01 4.601e-01 1.189e-01]
from sklearn.model_selection import train_test_split X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2) from sklearn.linear_model import LogisticRegression model = LogisticRegression() model.fit(X_train,y_train) train_score = model.score(X_train,y_train) test_score = model.score(X_test,y_test) print('train score:{train_score: .6f}; test score:{test_score:.6f}'.format(train_score=train_score,test_score=test_score)) # 檢視預測樣本中有幾個正確 y_pred = model.predict(X_test) # sum()只返回True的個數 print('matchs:{0}/{1}'.format(np.equal(y_pred,y_test).sum(),y_test.shape[0]))
train score: 0.967033; test score:0.921053
matchs:105/114
可以看到,在114個測試集樣本中,預測成功的有105個。
針對二分類問題,Logistic Regression模型會針對每個樣本輸出兩個概率(0和1的概率),哪個概率高就輸出哪個類別。
因此,可以針對測試資料集,找出模型預測自信度低於90%的樣本,即預測為陰性的自信度與預測為陽性的自信度同時高於10%的樣本。
model.predict_proba()計算概率
# 找出預測概率低於90%的樣本
y_pred_proba = model.predict_proba(X_test) #每個測試樣本的測試概率
print('sample of predict probability:{0}'.format(y_pred_proba[0])) #列印第一個樣本資料
# 找出第一列,即預測為陰性的概率大於0.1的樣本
result = y_pred_proba[y_pred_proba[:,0]>0.1]
# 在result裡找出第二列,即預測為陽性概率大於0.1的樣本
result_1 = result[result[:,1]>0.1]
print(result_1)
sample of predict probability:[0.01939711 0.98060289] [[0.88507494 0.11492506] [0.42675504 0.57324496] [0.1620304 0.8379696 ] [0.76926382 0.23073618] [0.17474437 0.82525563] [0.89571027 0.10428973] [0.61655269 0.38344731] [0.73476095 0.26523905] [0.10713253 0.89286747] [0.67842307 0.32157693] [0.89533222 0.10466778] [0.15608456 0.84391544] [0.86678907 0.13321093] [0.82521291 0.17478709] [0.19164219 0.80835781] [0.21962619 0.78037381] [0.44663372 0.55336628] [0.33092213 0.66907787] [0.63308328 0.36691672] [0.11658098 0.88341902] [0.80607166 0.19392834] [0.80001438 0.19998562] [0.86308949 0.13691051] [0.19086302 0.80913698] [0.12474998 0.87525002]]
可以看到有些樣本的預測概率較低:[0.61655269 0.38344731],預測為陰性的概率為61%。
b. 模型優化
LogisticRegression模型預測準確度達到92%,較好地預測結果。要優化模型,可以先從增加多項式特徵入手:
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
def polynomial_model(degree=1,**kwarg):
polynomial_features = PolynomialFeatures(degree=degree, include_bias=False)
logistic_regression = LogisticRegression(**kwarg)
pipeline = Pipeline([('polynomial_features',polynomial_features),('logistic_regression',logistic_regression)])
return pipeline
# 二階多項式
import time
# 使用L1範數為正則項,實現引數稀疏化
model = polynomial_model(degree=2,penalty='l1')
start = time.clock()
model.fit(X_train,y_train)
train_score = model.score(X_train,y_train)
test_score = model.score(X_test,y_test)
print('elaspe:{0:.6f}; train score:{1:.6f}; test score:{2:.6f}'.format(time.clock()-start,train_score,test_score))
elaspe:0.202307; train score:1.000000; test score:0.947368
找出二階多項式logisticRegression模型的特徵數量,以及非0特徵引數數量:
model.named_steps['']提取pipeline中的模型
model.coef_模型係數
logistic_regression = model.named_steps['logistic_regression']
print('model parameters shape:{0};count of non-zero element:{1}'.format(logistic_regression.coef_.shape,np.count_nonzero(logistic_regression.coef_)))
model parameters shape:(1, 495);count of non-zero element:86
原模型特徵有30個,變換成二階多項式後有495個特徵,其中非零特徵有86個,大部分特徵被拋棄。
c. 學習曲線
畫出學習曲線,對比使用L1範數、L2範數作為正則項的一階多項式模型、二階多項式模型,找出最佳的模型。
# L1範數的一階和二階多項式
cv = ShuffleSplit(n_splits=10,test_size=0.2,random_state=0)
title = 'Learning Curve(degree ={0},penalty={1})'
degrees=[1,2]
penalty='l1'
start=time.clock()
plt.figure(figsize=(12,4),dpi=144)
for i in range(len(degrees)):
plt.subplot(1,2,i+1)
plot_learning_curve(polynomial_model(degree=degrees[i],penalty=penalty),title.format(degrees[i],penalty),X,y,ylim=(0.8,1.01),cv=cv)
print('elaspe:{0:.6f}'.format(time.clock()-start))
# L2範數的一階和二階多項式
penalty='l2'
start=time.clock()
plt.figure(figsize=(12,4),dpi=144)
for i in range(len(degrees)):
plt.subplot(1,2,i+1)
plot_learning_curve(polynomial_model(degree=degrees[i],penalty=penalty),title.format(degrees[i],penalty),X,y,ylim=(0.8,1.01),cv=cv)
print('elaspe:{0:.6f}'.format(time.clock()-start))
可以看到,使用2階多項式,L1範數訓練集和測試集的準確度最高。
L1: elaspe:12.783659 L2:elaspe:3.204324
L1範數學習曲線用時較長,這是因為sklearn的learning_curve()函式在畫學習曲線時要對模型進行多次訓練,並計算交叉驗證樣本評分。同時,為了使曲線更平滑,針對每個點還會進行多次計算求平均值,這就是ShuffleSplit的作用。
本樣本數只有569個,是很小的資料集,如果資料集增加到100倍甚至更多,可以先抽取一小部分資料來畫學習曲線,待選擇好最有引數後再使用全部資料來訓練模型。
參考:
黃永昌《scikit-learn機器學習》