基于集成算法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)预测数据中缺失该怎么处理:

 

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