基於集成算法GBDT和RandomForest的投票組合模型的異常檢測----python數據分析與數據運營

本文基於python數據分析與數據化運營-第六章學習筆記,數據與大部分代碼均來源數據該書;

棘突某企業的訂單數據(含異常訂單),建立分類模型,實現異常訂單檢測
案例數據:13*134190,有異常值和缺失值;字段:order_id,order_date,order_time,商品類別,商品渠道,pro_id,pro_brand,total_money,total_quantity,order_source,pay_type,use_id,city,目標變量

import numpy as np
import pandas as pd
from sklearn.ensemble import VotingClassifier,GradientBoostingClassifier,RandomForestClassifier
from sklearn.model_selection import StratifiedKFold,cross_val_score
#from sklearn.preprocessing import OrdinalEncoder
#由於版本問題,無法導入OrdinalEncoder,導入LabelEncoder可以實現同樣效果,但是一次只能處理一列數據
from sklearn.preprocessing import LabelEncoder
#讀取數據
raw_data = pd.read_table(r"D:\data_analysis_and_data_operation_with_python\python_book_v2\chapter6\abnormal_orders.txt",delimiter=",")
#預覽數據,在spyder編輯器中,多列數據預覽無法實現(不能顯示全部列)
raw_data.head()
#從時間字段中提取月,周,日,小時,分鐘等
def datetime_exp(data):
    #將日期和時間數據拓展出其他屬性,例如星期幾,周幾,小時,分鐘
    data_set = [pd.datetime.strptime(dates, "%Y-%m-%d") for dates in data["order_date"]]
    data["weekday_data"] = [data.weekday() for data in data_set]
    data["daysinmonth_data"] = [data.day for data in data_set]
    data["month_data"] = [data.month for data in data_set]
    time_set = [pd.datetime.strptime(times, "%H:%M:%S") for times in data['order_time']]
    data["second_data"] = [data.second for data in time_set]
    data["minute_data"] = [data.minute for data in time_set]
    data["hour_data"] = [data.hour for data in time_set]
    return data.drop(['order_date','order_time'], axis=1)
raw_data = datetime_exp(raw_data)
#查看各列是否有異常值,並將每列異常值個數打印出來
def get_null_count(raw_data):
    columns_isnull = raw_data.isnull().any(axis=0)
    columns_isnull_count = []
    for name in list(raw_data.columns):
        if columns_isnull[name]==True:
            columns_isnull_count.append([name,sum(list(raw_data.isnull()[name]))])
    return columns_isnull_count
get_null_count(raw_data)
#結果如下[['cat', 1390], ['pro_brand', 772], ['total_money', 1], ['city', 2]]
#在本案例中,直接刪除異常值
drop_na_set = raw_data.dropna()#刪除缺失,缺失值處理依據實際情況而定
#刪除訂單編號等無意義數據
drop_na_set = drop_na_set.drop(['order_id'],axis=1)
#將分類屬性轉化爲(分類)數值屬性
convert_cols = ['cat', 'attribution', 'pro_id', 'pro_brand', 'order_source', 'pay_type', 'user_id', 'city']
enc = LabelEncoder()
#逐列轉換數據
for name in convert_cols:
    drop_na_set[name] = enc.fit_transform(drop_na_set[name])
#可以根據分類屬性對目標變量的影響,對分類變量進行編碼;

 

#分割數據,訓練集:測試集=7:3,分割時按照數據順序進行分割,需要保證數據是隨機分佈的
X_raw,y_raw = drop_na_set.drop(["abnormal_label"],axis=1), drop_na_set["abnormal_label"]
X_train,X_test = X_raw.iloc[:num,:],X_raw.iloc[num:,:]
y_train,y_test = y_raw[:num], y_raw[num:]
#樣本均衡,過抽樣處理
#由於環境問題,無法安裝該庫,因此沒有進行樣本均衡,但是模型效果相差不大,主要是因爲樣本不均衡問題並#不嚴重
#model_smote = SMOTE()
#x_smote_resampled,y_smote_resampled = model_smote.fit_sample(X_train,y_train)
#模型訓練,交叉檢驗
model_rf = RandomForestClassifier(max_features=0.8,random_state=0)
model_gdbc = GradientBoostingClassifier(max_features = 0.8,random_state=0)
estimators = [('randomforest', model_rf),('gradientboosting',model_gdbc)] #建立組合評估器列表
model_vot = VotingClassifier(estimators=estimators,voting="soft",weights=[0.9,1.2],n_jobs=-1)
cv = StratifiedKFold(5, random_state=2)
cv_score = cross_val_score(model_gdbc,X_train,y_train,cv=cv)
#cv_score ---array([0.7318018 , 0.79157476, 0.84306236, 0.80888841, 0.74468658])
model_vot.score(X_train,y_train)
#投票模型得分達到0.92,效果比單一模型好

 

#新數據集做預測
X_new = pd.read_csv(r"D:\data_analysis_and_data_operation_with_python\python_book_v2\chapter6\new_abnormal_orders.csv")
X_new_drop = X_new.drop(['order_id'],axis=1)
for name in convert_cols:
    X_new_drop[name] = enc.fit_transform(X_new_drop[name])
X_new_drop = datetime_exp(X_new_drop)

總結:

案例實際應用:

1)對異常訂單的主要特徵,品類集中度,重點客戶等進行分析,可以將異常訂單的聯繫人加入黑名單;

2)訂單的實時檢測,檢測出異常訂單後,交由審覈部門進一步審覈;將訓練過程與預測過程分離;訓練階段做增量更新,不必每次都運行所有數據

案例注意點:

1)耗時,5折交叉檢驗裏有四個集成方法,如果實踐中更加註重效率,那麼可以考慮其他方法

2)輸入特徵變量,在本案例中,pro_id,use_id放到模型中,一般來說,這種唯一ID很少用到模型中,但是在本案例中,一個用戶可能有多個訂單,且可能有大量異常案例,因此有必要加入到模型中,實際上也提高了模型的準確率;

3)分類型數據轉換爲數值型數據,分類的類別應該是固定的,若在預測中出現了新的類別,會出現錯誤

4)預測數據中缺失該怎麼處理:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章