基礎(chǔ)思想:
回歸模型中,y是一個(gè)定型變量械巡,比如y=0或1刹淌,logistic方法主要應(yīng)用于研究某些事件發(fā)生的概率。
優(yōu)點(diǎn):
計(jì)算代價(jià)不高讥耗,易于理解和實(shí)現(xiàn)有勾;
速度快,適合二分類問(wèn)題古程;
簡(jiǎn)單易于理解蔼卡,直接看到各個(gè)特征的權(quán)重;
能容易地更新模型吸收新的數(shù)據(jù)籍琳。
缺點(diǎn):
容易產(chǎn)生欠擬合菲宴;
分類精度可能不高;
對(duì)數(shù)據(jù)和場(chǎng)景的適應(yīng)能力有局限趋急,不如決策樹算法適應(yīng)性那么強(qiáng)
應(yīng)用領(lǐng)域:
用于二分類領(lǐng)域喝峦,可以得出概率值,適用于根據(jù)分類概率排名的領(lǐng)域呜达,如搜索排名等谣蠢;
Logistic 回歸的擴(kuò)展 softmax 可以應(yīng)用于多分類領(lǐng)域,如手寫字識(shí)別等查近;
信用評(píng)估眉踱;
測(cè)量市場(chǎng)營(yíng)銷的成功度;
預(yù)測(cè)某個(gè)產(chǎn)品的收益霜威;
特定的某天是否會(huì)發(fā)生地震谈喳。
邏輯回歸 vs 線性回歸
首先,邏輯回歸比線性回歸要好戈泼。
兩者都屬于廣義線性模型婿禽。
線性回歸優(yōu)化目標(biāo)函數(shù)用的最小二乘法,而邏輯回歸用的是最大似然估計(jì)大猛。
邏輯回歸只是在線性回歸的基礎(chǔ)上扭倾,將加權(quán)和通過(guò)sigmoid函數(shù),映射到0-1范圍內(nèi)空間挽绩。
線性回歸在整個(gè)實(shí)數(shù)范圍內(nèi)進(jìn)行預(yù)測(cè)膛壹,敏感度一致,而分類范圍,需要在[0,1]模聋。而邏輯回歸就是一種減小預(yù)測(cè)范圍肩民,將預(yù)測(cè)值限定為[0,1]間的一種回歸模型。邏輯曲線在z=0時(shí)撬槽,十分敏感此改,在z>>0或z<<0處趾撵,都不敏感侄柔,將預(yù)測(cè)值限定為(0,1)。邏輯回歸的魯棒性比線性回歸要好占调。
通過(guò)手機(jī)設(shè)備搜集的用戶運(yùn)動(dòng)數(shù)據(jù)暂题,有六個(gè)與運(yùn)動(dòng)有關(guān)的自變量,其中3個(gè)與加速度有關(guān)究珊,3個(gè)與運(yùn)動(dòng)方向有關(guān)
通過(guò)sklearn的子模塊linear_model中的Logistic回歸模型
# -----------------------第一步 建模 ----------------------- #
#導(dǎo)入第三方模塊
import numpy as np
import pandas as pd
from sklearn import linear_model
from sklearn import model_selection
#讀取數(shù)據(jù)
sports=pd.read_csv("F:\Run or Walk.csv")
sports.head()
#處理數(shù)據(jù)薪者,構(gòu)建自變量矩陣
X=sports.ix[:,sports.columns[4:]]
X.head()
#提取y變量
y=sports.activity
y.head()
#拆分?jǐn)?shù)據(jù)為訓(xùn)練集(75%)和測(cè)試集(25%)
X_train,X_test,y_train,y_test=model_selection.train_test_split(X,y,test_size=0.25,random_state=1234)
#利用訓(xùn)練集建模
sklearn_logistic=linear_model.LogisticRegression()
sklearn_logistic.fit(X_train,y_train)
#返回模型的各個(gè)參數(shù)
print(sklearn_logistic.intercept_,sklearn_logistic.coef_)
# -----------------------第二步 預(yù)測(cè)構(gòu)建混淆矩陣 ----------------------- #
# 模型預(yù)測(cè)
sklearn_predict = sklearn_logistic.predict(X_test)
sklearn_predict
# 預(yù)測(cè)結(jié)果統(tǒng)計(jì)
pd.Series(sklearn_predict).head()
pd.Series(sklearn_predict).value_counts()
其中判斷步行狀態(tài)的樣本有12121個(gè),跑步狀態(tài)的樣本有10026個(gè)
# 導(dǎo)入第三方模塊
from sklearn import metrics
# 混淆矩陣
cm = metrics.confusion_matrix(y_test, sklearn_predict, labels = [0,1])
cm
行表示實(shí)際的運(yùn)動(dòng)狀態(tài)剿涮,列表示模型預(yù)測(cè)的運(yùn)動(dòng)狀態(tài)
# -----------------------第三步 繪制ROC曲線 ----------------------- #
Accuracy = metrics.scorer.accuracy_score(y_test, sklearn_predict)
Sensitivity = metrics.scorer.recall_score(y_test, sklearn_predict)
Specificity = metrics.scorer.recall_score(y_test, sklearn_predict, pos_label=0)
print('模型準(zhǔn)確率為%.2f%%:' %(Accuracy*100))
print('正例覆蓋率為%.2f%%' %(Sensitivity*100))
print('負(fù)例覆蓋率為%.2f%%' %(Specificity*100))
整體的預(yù)測(cè)準(zhǔn)確率比較高
還可以對(duì)混淆矩陣做可視化展現(xiàn)
# 混淆矩陣的可視化
# 導(dǎo)入第三方模塊
import seaborn as sns
import matplotlib.pyplot as plt
# 繪制熱力圖
sns.heatmap(cm, annot = True, fmt = '.2e',cmap = 'GnBu')
# 圖形顯示
plt.show()
顏色越深的區(qū)塊代表樣本量越多言津,從圖中看出,主對(duì)角線上的區(qū)塊顏色要比其他地方深很多取试,說(shuō)明正確預(yù)測(cè)正例和負(fù)例的樣本數(shù)目都很大
# y得分為模型預(yù)測(cè)正例的概率
y_score = sklearn_logistic.predict_proba(X_test)[:,1]
# 計(jì)算不同閾值下悬槽,fpr和tpr的組合值,其中fpr表示1-Specificity瞬浓,tpr表示Sensitivity
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
# 計(jì)算AUC的值
roc_auc = metrics.auc(fpr,tpr)
# 繪制面積圖
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
# 添加邊際線
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加對(duì)角線
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
# 添加x軸與y軸標(biāo)簽
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
# 顯示圖形
plt.show()
曲線下面積高達(dá)0.93初婆,遠(yuǎn)遠(yuǎn)超過(guò)0.8,認(rèn)定回歸模型是合理的
# -----------------------第四步 繪制K-S曲線 ----------------------- #
# 自定義繪制ks曲線的函數(shù)
def plot_ks(y_test, y_score, positive_flag):
# 對(duì)y_test,y_score重新設(shè)置索引
y_test.index = np.arange(len(y_test))
#y_score.index = np.arange(len(y_score))
# 構(gòu)建目標(biāo)數(shù)據(jù)集
target_data = pd.DataFrame({'y_test':y_test, 'y_score':y_score})
# 按y_score降序排列
target_data.sort_values(by = 'y_score', ascending = False, inplace = True)
# 自定義分位點(diǎn)
cuts = np.arange(0.1,1,0.1)
# 計(jì)算各分位點(diǎn)對(duì)應(yīng)的Score值
index = len(target_data.y_score)*cuts
scores = target_data.y_score.iloc[index.astype('int')]
# 根據(jù)不同的Score值猿棉,計(jì)算Sensitivity和Specificity
Sensitivity = []
Specificity = []
for score in scores:
# 正例覆蓋樣本數(shù)量與實(shí)際正例樣本量
positive_recall = target_data.loc[(target_data.y_test == positive_flag) & (target_data.y_score>score),:].shape[0]
positive = sum(target_data.y_test == positive_flag)
# 負(fù)例覆蓋樣本數(shù)量與實(shí)際負(fù)例樣本量
negative_recall = target_data.loc[(target_data.y_test != positive_flag) & (target_data.y_score<=score),:].shape[0]
negative = sum(target_data.y_test != positive_flag)
Sensitivity.append(positive_recall/positive)
Specificity.append(negative_recall/negative)
# 構(gòu)建繪圖數(shù)據(jù)
plot_data = pd.DataFrame({'cuts':cuts,'y1':1-np.array(Specificity),'y2':np.array(Sensitivity),
'ks':np.array(Sensitivity)-(1-np.array(Specificity))})
# 尋找Sensitivity和1-Specificity之差的最大值索引
max_ks_index = np.argmax(plot_data.ks)
plt.plot([0]+cuts.tolist()+[1], [0]+plot_data.y1.tolist()+[1], label = '1-Specificity')
plt.plot([0]+cuts.tolist()+[1], [0]+plot_data.y2.tolist()+[1], label = 'Sensitivity')
# 添加參考線
plt.vlines(plot_data.cuts[max_ks_index], ymin = plot_data.y1[max_ks_index],
ymax = plot_data.y2[max_ks_index], linestyles = '--')
# 添加文本信息
plt.text(x = plot_data.cuts[max_ks_index]+0.01,
y = plot_data.y1[max_ks_index]+plot_data.ks[max_ks_index]/2,
s = 'KS= %.2f' %plot_data.ks[max_ks_index])
# 顯示圖例
plt.legend()
# 顯示圖形
plt.show()
# 調(diào)用自定義函數(shù)磅叛,繪制K-S曲線
plot_ks(y_test = y_test, y_score = y_score, positive_flag = 1)
中間的虛線表示在40%的分位點(diǎn),計(jì)算最大差為0.71萨赁,即KS值弊琴,大于0.4,模型擬合效果不錯(cuò)杖爽。