1. 簡介
1.1 定義
- 分類算法通過對已知類别訓練集的計算和分析,從中發現類别規則并預測新資料的類别。
1.2 應用場景
- 分類算法是解決分類問題的方法,是資料挖掘、機器學習和模式識别中一個重要的研究領域。
- 分類的主要用途和場景是“預測”,基于已有的樣本預測新樣本的所屬類别,例如信用評級、風險等級、欺詐預測等。 分類算法也可以用于知識抽取,通過模型找到潛在的規律,幫助業務得到可執行的規則。
1.3 地位
- 分類和回歸是解決實際營運問題中非常重要的兩種分析和挖掘方法。
1.4 分類
- 常用的分類算法包括樸素貝葉斯、邏輯回歸、決策樹、随機森林、支援向量機等。
2. 應用
2.1 簡介
案例 電信客戶流失預測
- AT&T資料,使用者個人,通話,上網等資訊資料
- 充分利用資料預測客戶的流失情況
- 幫助挽留使用者,保證使用者基數和活躍程度
2.2 資料說明
- CustomerID 客戶ID
- Gender 性别
- partneratt 配偶是否也為att使用者
- dependents_att 家人是否也是att使用者
- landline 是否使用att固話服務
- internet_att/internet_other 是否使用att的網際網路服務
- Paymentbank/creditcard/electroinc 付款方式
- MonthlyCharges 每月話費
- TotalCharges 累計話費
- Contract_month/1year 使用者使用月度/年度合約
- StreamingTv/streamingMovies 是否使用線上視訊或者電影app
- Churn 客戶轉化的flag
2.3 處理流程
- 分析流程:資料概況分析->單變量分析->相關性分析與可視化->回歸模型
- 資料概況分析
- 資料行/列數量
- 缺失值分布
- 單變量分析
- 數字型變量的描述名額(平均值,最大最小值,标準差)
- 類别型變量(多少個分類,各自占比)
- 正負樣本占比
- 相關性分析與可視化
- 按類别交叉對比
- 變量之間的相關性分析
- 散點圖/熱力圖
- 邏輯回歸分析
- 模型建立
- 模型評估與優化
2.4 實作
步驟
1 加載資料,檢視churn.info()
2 對churn列和gender列進行onehot編碼
3 churn的onehot編碼中churn_yes作為标簽列,churn_no丢棄
gender_yes gender_no都保留
**4 churn.flag.value_counts() churn.flag.value_counts(1)檢視正負樣本分布** 正負樣本是人為定義的,關注哪個類别則定義該類别為正樣本
5 按照flag分組,計算平均值,檢視相關特征
6 圍繞flag變量,分析其他變量與flag的相關關系
7 選擇相關性比較高的作為特征
8 構模組化型,訓練評估
9 如果評估結果不理想,則重新選擇特征重新訓練
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
churn=pd.read_csv('churn.csv')
churn.info()
RangeIndex: 7043 entries, 0 to 7042
Data columns (total 16 columns):
Churn 7043 non-null object
gender 7043 non-null object
Partner_att 7043 non-null int64
Dependents_att 7043 non-null int64
landline 7043 non-null int64
internet_att 7043 non-null int64
internet_other 7043 non-null int64
StreamingTV 7043 non-null int64
StreamingMovies 7043 non-null int64
Contract_Month 7043 non-null int64
Contract_1YR 7043 non-null int64
PaymentBank 7043 non-null int64
PaymentCreditcard 7043 non-null int64
PaymentElectronic 7043 non-null int64
MonthlyCharges 7043 non-null float64
TotalCharges 7043 non-null float64
dtypes: float64(2), int64(12), object(2)
memory usage: 880.5+ KB
#預測目标是churn,是類别型變量 gender也是類别型變量 需要對類别型變量進行處理
churn.head()
Churn gender Partner_att Dependents_att landline internet_att
0 No Female 1 0 0 1
1 No Male 0 0 1 1
2 Yes Male 0 0 1 1
3 No Male 0 0 0 1
4 Yes Female 0 0 1 0
internet_other StreamingTV StreamingMovies Contract_Month Contract_1YR
0 0 0 0 1 0
1 0 0 0 0 1
2 0 0 0 1 0
3 0 0 0 0 1
4 1 0 0 1 0
PaymentBank PaymentCreditcard PaymentElectronic MonthlyCharges
0 0 0 1 29.85
1 0 0 0 56.95
2 0 0 0 53.85
3 1 0 0 42.30
4 0 0 1 70.70
TotalCharges
0 29.85
1 1889.50
2 108.15
3 1840.75
4 151.65
#需要把churn和gender轉變為數字型變量,使用get_dummies
churn=pd.get_dummies(churn)
churn.head()
Churn_No Churn_Yes gender_Female gender_Male
0 1 0 1 0
1 1 0 0 1
2 0 1 0 1
3 1 0 0 1
4 0 1 1 0
#資料整理,将churn_yes保留,将female保留,drop不需要的資料
churn.drop(['Churn_No','gender_Male'],axis=1,inplace=True)
#變量大小寫不規則,統一變成小寫
churn.columns=churn.columns.str.lower()
churn.head()
churn_yes gender_female
0 0 1
1 0 0
2 1 0
3 0 0
4 1 1
#将churn_yes重命名,友善後續的變量編寫
churn=churn.rename(columns={'churn_yes':'flag'})
#二分類模型,分析flag 1和0的占比
churn.flag.value_counts()
0 5174
1 1869
Name: flag, dtype: int64
churn.flag.value_counts(1)
0 0.73463
1 0.26537
Name: flag, dtype: float64
summary=churn.groupby('flag')
summary.mean()
partner_att dependents_att landline internet_att internet_other
flag
0 0.528218 0.344801 0.901044 0.379204 0.347700
1 0.357945 0.174425 0.909042 0.245586 0.693954
streamingtv streamingmovies contract_month contract_1yr paymentbank
flag
0 0.365868 0.369927 0.429068 0.252609 0.248550
1 0.435527 0.437667 0.885500 0.088818 0.138042
paymentcreditcard paymentelectronic monthlycharges totalcharges
flag
0 0.249324 0.250097 61.265124 2545.918081
1 0.124131 0.573034 74.441332 1528.514714
gender_female
flag
0 0.492656
1 0.502408
- 觀察flag在0和1的情況下,所有自變量的差别 internet_other變量,在0的分組中,均值是0.35,在1的分組中,均值是0.69。資料顯示如果使用别的公司的網際網路,使用者流失的機率就越高
sns.countplot(y='contract_month',hue='flag',data=churn)
- 結論:contract_month為1的客戶流失的機率更高,即與非按月付費客戶相比,按月付費客戶流失比例高
- 相關性分析
#圍繞flag變量,分析其他變量與flag的相關關系
churn.corr()[['flag']].sort_values('flag',ascending=False)
flag
flag 1.000000
contract_month 0.405103
internet_other 0.308020
paymentelectronic 0.301919
monthlycharges 0.193356
streamingtv 0.063228
streamingmovies 0.061382
landline 0.011942
gender_female 0.008612
paymentbank -0.117937
internet_att -0.124214
paymentcreditcard -0.134302
partner_att -0.150448
dependents_att -0.164221
contract_1yr -0.177820
totalcharges -0.198175
# contract_month與internet_other與flag相關性高
- 邏輯回歸模型
#設定因變量與自變量, y 是 flag, x 根據剛才的相關分析挑選contract_month,internet_other與streamingtv
#自變量可以分為幾類,partner/dependents,internet,streaming,contract,payment,charges,後續大家可以自己挑選進行模組化
y=churn['flag']
x=churn[['contract_month','internet_other','streamingtv']]
#模型優化,streamingtv調整為paymentelectronic
y=churn['flag']
x=churn[['contract_month','internet_other','paymentelectronic']]
#調用sklearn子產品,随機抽取訓練集與測試集
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3,random_state=100)
#模型優化,測試集與訓練集對半分,第三次也跑這裡
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.5,random_state=100)
#使用sklearn
from sklearn import linear_model
lr=linear_model.LogisticRegression()
lr.fit(x_train,y_train)
"""
LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
verbose=0, warm_start=False)
"""
- 模型的截距與系數
#第一次
lr.intercept_
lr.coef_
#array([-3.21761938])
#array([[2.19790192, 1.14360005, 0.23641705]])
#第二次,測試集與訓練集對半分
lr.intercept_
array([-3.26144359])
array([[2.23886897, 1.09248895, 0.32579547]])
#第三次,變量調整
array([-3.18770265])
array([[2.0019671 , 1.02830763, 0.62165925]])
- 模型的評估
y_pred_train=lr.predict(x_train)
y_pred_test=lr.predict(x_test)
import sklearn.metrics as metrics
metrics.accuracy_score(y_train,y_pred_train)
from sklearn.metrics import roc_curve,auc
fpr,tpr,threshold=roc_curve(y_train,y_pred_train)
roc_auc=auc(fpr,tpr)
- 用分類分析來提煉規則、提取變量、處理缺失值
- 分類分析用于提煉應用規則 預測是分類分析的主要應用方向,但将分類用于提煉應用規則,為資料化營運提供規則支援也是其重點應用之一,這種應用相對于其他算法更加具有落地價值。常見的應用場景如下:
- 要針對沉默會員做會員重新激活,應該挑選具有什麼特征的會員?
- 商品A庫存積壓嚴重,現在要通過促銷活動清倉,選擇哪些類型的促銷活動更容易實作該目标?
- 網站需要大流量廣告位來滿足VIP商家的精準廣告投放,具有哪些特征的廣告位更符合VIP商家的客戶需求?
- 分類分析用于提煉應用規則 預測是分類分析的主要應用方向,但将分類用于提煉應用規則,為資料化營運提供規則支援也是其重點應用之一,這種應用相對于其他算法更加具有落地價值。常見的應用場景如下:
- 從分類算法中提煉特征規則,利用的是在建構算法過程中的分類規則
- 以決策樹為例,決策樹的分裂節點是表示局部最優值的顯著特征值,每個節點下的特征變量以及對應的值的組合構成了規則。
- 分類分析用于提取變量特征
- 具體實作思路是:擷取原始資料集并對資料做預處理,将預處理的資料集放到分類算法中進行訓練,然後從算法模型中提取特征權重資訊。
- 分類分析用于處理缺失值
3. 聚類和分類算法的差別
- 學習方式不同聚類是一種非監督式學習算法,而分類是監督式學習算法。
- 對源資料集要求不同,有無目标值
- 應用場景不同
- 聚類一般應用于資料探索性分析、資料降維、資料壓縮等探索性、過程性分析和處理
- 分類更多地用于預測性分析和使用。
- 解讀結果不同。聚類算法的結果是将不同的資料集按照各自的典型特征分成不同類别,不同人對聚類的結果解讀可能不同;而分類的結果卻是一個固定值(例如高、中、低、是、否等),不存在不同解讀的情況。
- 模型評估名額不同
- 聚類分析沒有所謂的“準确”與否,以及多麼準确的相關度量,更多的是基于距離的度量。如果是對帶有标簽的資料集做聚類則可以做相似度、完整度等方面的評估
- 而分類模型的名額例如準确率、混淆矩陣、提升率等都有明顯的好與壞、提升程度等評估名額。例如準确率、混淆矩陣、提升率等都有明顯的好與壞、提升程度等評估名額。
- 假如原始資料集帶有類别标簽,那麼選擇分類或聚類算法都可以(标簽列資料并不是一定要使用)。假如原始資料集不帶有類别标簽,那麼隻能選擇使用聚類算法。
- 有關分類和聚類的應用示例
- 假如現在公司要對某新會員做促銷活動,例如推薦商品、提供個性化資訊、推薦最感興趣的熱榜等,并盡量提供該使用者感興趣的内容。
- 分類:基于現有的會員及其特定類别标簽(可選擇有代表性或與實際營運場景最相關的類别标簽)做分類模型訓練,将該新使用者的資料作為新的樣本輸入模型,預測得到該使用者所屬的目标類别。接着計算該類别下使用者最經常購買的商品、經常浏覽的資訊等,并給出推薦内容。
- 聚類:将新的會員和現有的會員作為一個整體做聚類分析,然後獲得該會員所屬的聚類類别,進而提取其所在類别下其他會員的經常購買商品、經常浏覽資訊等,并給出推薦内容。
4. 分類分析算法選擇
- 文本分類:樸素貝葉斯,例如電子郵件中垃圾郵件的識别。
- 訓練集較小,選擇高偏差且低方差的分類算法:樸素貝葉斯、支援向量機(不容易過拟合)
- 算法模型的計算時間短和模型易用性,不要選支援向量機、人工神經網絡
- 重視算法的準确率:支援向量機或GBDT、XGBoost等基于Boosting的內建方法
- 注重效果的穩定性或模型魯棒性,那麼應選擇随機森林、組合投票模型等基于Bagging的內建方法。
- 想得到有關預測結果的機率資訊,基于預測機率做進一步的應用:邏輯回歸
- 擔心離群點或資料不可分并且需要清晰的決策規則:決策樹
5. 分類評估
- 準确率:(對不對)
- (TP+TN)/(TP+TN+FN+FP)
- 精确率 – 查的準不準
- TP/(TP+FP)
- 召回率 – 查的全不全
- TP/(TP+FN)
- F1-score
- 反映模型的穩健性
- 不同的場景關注的名額不一樣
5…1 混淆矩陣
在分類任務下,預測結果(Predicted Condition)與正确标記(True Condition)之間存在四種不同的組合,構成混淆矩陣(适用于多分類)
TP True positive
FN False nagative
FP False positive
TN True negative
5.2. 精确率/查準率
- 精确率(Precision):預測結果為正例樣本中真實為正例的比例
- TP/(TP+FP)
5.3. 召回率/查全率
- 召回率(Recall):真實為正例的樣本中預測結果為正例的比例(查得全,對正樣本的區分能力)
- TP/(TP+FN)
5.4. F1-score
反映了模型的穩健性
5.5 ROC曲線與AUC名額
1. TPR與FPR
- 真陽性率
- 所有真實類别為1的樣本中,預測類别為1的比例
- 假陽性率
- 所有真實類别為0的樣本中,預測類别為1的比例
2. ROC曲線
多次調整門檻值得到若幹組TPR FPR的值,把這些值在同一個坐标系中表示出來,就得到了ROC曲線
最極端,FPR=0,TPR=1,
FPR=0時,即FP=0;TPR=1時,即FN=0,就是所有預測錯了的樣本都為0,也就是所有的樣本預測結果都是正确的
此時對應的曲線下面積是1,如果roc曲線和對角線重合,則面積是0.5,此時模型的預測結果和瞎猜是一樣的
AUC名額,area under curve
AUC=1,完美分類器
0.5<AUC<1,優于随機猜測
from sklearn.metrics import roc_auc_score
- 通過tpr和fpr來進行圖形繪制,然後繪制之後,行成一個名額auc
- ROC曲線的橫軸就是FPRate,縱軸就是TPRate,當二者相等時,表示的意義則是:對于不論真實類别是1還是0的樣本,分類器預測為1的機率是相等的,此時AUC為0.5。
- 在一個二分類模型中,假設采用邏輯回歸分類器,其給出針對每個執行個體為正例的機率。
- 通過設定一個門檻值如0.6,機率大于等于0.6的為正例,小于0.6的為負例。對應的就可以算出一組(FPR,TPR),在平面中得到對應坐标點。
- 随着門檻值的逐漸減小,越來越多的執行個體被劃分為正例,但是這些正例中同樣也摻雜着真正的負執行個體,即TPR和FPR會同時增大。
- 門檻值最大時,對應坐标點為(0,0),即把所有樣本都預測為負例,TP和FP都為0,對應的TPR和FPR為0;
- 門檻值最小時,對應坐标點(1,1),即把所有樣本都預測為正例,FN和TN都為0,對應的TPR和FPR為1。
3. AUC名額
- 越接近1,效果越好
- 越接近0,效果越差
- 越接近0.5,效果就是胡說
- AUC的機率意義是随機取一對正負樣本,正樣本得分大于負樣本得分的機率
- AUC的範圍在[0, 1]之間,并且越接近1越好,越接近0.5屬于随機猜測
- AUC=1,完美分類器,采用這個預測模型時,不管設定什麼門檻值都能得出完美預測。絕大多數預測的場合,不存在完美分類器。
- 0.5<AUC<1,優于随機猜測。這個分類器(模型)妥善設定門檻值的話,能有預測價值。
4. API
from sklearn.metrics import roc_auc_score
sklearn.metrics.roc_auc_score(y_true, y_score)
- 計算ROC曲線面積,即AUC值
- y_true:每個樣本的真實類别,必須為0(反例),1(正例)标記
- y_score:預測得分,可以是正例的估計機率、置信值或者分類器方法的傳回值
# 0.5~1之間,越接近于1約好
y_test = np.where(y_test > 2.5, 1, 0)
print("AUC名額:", roc_auc_score(y_test, y_predict)
- AUC隻能用來評價二分類
- AUC非常适合評價樣本不平衡中的分類器性能
6. 分類評估報告api
# y_true:真實目标值
# y_pred:估計器預測目标值
# labels:指定類别對應的數字
# target_names:目标類别名稱
# return:每個類别精确率與召回率
sklearn.metrics.classification_report(y_true, y_pred, labels=[], target_names=None )
ret = classification_report(y_test, y_predict, labels=(2,4), target_names=("良性", "惡性"))
print(ret)
樣本不均衡下的評估問題: 假設這樣一個情況,如果99個樣本癌症,1個樣本非癌症,不管怎樣全都預測正例(預設癌症為正例),準确率就為99%但是這樣效果并不好