pythonによる顧客流出アラートモデル(上)の構築-データ処理部

41474 ワード

pythonによる顧客流出アラートモデル(上)の構築-データ処理部
前言
多くの文章を読んで大いに利益を得て、私もここで自分の運用したことを総括してみて、みんなと一緒に交流して勉強することを目的として、各位の大物によろしくお願いします.次に本題に入ります.データは商業銀行の顧客データで、データセットを訓練セットとテスト機に分けます.1、顧客流失警報モデルを構築します(bad_goodは解釈される変数です).2、関連変数によって顧客画像システムを構築する;3、二つのモデルに基づいて、流出したお客様の対応策を提出します.データ処理とモデル構築の二つの部分から展開します.
データしょり
データ探索
一、データを読み込む
import pandas as pd
data=pd.read_csv('train.csv',sep=',',index_col=None)

二、データ探索1、欠落値があるかどうか
data.isnull().any().any()#  data       
v_null=data.isnull().any()#          
v_null=v_null[v_null==True].reset_index()#         
v_null=data[v_null['index']]#      
v_isnull().sum()
#         fillna    
data['   '].fillna(data['   '].mean())

2、論理的な重複データ、すなわち重複サンプルがあるかどうかを確認する
len(np.unique(data['   ']))#           ,        
sta=data['   '].value_counts()#      
sta=sta[sta>1]#      ,     

3、離散と連続データ分布の表示
dis=data[    ].apply(pd.value_counts)#        
con=data[    ].describe()

このデータの中で性別がXのサンプルがあることを見て、後続の処理が必要で、同時に大部分のFLAG変数の属性が統一されていないで、N、Y、0、1が共存する情況が存在して、後続にそれを統一する必要がある4、変数の整理と派生変数はまず変数のレベルから元の628個の変数に対して整理をして、離散変数、取引金額とペン数の最大の最小変数を得て、当期3ヶ月6ヶ月の変数とその他の変数が存在する1)離散変数:まず属性の統一を行い、mapを使用してそれを0または1にマッピングし、その中の基金に対して、すべての基金標識を合併し、1種類が1であれば、最終的に1であれば、その中の国債に対して、すべての国債の標識を合併し、1種類が1であれば、最終的に1であれば、顧客カードに対して、プラチナ、ダイヤモンドおよび無限カードはVIPとして、残りは非VIP 2)最大最小変数:最小変数を削除する.ごく少数のサンプルにしか値がなく、値も大きくないため、研究意義のない変数は1つの変数に統合することができ、それを最大にして、新しい派生変数が転入した金額が最大で異なるルートの金額が最大であることを示す.3ヶ月6ヶ月の変数:まず、安定した測定指標として6ヶ月の変数のみを保持することを考慮した新しい派生変数の活性度:今期を3ヶ月の比率で割ったものと、3ヶ月の比率で割ったものを6ヶ月の比率で割ったものを7:3の重みで総合的に得たものと、新しい派生変数転入転入転出比率の新しい派生変数の貸借対照比の新しい派生変数の集中度を得るものとする.異なるルートまたは製品の最大値および最大値に対応する活躍度:取引金額とペン数、投資金額、転入転入転入金額とペン数についてそれぞれ構成する4)その他の変数:6ヶ月のデータがないものもあるが、他の変数から6ヶ月のデータを算出することができるため、その他のうち当期と3ヶ月のデータを削除し、また、業務に影響を及ぼさない変数を削除することもできます5)データ量が多い場合は、1回の操作を完了するたびにデータを保存することも考えられます.そうしないと、実行するたびに多くの時間がかかります
#                      
all_names=data.columns.values.tolist()                                              #      
all_names.remove('bad_good')
remove_variable=[]
data['GENDER']=data['GENDER'].map({1:'1',2:'2','2':'2','1':'1','X':'X'})
for i in range(len(all_names)):                                                      #         
    if len(np.unique(data[all_names[i]]))==1:
        remove_variable.append(all_names[i])
data=data.drop(remove_variable,axis=1,inplace=False)
all_names=list(set(all_names).difference(set(remove_variable)))
del remove_variable

discrete_variable=['OPEN_ORG_NUM','IDF_TYP_CD','GENDER']                             #      
for i in range(len(all_names)):                                                      #       
    if all_names[i].upper().endswith('FLAG'):
        discrete_variable.append(all_names[i])
IND_variable=[]
for i in range(len(all_names)):                                                      #           
    if all_names[i].upper().endswith('IND'):
        IND_variable.append(all_names[i])
data_ind=data[IND_variable]
data=data.drop(IND_variable,axis=1,inplace=False)
continuous_variable=list(set(all_names).difference(set(
                 discrete_variable)).difference(set(IND_variable)))           #      
sta_data=data[discrete_variable].apply(pd.value_counts)                            #      
con_data=data[continuous_variable].describe()
                         


5、値置換1)訓練集中男女性別比に基づきX値をランダムに置換する
sum1=data.groupby('GENDER').size()[0]                                               #      ,     
sum2=data.groupby('GENDER').size()[1]                                               #     sum1,   sum2
data_gender=data[data['GENDER']=='X'].reset_index()['index'].tolist()
for i in data_gender:                                                          
	random.seed(6)      #                                                          
    data.loc[i,'GENDER']=str(math.ceil(random.randint(1,sum1+sum2)/sum1))
data['GENDER']=train['GENDER'].map({'1':1,'2':2})
sta_data=data[discrete_variable].apply(pd.value_counts)   

2)以前のデータ探索で離散変数の中で属性の多い変数に対してベイズ平滑化を利用して流失率を得,人為的に与えられた区分限界を観察し,離散変数属性を結合し,属性の少ない変数を得た.
変換率(CTR)予測ベイズ平滑化https://blog.csdn.net/jinping_shi/article/details/78334362
def est(data):                                                                       #         
    datamean=sum(data.iloc[:,1]*data.iloc[:,3])/sum(data.iloc[:,1])
    datavar=sum(data.iloc[:,1]*pow(data.iloc[:,3]-datamean,2))/(sum(data.iloc[:,1])-1)
    a=datamean*(datamean*(1-datamean)/datavar-1)
    b=(1-datamean)*(datamean*(1-datamean)/datavar-1)
    return a,b

5.スクリーニング変数1)初期スクリーニング:すべてのサンプルの値が同じ変数を削除する2)離散変数をスクリーニングする(離散と離散関係):一般的にカード検査を使用するか、計算WOEとIVを使用するか、IVの大きさによって判断することができ、一般的に0.2未満の削除で、0.6より大きいものは変数によって特別に関連し、適切かどうかを考慮し、残りは保留することができる

#            
dis_chi2=pd.DataFrame({'name':discrete_variable,'p_value':chi2(train[discrete_variable],train.bad_good)[1]})             #  
dis_chi2=dis_chi2[dis_chi2.p_value<0.05].sort_index(by='p_value').reset_index().drop('index',axis=1,inplace=False)  #         p 

left_dis=dis_chi2.name.tolist()                                                      #     
dis_remove=list(set(discrete_variable).difference(set(left_dis)))                    #     
all_names=list(set(all_names).difference(set(dis_remove)))                           #    
data=data.drop(dis_remove,axis=1,inplace=False)
del dis_remove,discrete_variable

https://blog.csdn.net/sscc_learning/article/details/78591210
3)連続変数(連続と離散関係)を選別する:一般的に分散分析を使用して、離散変数属性の平均値に差異があるかどうかを見るが、分散分析は正規性、分散整合性及び独立性条件を満たす必要があり、先にKSで正規性及び分散整合性を検査してから分散分析を行うことができる.満たされていない場合は、マン・ホイットニーU検査を使用することを考慮します.(相関解析やMI相互情報を用いて変数間の相関度合いを考察することもできる)
#      
data0=data[data.bad_good==0]
data1=data[data.bad_good==1]
sel_con=pd.DataFrame({'name':continuous_variable,'ks0p_value':1,'ks1p_value':1,
                      'lp_value':1,'ap_value':1,'Up_value':1})
for i in range(len(continuous_variable)):                                            #     、    
    d0=data0[continuous_variable[i]]                                              #          
    d1=data1[continuous_variable[i]]                                              #    
    args=[d0,d1]
    sel_con.loc[i,'ks0p_value']=kstest(data0[continuous_variable[i]],'norm')[1]
    sel_con.loc[i,'ks1p_value']=kstest(data1[continuous_variable[i]],'norm')[1]
    sel_con.loc[i,'lp_value']=stats.levene(*args)[1]
    sel_con.loc[i,'ap_value']=anova_lm(ols(continuous_variable[i]+'~bad_good',data).fit()).iloc[0,4]
    sel_con.loc[i,'Up_value']=stats.mannwhitneyu(d0,d1)[1]
con_U=sel_con[sel_con.Up_value<0.05].sort_index(by='Up_value').reset_index()[['name','Up_value']]
left_con=con_U.name.tolist()  #                                                         

6.データの正規化または標準化は主に変数間の桁違いを解消するためであり、回帰および距離の計算が必要な問題に対して特に重要であり、その後のオーバーサンプリング方法の使用にも準備されている.主に正規化、標準化、または対数を取る方法がある.
#     
data_all=data.append(test).reset_index()
data_all=data_all.drop('index',axis=1,inplace=False)
data_all=pd.DataFrame(preprocessing.MinMaxScaler().fit_transform(data_all.values),columns=data_all.columns)
train=data_all.iloc[:len(data),:]
test=data_all.iloc[len(data):,:]
del data_all

7.サンプリング方法はオーバーサンプリング、アンダーサンプリング、ダブルサンプリングの方法でアンバランスデータを処理することができ、最も一般的なのは簡単に元のサンプルを少類再サンプリングまたは多類ランダム削除する方法である.オーバーサンプリングの比較的新しい方法は、SMOTE法によって大量の少数のサンプルを人工的に合成することができる.
#   ,     
x_train,y_train=SMOTE(random_state=666,kind='borderline2').fit_sample(train.iloc[:,1:],train.bad_good)
y_train=list(map(int,y_train))
#x_train=train.iloc[:,1:].values
#y_train=train.bad_good.values
x_test=test.iloc[:,1:].values
y_test=test.bad_good.values